Mercurial > pidgin
changeset 30527:f01d73b4452e
propagate from branch 'im.pidgin.pidgin' (head a9876c2b74baddb4b0fd99eede7daef1d346604b)
to branch 'im.pidgin.cpw.malu.xmpp.google_relay' (head 927cc5343bf914f4b65641b43aa1154154930d30)
author | Marcus Lundblad <ml@update.uu.se> |
---|---|
date | Wed, 10 Mar 2010 05:40:56 +0000 |
parents | 8648453adb22 (current diff) eb300dde8113 (diff) |
children | 356a8d472395 |
files | libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/jabber.h libpurple/protocols/msnp9/Makefile.am libpurple/protocols/msnp9/Makefile.mingw libpurple/protocols/msnp9/cmdproc.c libpurple/protocols/msnp9/cmdproc.h libpurple/protocols/msnp9/command.c libpurple/protocols/msnp9/command.h libpurple/protocols/msnp9/dialog.c libpurple/protocols/msnp9/dialog.h libpurple/protocols/msnp9/directconn.c libpurple/protocols/msnp9/directconn.h libpurple/protocols/msnp9/error.c libpurple/protocols/msnp9/error.h libpurple/protocols/msnp9/group.c libpurple/protocols/msnp9/group.h libpurple/protocols/msnp9/history.c libpurple/protocols/msnp9/history.h libpurple/protocols/msnp9/httpconn.c libpurple/protocols/msnp9/httpconn.h libpurple/protocols/msnp9/msg.c libpurple/protocols/msnp9/msg.h libpurple/protocols/msnp9/msn-utils.c libpurple/protocols/msnp9/msn-utils.h libpurple/protocols/msnp9/msn.c libpurple/protocols/msnp9/msn.h libpurple/protocols/msnp9/nexus.c libpurple/protocols/msnp9/nexus.h libpurple/protocols/msnp9/notification.c libpurple/protocols/msnp9/notification.h libpurple/protocols/msnp9/object.c libpurple/protocols/msnp9/object.h libpurple/protocols/msnp9/page.c libpurple/protocols/msnp9/page.h libpurple/protocols/msnp9/servconn.c libpurple/protocols/msnp9/servconn.h libpurple/protocols/msnp9/session.c libpurple/protocols/msnp9/session.h libpurple/protocols/msnp9/slp.c libpurple/protocols/msnp9/slp.h libpurple/protocols/msnp9/slpcall.c libpurple/protocols/msnp9/slpcall.h libpurple/protocols/msnp9/slplink.c libpurple/protocols/msnp9/slplink.h libpurple/protocols/msnp9/slpmsg.c libpurple/protocols/msnp9/slpmsg.h libpurple/protocols/msnp9/slpsession.c libpurple/protocols/msnp9/slpsession.h libpurple/protocols/msnp9/state.c libpurple/protocols/msnp9/state.h libpurple/protocols/msnp9/switchboard.c libpurple/protocols/msnp9/switchboard.h libpurple/protocols/msnp9/sync.c libpurple/protocols/msnp9/sync.h libpurple/protocols/msnp9/table.c libpurple/protocols/msnp9/table.h libpurple/protocols/msnp9/transaction.c libpurple/protocols/msnp9/transaction.h libpurple/protocols/msnp9/user.c libpurple/protocols/msnp9/user.h libpurple/protocols/msnp9/userlist.c libpurple/protocols/msnp9/userlist.h |
diffstat | 71 files changed, 828 insertions(+), 19085 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Tue Mar 09 21:41:41 2010 +0000 +++ b/ChangeLog Wed Mar 10 05:40:56 2010 +0000 @@ -27,6 +27,7 @@ Gadu-Gadu: * Updated our bundled libgadu to 1.9.0-rc2 (many thanks to Krzysztof Klinikowski for the work and testing put in here!) + * Minimum requirement for external libgadu is now also 1.9.0-rc2. ICQ: * X-Status (Custom ICQ status icon) support (Andrew Ivanov, Tomáš Kebert,
--- a/configure.ac Tue Mar 09 21:41:41 2010 +0000 +++ b/configure.ac Wed Mar 10 05:40:56 2010 +0000 @@ -72,8 +72,8 @@ ]) fi -AC_CANONICAL_SYSTEM -AM_CONFIG_HEADER(config.h) +AC_CANONICAL_HOST +AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([1.9 -Wno-portability dist-bzip2]) PURPLE_MAJOR_VERSION=purple_major_version @@ -152,7 +152,7 @@ if test x$MSGFMT = xno -o x$MSGFMT$GMSGFMT$INTLTOOL_MSGFMT = x then - AC_ERROR([ + AC_MSG_ERROR([ The msgfmt command is required to build libpurple. If it is installed on your system, ensure that it is in your path. If it is not, install @@ -168,9 +168,6 @@ ]) fi -dnl we don't use autobreak on cygwin!! -dnl AC_CYGWIN - dnl Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT @@ -198,11 +195,11 @@ dnl Check for inet_aton AC_CHECK_FUNC(inet_aton, , [AC_CHECK_LIB(resolv, inet_aton, , - [AC_ERROR(inet_aton not found)])]) + [AC_MSG_ERROR([inet_aton not found])])]) AC_CHECK_LIB(resolv, __res_query) AC_CHECK_LIB(nsl, gethostent) AC_CHECK_FUNC(socket, , - [AC_CHECK_LIB(socket, socket, , [AC_ERROR([socket not found])])]) + [AC_CHECK_LIB(socket, socket, , [AC_MSG_ERROR([socket not found])])]) dnl If all goes well, by this point the previous two checks will have dnl pulled in -lsocket and -lnsl if we need them. AC_CHECK_FUNC(getaddrinfo, @@ -214,19 +211,18 @@ AC_CHECK_FUNCS(getifaddrs) dnl Check for socklen_t (in Unix98) AC_MSG_CHECKING(for socklen_t) -AC_TRY_COMPILE([ +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> #include <sys/socket.h> socklen_t x; -], [], -[ +]], [[]])], [ AC_MSG_RESULT(yes) ], [ - AC_TRY_COMPILE([ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> #include <sys/socket.h> int accept(int, struct sockaddr *, size_t *); - ], [], [ + ]], [[]])], [ AC_MSG_RESULT(size_t) AC_DEFINE(socklen_t, size_t, [socklen_t size]) ], [ @@ -249,7 +245,7 @@ AC_CHECK_FUNC(dlopen, LIBDL="", [AC_CHECK_LIB(dl, dlopen, LIBDL="-ldl")]) AC_MSG_CHECKING(for fileno()) -AC_TRY_RUN([ +AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include <stdio.h> int main(int argc, char *argv[]) @@ -260,7 +256,7 @@ return !(fd > 0); } -], [ +]])], [ AC_MSG_RESULT(yes) AC_DEFINE([HAVE_FILENO], [1], [Define to 1 if your stdio has int fileno(FILE *).]) @@ -273,7 +269,7 @@ ]) AC_MSG_CHECKING(for the %z format string in strftime()) -AC_TRY_RUN([ +AC_RUN_IFELSE([AC_LANG_SOURCE([[ #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif @@ -297,7 +293,7 @@ (buf[4] >= '0' && buf[4] <= '9') ); } -], [ +]])], [ AC_MSG_RESULT(yes) AC_DEFINE([HAVE_STRFTIME_Z_FORMAT], [1], [Define to 1 if you have a strftime() that supports the %z format string.]) @@ -307,8 +303,7 @@ # Fallback for Cross Compiling... # This will enable the compatibility code. AC_MSG_RESULT(no) -] -) +]) dnl ####################################################################### dnl # Check for GLib 2.12 (required) @@ -458,10 +453,10 @@ if test "x$XSS_LIBS" != "x"; then oldCPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $x_incpath_add" - AC_TRY_COMPILE([ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <X11/Xlib.h> #include <X11/extensions/scrnsaver.h> - ], [], [], [enable_screensaver=no]) + ]], [[]])], [], [enable_screensaver=no]) CPPFLAGS="$oldCPPFLAGS" else enable_screensaver=no @@ -648,14 +643,14 @@ f="$location/ncurses.h" AC_CHECK_HEADER($f,[ AC_MSG_CHECKING([if $f supports wide characters]) - AC_TRY_COMPILE([ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define _XOPEN_SOURCE_EXTENDED #include <$f> - ], [ + ]], [[ #ifndef get_wch # error get_wch not found! #endif - ], [ + ]])], [ dir=$location if test x"$dir" != x"." ; then GNT_CFLAGS="-I$dir/" @@ -997,10 +992,10 @@ CPPFLAGS_save="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $SILC_CFLAGS" AC_MSG_CHECKING(for silcmime.h) - AC_TRY_COMPILE([ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <silcincludes.h> #include <silcmime.h> - ], [], [ + ]], [[]])], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_SILCMIME_H, 1, [Define if we have silcmime.h]) ], [ @@ -1022,7 +1017,7 @@ gadu_manual_check="no" fi if test "x$gadu_manual_check" = "xno"; then - PKG_CHECK_MODULES(GADU, libgadu, [ + PKG_CHECK_MODULES(GADU, [libgadu >= 1.9.0-rc2], [ gadu_includes="yes" gadu_libs="yes" ], [ @@ -1049,14 +1044,33 @@ AC_MSG_CHECKING(for libgadu GPL compatibility) CPPFLAGS_save="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $GADU_CFLAGS" - AC_TRY_COMPILE([#include <libgadu.h>], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <libgadu.h>]], [[ #if defined(__GG_LIBGADU_HAVE_OPENSSL) || defined(GG_CONFIG_HAVE_OPENSSL) #error "libgadu is not compatible with the GPL when compiled with OpenSSL support." #endif - ], [ - AC_MSG_RESULT(yes) - AC_DEFINE([HAVE_LIBGADU], [1], - [Define to 1 if you have libgadu.]) + ]])], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <libgadu.h>]], [[ +#if GG_DEFAULT_PROTOCOL_VERSION < 0x2e +#error "Your libgadu version is too old. libpurple requires 1.9.0-rc2 or higher." +#endif + ]])], [ + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_LIBGADU], [1], + [Define to 1 if you have libgadu.]) + ], [ + AC_MSG_RESULT(no) + echo + echo + echo "Your supplied copy of libgadu is too old." + echo "Install version 1.9.0-rc2 or newer." + echo "Then rerun this ./configure" + echo + echo "Falling back to using our own copy of libgadu" + echo + GADU_LIBS="" + GADU_CFLAGS="" + gadu_libs=no + ]) ], [ AC_MSG_RESULT(no) echo @@ -1080,9 +1094,6 @@ AC_SUBST(GADU_LIBS) AC_SUBST(GADU_CFLAGS) -# change the next line to not make MSNP15 the default (s/disable/enable/; s/yes/no/;) -AC_ARG_ENABLE(msnp15,[AC_HELP_STRING([--disable-msnp15], [Disable the newer MSNP15 protocol])],enable_msnp15=$enableval,enable_msnp15=yes) - AC_ARG_ENABLE(distrib,,,enable_distrib=no) AM_CONDITIONAL(DISTRIB, test "x$enable_distrib" = "xyes") DYNAMIC_PRPLS=all @@ -1100,9 +1111,6 @@ if test "x$avahiincludes" != "xyes" -o "x$avahilibs" != "xyes"; then STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/bonjour//'` fi -if test "x$enable_msnp15" != "xyes" ; then - STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/msn/msnp9/'` -fi if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc/silc10/'` fi @@ -1133,8 +1141,6 @@ STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la" elif test "x$i" = "xsilc10"; then STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libsilcpurple.la" - elif test "x$i" = "xmsnp9"; then - STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libmsn.la" else STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la" fi @@ -1147,7 +1153,6 @@ irc) static_irc=yes ;; jabber) static_jabber=yes ;; msn) static_msn=yes ;; - msnp9) static_msn=yes ;; myspace) static_myspace=yes ;; mxit) static_mxit=yes ;; novell) static_novell=yes ;; @@ -1193,9 +1198,6 @@ if test "x$avahiincludes" != "xyes" -o "x$avahilibs" != "xyes"; then DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/bonjour//'` fi -if test "x$enable_msnp15" != "xyes" ; then - DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/msn/msnp9/'` -fi if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc/silc10/'` fi @@ -1210,7 +1212,6 @@ irc) dynamic_irc=yes ;; jabber) dynamic_jabber=yes ;; msn) dynamic_msn=yes ;; - msnp9) dynamic_msn=yes ;; myspace) dynamic_myspace=yes ;; mxit) dynamic_mxit=yes ;; novell) dynamic_novell=yes ;; @@ -1281,9 +1282,9 @@ orig_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $newflag" AC_MSG_CHECKING(for $newflag option to gcc) - AC_TRY_COMPILE([], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ int main() {return 0;} - ], [ + ]])], [ AC_MSG_RESULT(yes) CFLAGS="$orig_CFLAGS" DEBUG_CFLAGS="$DEBUG_CFLAGS $newflag" @@ -1295,7 +1296,7 @@ if test "x$enable_fortify" = "xyes"; then AC_MSG_CHECKING(for FORTIFY_SOURCE support) - AC_TRY_COMPILE([#include <features.h>], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <features.h>]], [[ int main() { #if !(__GNUC_PREREQ (4, 1) \ || (defined __GNUC_RH_RELEASE__ && __GNUC_PREREQ (4, 0)) \ @@ -1307,7 +1308,7 @@ #endif return 0; } - ], [ + ]])], [ AC_MSG_RESULT(yes) DEBUG_CFLAGS="$DEBUG_CFLAGS -Wp,-D_FORTIFY_SOURCE=2" ], [ @@ -1481,12 +1482,15 @@ PY_MAJOR=`$pythonpath -c 'import sys ; print sys.version[0:2]'` changequote([, ])dnl if test -f $PY_PREFIX/include/python$PY_VERSION/Python.h -a "$PY_MAJOR" = "2."; then + AC_MSG_RESULT() AC_CHECK_LIB(pthread, pthread_create, ) AC_CHECK_LIB(util, openpty, ) AC_CHECK_LIB(db, dbopen, ) PY_LIBS="-L$PY_EXEC_PREFIX/lib/python$PY_VERSION/config -lpython$PY_VERSION" PY_CFLAGS="-I$PY_PREFIX/include/python$PY_VERSION" AC_DEFINE(USE_PYTHON, [1], [Define if python headers are available.]) + dnl Because the above AC_CHECK_LIB get in the way... + AC_MSG_CHECKING(for Python compile flags) AC_MSG_RESULT(ok) else AC_MSG_RESULT([Can't find Python.h]) @@ -2144,6 +2148,7 @@ if test -f $dir/tclConfig.sh; then TCLCONFIG=$dir/tclConfig.sh AC_MSG_RESULT([yes ($TCLCONFIG)]) + break fi done if test "$TCLCONFIG" = "no"; then @@ -2169,8 +2174,8 @@ CPPFLAGS="$CPPFLAGS $TCL_INCLUDE_SPEC -I$TCL_PREFIX/include" oldLIBS=$LIBS LIBS="$LIBS $TCL_LIB_SPEC" - AC_TRY_LINK([#include <tcl.h>], - [Tcl_Interp *interp=NULL; Tcl_Init(interp)], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <tcl.h>]], + [[Tcl_Interp *interp=NULL; Tcl_Init(interp)]])], [AC_MSG_RESULT([yes]);enable_tcl=yes], [AC_MSG_RESULT([no]);enable_tcl=no]) CPPFLAGS="$oldCPPFLAGS" @@ -2214,6 +2219,7 @@ if test -f $dir/tkConfig.sh; then TKCONFIG=$dir/tkConfig.sh AC_MSG_RESULT([yes ($TKCONFIG)]) + break fi done if test "$TKCONFIG" = "no"; then @@ -2233,8 +2239,8 @@ CPPFLAGS="$CPPFLAGS $TCL_CFLAGS" oldLIBS=$LIBS LIBS="$LIBS $TCL_LIB_SPEC $TK_LIB_SPEC" - AC_TRY_LINK([#include <tk.h>], - [Tcl_Interp *interp=NULL; Tcl_Init(interp); Tk_Init(interp);], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <tk.h>]], + [[Tcl_Interp *interp=NULL; Tcl_Init(interp); Tk_Init(interp);]])], [AC_MSG_RESULT([yes]);enable_tk=yes], [AC_MSG_RESULT([no]);enable_tk=no]) CPPFLAGS="$oldCPPFLAGS" @@ -2286,7 +2292,7 @@ SASL_LIBS=-"lsasl2" ], [ AM_CONDITIONAL(USE_CYRUS_SASL, false) - AC_ERROR(Cyrus SASL library not found) + AC_MSG_ERROR([Cyrus SASL library not found]) ]) else AM_CONDITIONAL(USE_CYRUS_SASL, false) @@ -2319,7 +2325,7 @@ [KRB4_LIBS="-lkrb4 -ldes425 -lkrb5 -lk5crypto -lcom_err"], [AC_CHECK_LIB(krb, krb_rd_req, [KRB4_LIBS="-lkrb -ldes"], - [AC_ERROR(Kerberos 4 libraries not found)], + [AC_MSG_ERROR([Kerberos 4 libraries not found])], -ldes)], -ldes425 -lkrb5 -lk5crypto -lcom_err) orig_LIBS="$LIBS" @@ -2353,7 +2359,7 @@ LDFLAGS="$LDFLAGS $ZEPHYR_LDFLAGS" AC_CHECK_LIB(zephyr, ZInitialize, [ZEPHYR_LIBS="-lzephyr"], - [AC_ERROR(Zephyr libraries not found)], + [AC_MSG_ERROR([Zephyr libraries not found])], -lzephyr) orig_LIBS="$LIBS" LIBS="$orig_LIBS" @@ -2384,18 +2390,18 @@ AC_VAR_TIMEZONE_EXTERNALS AC_CACHE_CHECK(for tm_gmtoff in struct tm, ac_cv_struct_tm_gmtoff, - AC_TRY_COMPILE([ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <time.h> - ], [ + ]], [[ struct tm tm; tm.tm_gmtoff = 1; - ], ac_cv_struct_tm_gmtoff=yes, ac_cv_struct_tm_gmtoff=no)) + ]])], [ac_cv_struct_tm_gmtoff=yes], [ac_cv_struct_tm_gmtoff=no])) if test $ac_cv_struct_tm_gmtoff = yes; then AC_DEFINE(HAVE_TM_GMTOFF, 1, [Define if you have a tm_gmtoff member in struct tm]) fi AC_CACHE_CHECK([whether va_lists can be copied by value], ac_cv_va_val_copy,[ - AC_TRY_RUN([#include <stdarg.h> + AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdarg.h> #include <stdlib.h> void f (int i, ...) { va_list args1, args2; @@ -2408,7 +2414,7 @@ int main() { f (0, 42); return 0; - }], + }]])], [ac_cv_va_val_copy=yes], [ac_cv_va_val_copy=no], [ac_cv_va_val_copy=yes]) @@ -2506,7 +2512,7 @@ AM_CONDITIONAL(PURPLE_AVAILABLE, true) -AC_OUTPUT([Makefile +AC_CONFIG_FILES([Makefile Doxyfile doc/Makefile doc/pidgin.1 @@ -2552,7 +2558,6 @@ libpurple/protocols/irc/Makefile libpurple/protocols/jabber/Makefile libpurple/protocols/msn/Makefile - libpurple/protocols/msnp9/Makefile libpurple/protocols/myspace/Makefile libpurple/protocols/mxit/Makefile libpurple/protocols/novell/Makefile @@ -2579,6 +2584,7 @@ po/Makefile.in pidgin.spec ]) +AC_OUTPUT echo echo $PACKAGE $VERSION
--- a/libpurple/protocols/Makefile.am Tue Mar 09 21:41:41 2010 +0000 +++ b/libpurple/protocols/Makefile.am Wed Mar 10 05:40:56 2010 +0000 @@ -1,5 +1,5 @@ EXTRA_DIST = Makefile.mingw -DIST_SUBDIRS = bonjour gg irc jabber msn msnp9 myspace mxit novell null oscar qq sametime silc silc10 simple yahoo zephyr +DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar qq sametime silc silc10 simple yahoo zephyr SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS)
--- a/libpurple/protocols/jabber/bosh.c Tue Mar 09 21:41:41 2010 +0000 +++ b/libpurple/protocols/jabber/bosh.c Wed Mar 10 05:40:56 2010 +0000 @@ -521,7 +521,7 @@ } if (version) { - const char *dot = strstr(version, "."); + const char *dot = strchr(version, '.'); int major, minor = 0; purple_debug_info("jabber", "BOSH connection manager version %s\n", version);
--- a/libpurple/protocols/jabber/buddy.c Tue Mar 09 21:41:41 2010 +0000 +++ b/libpurple/protocols/jabber/buddy.c Wed Mar 10 05:40:56 2010 +0000 @@ -1824,7 +1824,8 @@ if(!jb) return m; - if (js->protocol_version == JABBER_PROTO_0_9 && jb != js->user_jb) { + if (js->protocol_version.major == 0 && js->protocol_version.minor == 9 && + jb != js->user_jb) { if(jb->invisible & JABBER_INVIS_BUDDY) { act = purple_menu_action_new(_("Un-hide From"), PURPLE_CALLBACK(jabber_buddy_make_visible),
--- a/libpurple/protocols/jabber/jabber.c Tue Mar 09 21:41:41 2010 +0000 +++ b/libpurple/protocols/jabber/jabber.c Wed Mar 10 05:40:56 2010 +0000 @@ -870,7 +870,8 @@ js->old_length = 0; js->keepalive_timeout = 0; /* Set the default protocol version to 1.0. Overridden in parser.c. */ - js->protocol_version = JABBER_PROTO_1_0; + js->protocol_version.major = 1; + js->protocol_version.minor = 0; js->sessions = NULL; js->stun_ip = NULL; js->stun_port = 0; @@ -3561,6 +3562,36 @@ const gchar *type = "pc"; /* default client type, if unknown or unspecified */ const gchar *ui_name = NULL; +#ifdef HAVE_CYRUS_SASL + /* We really really only want to do this once per process */ + static gboolean sasl_initialized = FALSE; +#ifdef _WIN32 + UINT old_error_mode; + gchar *sasldir; +#endif + int ret; +#endif + + /* XXX - If any other plugin wants SASL this won't be good ... */ +#ifdef HAVE_CYRUS_SASL + if (!sasl_initialized) { + sasl_initialized = TRUE; +#ifdef _WIN32 + sasldir = g_build_filename(wpurple_install_dir(), "sasl2", NULL); + sasl_set_path(SASL_PATH_TYPE_PLUGIN, sasldir); + g_free(sasldir); + /* Suppress error popups for failing to load sasl plugins */ + old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS); +#endif + if ((ret = sasl_client_init(NULL)) != SASL_OK) { + purple_debug_error("xmpp", "Error (%d) initializing SASL.\n", ret); + } +#ifdef _WIN32 + /* Restore the original error mode */ + SetErrorMode(old_error_mode); +#endif + } +#endif jabber_cmds = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, cmds_free_func); @@ -3628,6 +3659,7 @@ /* reverse order of unload_plugin */ jabber_iq_init(); + jabber_presence_init(); jabber_caps_init(); /* PEP things should be init via jabber_pep_init, not here */ jabber_pep_init();
--- a/libpurple/protocols/jabber/jabber.h Tue Mar 09 21:41:41 2010 +0000 +++ b/libpurple/protocols/jabber/jabber.h Wed Mar 10 05:40:56 2010 +0000 @@ -105,9 +105,9 @@ xmlParserCtxt *context; xmlnode *current; - enum { - JABBER_PROTO_0_9, - JABBER_PROTO_1_0 + struct { + guint8 major; + guint8 minor; } protocol_version; JabberSaslMech *auth_mech;
--- a/libpurple/protocols/jabber/libxmpp.c Tue Mar 09 21:41:41 2010 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Wed Mar 10 05:40:56 2010 +0000 @@ -249,13 +249,6 @@ static void init_plugin(PurplePlugin *plugin) { -#ifdef HAVE_CYRUS_SASL -#ifdef _WIN32 - UINT old_error_mode; - gchar *sasldir; -#endif - int ret; -#endif PurpleAccountUserSplit *split; PurpleAccountOption *option; @@ -315,24 +308,6 @@ purple_prefs_remove("/plugins/prpl/jabber"); - /* XXX - If any other plugin wants SASL this won't be good ... */ -#ifdef HAVE_CYRUS_SASL -#ifdef _WIN32 - sasldir = g_build_filename(wpurple_install_dir(), "sasl2", NULL); - sasl_set_path(SASL_PATH_TYPE_PLUGIN, sasldir); - g_free(sasldir); - /* Suppress error popups for failing to load sasl plugins */ - old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS); -#endif - if ((ret = sasl_client_init(NULL)) != SASL_OK) { - purple_debug_error("xmpp", "Error (%d) initializing SASL.\n", ret); - } -#ifdef _WIN32 - /* Restore the original error mode */ - SetErrorMode(old_error_mode); -#endif -#endif - purple_signal_connect(purple_get_core(), "uri-handler", plugin, PURPLE_CALLBACK(xmpp_uri_handler), NULL); }
--- a/libpurple/protocols/jabber/parser.c Tue Mar 09 21:41:41 2010 +0000 +++ b/libpurple/protocols/jabber/parser.c Wed Mar 10 05:40:56 2010 +0000 @@ -44,14 +44,28 @@ if(!element_name) { return; } else if(!xmlStrcmp(element_name, (xmlChar*) "stream")) { - js->protocol_version = JABBER_PROTO_0_9; + js->protocol_version.major = 0; + js->protocol_version.minor = 9; for(i=0; i < nb_attributes * 5; i += 5) { int attrib_len = attributes[i+4] - attributes[i+3]; char *attrib = g_strndup((gchar *)attributes[i+3], attrib_len); - if(!xmlStrcmp(attributes[i], (xmlChar*) "version") - && !strcmp(attrib, "1.0")) { - js->protocol_version = JABBER_PROTO_1_0; + if(!xmlStrcmp(attributes[i], (xmlChar*) "version")) { + const char *dot = strchr(attrib, '.'); + + js->protocol_version.major = atoi(attrib); + js->protocol_version.minor = dot ? atoi(dot + 1) : 0; + + if (js->protocol_version.major > 1) + /* TODO: Send <unsupported-version/> error */ + purple_connection_error_reason(js->gc, + PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, + _("XMPP Version Mismatch")); + + if (js->protocol_version.major == 0 && js->protocol_version.minor != 9) { + purple_debug_warning("jabber", "Treating version %s as 0.9 for backward " + "compatibility\n", attrib); + } g_free(attrib); } else if(!xmlStrcmp(attributes[i], (xmlChar*) "id")) { g_free(js->stream_id); @@ -255,7 +269,8 @@ } } - if (js->protocol_version == JABBER_PROTO_0_9 && !js->gc->disconnect_timeout && + if (js->protocol_version.major == 0 && js->protocol_version.minor == 9 && + !js->gc->disconnect_timeout && (js->state == JABBER_STREAM_INITIALIZING || js->state == JABBER_STREAM_INITIALIZING_ENCRYPTION)) { /*
--- a/libpurple/protocols/jabber/presence.c Tue Mar 09 21:41:41 2010 +0000 +++ b/libpurple/protocols/jabber/presence.c Wed Mar 10 05:40:56 2010 +0000 @@ -43,6 +43,37 @@ #include "usermood.h" #include "usertune.h" +static GHashTable *presence_handlers = NULL; + +static const struct { + const char *name; + JabberPresenceType type; +} jabber_presence_types[] = { + { "error", JABBER_PRESENCE_ERROR }, + { "probe", JABBER_PRESENCE_PROBE }, + { "unavailable", JABBER_PRESENCE_UNAVAILABLE }, + { "subscribe", JABBER_PRESENCE_SUBSCRIBE }, + { "subscribed", JABBER_PRESENCE_SUBSCRIBED }, + { "unsubscribe", JABBER_PRESENCE_UNSUBSCRIBE }, + { "unsubscribed", JABBER_PRESENCE_UNSUBSCRIBED } + /* { NULL, JABBER_PRESENCE_AVAILABLE } the default */ +}; + +static JabberPresenceType +str_to_presence_type(const char *type) +{ + int i; + + if (type == NULL) + return JABBER_PRESENCE_AVAILABLE; + + for (i = 0; i < G_N_ELEMENTS(jabber_presence_types); ++i) + if (g_str_equal(type, jabber_presence_types[i].name)) + return jabber_presence_types[i].type; + + purple_debug_warning("jabber", "Unknown presence type '%s'\n", type); + return JABBER_PRESENCE_AVAILABLE; +} static void chats_send_presence_foreach(gpointer key, gpointer val, gpointer user_data) @@ -476,7 +507,6 @@ purple_prpl_got_media_caps( purple_connection_get_account(userdata->js->gc), userdata->from); - if (info == NULL) goto out; @@ -508,573 +538,498 @@ g_free(userdata); } +gboolean +handle_presence_chat(JabberStream *js, JabberPresence *presence, xmlnode *packet) +{ + static int i = 1; + PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE; + JabberChat *chat = presence->chat; + + if (presence->state == JABBER_BUDDY_STATE_ERROR) { + char *title, *msg = jabber_parse_error(js, packet, NULL); + + if (!chat->conv) { + title = g_strdup_printf(_("Error joining chat %s"), presence->from); + purple_serv_got_join_chat_failed(js->gc, chat->components); + } else { + title = g_strdup_printf(_("Error in chat %s"), presence->from); + if (g_hash_table_size(chat->members) == 0) + serv_got_chat_left(js->gc, chat->id); + } + purple_notify_error(js->gc, title, title, msg); + g_free(title); + g_free(msg); + + if (g_hash_table_size(chat->members) == 0) + /* Only destroy the chat if the error happened while joining */ + jabber_chat_destroy(chat); + return FALSE; + } + + if (presence->type == JABBER_PRESENCE_AVAILABLE) { + const char *jid = NULL; + const char *affiliation = NULL; + const char *role = NULL; + gboolean is_our_resource = FALSE; /* Is the presence about us? */ + JabberBuddyResource *jbr; + + /* + * XEP-0045 mandates the presence to include a resource (which is + * treated as the chat nick). Some non-compliant servers allow + * joining without a nick. + */ + if (!presence->jid_from->resource) + return FALSE; + + if (presence->chat_info.item) { + jid = xmlnode_get_attrib(presence->chat_info.item, "jid"); + affiliation = xmlnode_get_attrib(presence->chat_info.item, "affiliation"); + role = xmlnode_get_attrib(presence->chat_info.item, "role"); + } + + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(110))) + is_our_resource = TRUE; + + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(201))) { + chat->config_dialog_type = PURPLE_REQUEST_ACTION; + chat->config_dialog_handle = + purple_request_action(js->gc, + _("Create New Room"), + _("Create New Room"), + _("You are creating a new room. Would" + " you like to configure it, or" + " accept the default settings?"), + /* Default Action */ 1, + purple_connection_get_account(js->gc), NULL, chat->conv, + chat, 2, + _("_Configure Room"), G_CALLBACK(jabber_chat_request_room_configure), + _("_Accept Defaults"), G_CALLBACK(jabber_chat_create_instant_room)); + } + + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(210))) { + /* server rewrote room-nick */ + g_free(chat->handle); + chat->handle = g_strdup(presence->jid_from->resource); + } + + if (purple_strequal(affiliation, "owner")) + flags |= PURPLE_CBFLAGS_FOUNDER; + if (role) { + if (g_str_equal(role, "moderator")) + flags |= PURPLE_CBFLAGS_OP; + else if (g_str_equal(role, "participant")) + flags |= PURPLE_CBFLAGS_VOICE; + } + + if(!chat->conv) { + char *room_jid = g_strdup_printf("%s@%s", presence->jid_from->node, presence->jid_from->domain); + chat->id = i++; + chat->conv = serv_got_joined_chat(js->gc, chat->id, room_jid); + purple_conv_chat_set_nick(PURPLE_CONV_CHAT(chat->conv), chat->handle); + + jabber_chat_disco_traffic(chat); + g_free(room_jid); + } + + jbr = jabber_buddy_track_resource(presence->jb, presence->jid_from->resource, presence->priority, presence->state, presence->status); + jbr->commands_fetched = TRUE; + + jabber_chat_track_handle(chat, presence->jid_from->resource, jid, affiliation, role); + + if(!jabber_chat_find_buddy(chat->conv, presence->jid_from->resource)) + purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat->conv), presence->jid_from->resource, + jid, flags, !presence->delayed); + else + purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(chat->conv), presence->jid_from->resource, + flags); + } else if (presence->type == JABBER_PRESENCE_UNAVAILABLE) { + gboolean nick_change = FALSE; + gboolean kick = FALSE; + gboolean is_our_resource = FALSE; /* Is the presence about us? */ + + const char *jid = NULL; + + /* If the chat nick is invalid, we haven't yet joined, or we've + * already left (it was probably us leaving after we closed the + * chat), we don't care. + */ + if (!presence->jid_from->resource || !chat->conv || chat->left) { + if (chat->left && + presence->jid_from->resource && chat->handle && !strcmp(presence->jid_from->resource, chat->handle)) + jabber_chat_destroy(chat); + return FALSE; + } + + is_our_resource = (0 == g_utf8_collate(presence->jid_from->resource, chat->handle)); + + jabber_buddy_remove_resource(presence->jb, presence->jid_from->resource); + + if (presence->chat_info.item) + jid = xmlnode_get_attrib(presence->chat_info.item, "jid"); + + if (chat->muc) { + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(110))) + is_our_resource = TRUE; + + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(301))) { + /* XXX: We got banned. YAY! (No GIR, that's bad) */ + } + + + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(303))) { + const char *nick = NULL; + if (presence->chat_info.item) + nick = xmlnode_get_attrib(presence->chat_info.item, "nick"); + + /* nick change */ + if (nick) { + purple_debug_warning("jabber", "Chat presence indicating a nick change, but no new nickname!\n"); + } else { + nick_change = TRUE; + + if (g_str_equal(presence->jid_from->resource, chat->handle)) { + /* Changing our own nickname */ + g_free(chat->handle); + chat->handle = g_strdup(nick); + } + + purple_conv_chat_rename_user(PURPLE_CONV_CHAT(chat->conv), + presence->jid_from->resource, + nick); + jabber_chat_remove_handle(chat, + presence->jid_from->resource); + } + } + + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(307))) { + /* Someone was kicked from the room */ + const char *actor = NULL; + char *reason = NULL; + char *tmp; + + kick = TRUE; + + if (presence->chat_info.item) { + xmlnode *node; + + node = xmlnode_get_child(presence->chat_info.item, "actor"); + if (node) + actor = xmlnode_get_attrib(node, "jid"); + node = xmlnode_get_child(presence->chat_info.item, "reason"); + if (node) + reason = xmlnode_get_data(node); + } + + if (reason == NULL) + reason = g_strdup(_("No reason")); + + if (is_our_resource) { + if (actor) + tmp = g_strdup_printf(_("You have been kicked by %s: (%s)"), + actor, reason); + else + tmp = g_strdup_printf(_("You have been kicked: (%s)"), + reason); + } else { + if (actor) + tmp = g_strdup_printf(_("Kicked by %s (%s)"), + actor, reason); + else + tmp = g_strdup_printf(_("Kicked (%s)"), + reason); + } + + g_free(presence->status); + presence->status = tmp; + + g_free(reason); + } + + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(321))) { + /* XXX: removed due to an affiliation change */ + } + + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(322))) { + /* XXX: removed because room is now members-only */ + } + + if (g_slist_find(presence->chat_info.codes, GINT_TO_POINTER(332))) { + /* XXX: removed due to system shutdown */ + } + } + + /* + * Possibly another connected resource of our JID (see XEP-0045 + * v1.24 section 7.1.10) being disconnected. Should be + * distinguished by the item_jid. + * Also possibly works around bits of an Openfire bug. See + * #8319. + */ + if (is_our_resource && jid && !purple_strequal(presence->to, jid)) { + /* TODO: When the above is a loop, this needs to still act + * sanely for all cases (this code is a little fragile). */ + if (!kick && !nick_change) + /* Presumably, kicks and nick changes also affect us. */ + is_our_resource = FALSE; + } + + if(!nick_change) { + if (is_our_resource) { + if (kick) + purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), presence->jid_from->resource, + presence->status, PURPLE_MESSAGE_SYSTEM, time(NULL)); + + serv_got_chat_left(js->gc, chat->id); + jabber_chat_destroy(chat); + } else { + purple_conv_chat_remove_user(PURPLE_CONV_CHAT(chat->conv), presence->jid_from->resource, + presence->status); + jabber_chat_remove_handle(chat, presence->jid_from->resource); + } + } + } + + return TRUE; +} + +gboolean +handle_presence_contact(JabberStream *js, JabberPresence *presence) +{ + JabberBuddyResource *jbr; + PurpleAccount *account; + PurpleBuddy *b; + char *buddy_name; + PurpleConversation *conv; + + buddy_name = jabber_id_get_bare_jid(presence->jid_from); + + account = purple_connection_get_account(js->gc); + b = purple_find_buddy(account, buddy_name); + + /* + * Unbind/unlock from sending messages to a specific resource on + * presence changes. This is locked to a specific resource when + * receiving a message (in message.c). + */ + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + buddy_name, account); + if (conv) { + purple_debug_info("jabber", "Changed conversation binding from %s to %s\n", + purple_conversation_get_name(conv), buddy_name); + purple_conversation_set_name(conv, buddy_name); + } + + if (b == NULL) { + if (presence->jb != js->user_jb) { + purple_debug_warning("jabber", "Got presence for unknown buddy %s on account %s (%p)\n", + buddy_name, purple_account_get_username(account), account); + return FALSE; + } else { + /* this is a different resource of our own account. Resume even when this account isn't on our blist */ + } + } + + if(b && presence->vcard_avatar_hash) { + const char *avatar_hash2 = purple_buddy_icons_get_checksum_for_user(b); + if(!avatar_hash2 || strcmp(presence->vcard_avatar_hash, avatar_hash2)) { + JabberIq *iq; + xmlnode *vcard; + + /* XXX this is a crappy way of trying to prevent + * someone from spamming us with presence packets + * and causing us to DoS ourselves...what we really + * need is a queue system that can throttle itself, + * but i'm too tired to write that right now */ + if(!g_slist_find(js->pending_avatar_requests, presence->jb)) { + + js->pending_avatar_requests = g_slist_prepend(js->pending_avatar_requests, presence->jb); + + iq = jabber_iq_new(js, JABBER_IQ_GET); + xmlnode_set_attrib(iq->node, "to", buddy_name); + vcard = xmlnode_new_child(iq->node, "vCard"); + xmlnode_set_namespace(vcard, "vcard-temp"); + + jabber_iq_set_callback(iq, jabber_vcard_parse_avatar, NULL); + jabber_iq_send(iq); + } + } + } + + if (presence->state == JABBER_BUDDY_STATE_ERROR || + presence->type == JABBER_PRESENCE_UNAVAILABLE || + presence->type == JABBER_PRESENCE_UNSUBSCRIBED) { + jabber_buddy_remove_resource(presence->jb, presence->jid_from->resource); + } else { + jbr = jabber_buddy_track_resource(presence->jb, + presence->jid_from->resource, presence->priority, + presence->state, presence->status); + jbr->idle = presence->idle ? time(NULL) - presence->idle : 0; + } + + jbr = jabber_buddy_find_resource(presence->jb, NULL); + if (jbr) { + jabber_google_presence_incoming(js, buddy_name, jbr); + purple_prpl_got_user_status(account, buddy_name, + jabber_buddy_state_get_status_id(jbr->state), + "priority", jbr->priority, + "message", jbr->status, + NULL); + purple_prpl_got_user_idle(account, buddy_name, + jbr->idle, jbr->idle); + if (presence->nickname) + serv_got_alias(js->gc, buddy_name, presence->nickname); + } else { + purple_prpl_got_user_status(account, buddy_name, + jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_UNAVAILABLE), + presence->status ? "message" : NULL, presence->status, + NULL); + } + g_free(buddy_name); + + return TRUE; +} + void jabber_presence_parse(JabberStream *js, xmlnode *packet) { - const char *from; const char *type; - char *status = NULL; - int priority = 0; - JabberID *jid; - JabberChat *chat; - JabberBuddy *jb; - JabberBuddyResource *jbr = NULL, *found_jbr = NULL; - PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE; - gboolean delayed = FALSE; - const gchar *stamp = NULL; /* from <delayed/> element */ - PurpleAccount *account; - PurpleBuddy *b = NULL; - char *buddy_name; - JabberBuddyState state = JABBER_BUDDY_STATE_UNKNOWN; - xmlnode *y; - char *avatar_hash = NULL; - xmlnode *caps = NULL; - int idle = 0; - gchar *nickname = NULL; - gboolean signal_return; + JabberBuddyResource *jbr = NULL; + gboolean signal_return, ret; + JabberPresence presence; + xmlnode *child; - from = xmlnode_get_attrib(packet, "from"); + memset(&presence, 0, sizeof(presence)); + /* defaults */ + presence.state = JABBER_BUDDY_STATE_UNKNOWN; + presence.sent = time(NULL); + /* interesting values */ + presence.from = xmlnode_get_attrib(packet, "from"); + presence.to = xmlnode_get_attrib(packet, "to"); type = xmlnode_get_attrib(packet, "type"); - - jb = jabber_buddy_find(js, from, TRUE); - g_return_if_fail(jb != NULL); + presence.type = str_to_presence_type(type); - signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), - "jabber-receiving-presence", js->gc, type, from, packet)); - if (signal_return) - return; + presence.jb = jabber_buddy_find(js, presence.from, TRUE); + g_return_if_fail(presence.jb != NULL); - account = purple_connection_get_account(js->gc); - - jid = jabber_id_new(from); - if (jid == NULL) { + presence.jid_from = jabber_id_new(presence.from); + if (presence.jid_from == NULL) { purple_debug_error("jabber", "Ignoring presence with malformed 'from' " - "JID: %s\n", from); + "JID: %s\n", presence.from); return; } - if(jb->error_msg) { - g_free(jb->error_msg); - jb->error_msg = NULL; + signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), + "jabber-receiving-presence", js->gc, type, presence.from, packet)); + if (signal_return) { + goto out; + } + + presence.chat = jabber_chat_find(js, presence.jid_from->node, + presence.jid_from->domain); + if(presence.jb->error_msg) { + g_free(presence.jb->error_msg); + presence.jb->error_msg = NULL; } - if (type == NULL) { - xmlnode *show; - char *show_data = NULL; - - state = JABBER_BUDDY_STATE_ONLINE; - - show = xmlnode_get_child(packet, "show"); - if (show) { - show_data = xmlnode_get_data(show); - if (show_data) { - state = jabber_buddy_show_get_state(show_data); - g_free(show_data); - } else - purple_debug_warning("jabber", "<show/> present on presence, " - "but no contents!\n"); - } - } else if (g_str_equal(type, "error")) { + if (presence.type == JABBER_PRESENCE_AVAILABLE) { + presence.state = JABBER_BUDDY_STATE_ONLINE; + } else if (presence.type == JABBER_PRESENCE_ERROR) { + /* TODO: Is this handled properly? Should it be treated as per-jbr? */ char *msg = jabber_parse_error(js, packet, NULL); - - state = JABBER_BUDDY_STATE_ERROR; - jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence")); - } else if (g_str_equal(type, "subscribe")) { + presence.state = JABBER_BUDDY_STATE_ERROR; + presence.jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence")); + } else if (presence.type == JABBER_PRESENCE_SUBSCRIBE) { + /* TODO: Move to handle_subscribe() (so nick is extracted by the + * PresenceHandler */ struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1); gboolean onlist = FALSE; + PurpleAccount *account; PurpleBuddy *buddy; - JabberBuddy *jb = NULL; xmlnode *nick; - buddy = purple_find_buddy(account, from); + account = purple_connection_get_account(js->gc); + buddy = purple_find_buddy(account, presence.from); nick = xmlnode_get_child_with_namespace(packet, "nick", "http://jabber.org/protocol/nick"); if (nick) - nickname = xmlnode_get_data(nick); + presence.nickname = xmlnode_get_data(nick); if (buddy) { - jb = jabber_buddy_find(js, from, TRUE); - if ((jb->subscription & (JABBER_SUB_TO | JABBER_SUB_PENDING))) + if ((presence.jb->subscription & (JABBER_SUB_TO | JABBER_SUB_PENDING))) onlist = TRUE; } jap->gc = js->gc; - jap->who = g_strdup(from); + jap->who = g_strdup(presence.from); jap->js = js; - purple_account_request_authorization(account, from, NULL, nickname, + purple_account_request_authorization(account, presence.from, NULL, presence.nickname, NULL, onlist, authorize_add_cb, deny_add_cb, jap); - g_free(nickname); - jabber_id_free(jid); - return; - } else if (g_str_equal(type, "subscribed")) { - /* we've been allowed to see their presence, but we don't care */ - jabber_id_free(jid); - return; - } else if (g_str_equal(type, "unsubscribe")) { + goto out; + } else if (presence.type == JABBER_PRESENCE_SUBSCRIBED) { + /* This case (someone has approved our subscribe request) is handled + * by the roster push the server sends along with this. + */ + goto out; + } else if (presence.type == JABBER_PRESENCE_UNSUBSCRIBE) { /* XXX I'm not sure this is the right way to handle this, it * might be better to add "unsubscribe" to the presence status * if lower down, but I'm not sure. */ /* they are unsubscribing from our presence, we don't care */ /* Well, maybe just a little, we might want/need to start * acknowledging this (and the others) at some point. */ - jabber_id_free(jid); - return; - } else if (g_str_equal(type, "probe")) { + goto out; + } else if (presence.type == JABBER_PRESENCE_PROBE) { purple_debug_warning("jabber", "Ignoring presence probe\n"); - jabber_id_free(jid); - return; - } else if (g_str_equal(type, "unavailable")) { - state = JABBER_BUDDY_STATE_UNAVAILABLE; - } else if (g_str_equal(type, "unsubscribed")) { - state = JABBER_BUDDY_STATE_UNKNOWN; + goto out; + } else if (presence.type == JABBER_PRESENCE_UNAVAILABLE) { + presence.state = JABBER_BUDDY_STATE_UNAVAILABLE; + } else if (presence.type == JABBER_PRESENCE_UNSUBSCRIBED) { + presence.state = JABBER_BUDDY_STATE_UNKNOWN; } else { purple_debug_warning("jabber", "Ignoring presence with invalid type " "'%s'\n", type); - jabber_id_free(jid); - return; + goto out; } - - for(y = packet->child; y; y = y->next) { - const char *xmlns; - if(y->type != XMLNODE_TYPE_TAG) - continue; - xmlns = xmlnode_get_namespace(y); - - if(!strcmp(y->name, "status")) { - g_free(status); - status = xmlnode_get_data(y); - } else if(!strcmp(y->name, "priority")) { - char *p = xmlnode_get_data(y); - if(p) { - priority = atoi(p); - g_free(p); - } - } else if(xmlns == NULL) { - /* The rest of the cases used to check xmlns individually. */ + for (child = packet->child; child; child = child->next) { + char *key; + JabberPresenceHandler *pih; + if (child->type != XMLNODE_TYPE_TAG) continue; - } else if(!strcmp(y->name, "delay") && !strcmp(xmlns, NS_DELAYED_DELIVERY)) { - /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */ - delayed = TRUE; - stamp = xmlnode_get_attrib(y, "stamp"); - } else if(!strcmp(y->name, "c") && !strcmp(xmlns, "http://jabber.org/protocol/caps")) { - caps = y; /* store for later, when creating buddy resource */ - } else if (g_str_equal(y->name, "nick") && g_str_equal(xmlns, "http://jabber.org/protocol/nick")) { - nickname = xmlnode_get_data(y); - } else if(!strcmp(y->name, "x")) { - if(!strcmp(xmlns, NS_DELAYED_DELIVERY_LEGACY)) { - /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */ - delayed = TRUE; - stamp = xmlnode_get_attrib(y, "stamp"); - } else if(!strcmp(xmlns, "http://jabber.org/protocol/muc#user")) { - } else if(!strcmp(xmlns, "vcard-temp:x:update")) { - xmlnode *photo = xmlnode_get_child(y, "photo"); - if(photo) { - g_free(avatar_hash); - avatar_hash = xmlnode_get_data(photo); - } - } - } else if (!strcmp(y->name, "query") && - !strcmp(xmlnode_get_namespace(y), NS_LAST_ACTIVITY)) { - /* resource has specified idle */ - const gchar *seconds = xmlnode_get_attrib(y, "seconds"); - if (seconds) { - /* we may need to take "delayed" into account here */ - idle = atoi(seconds); - } - } - } - - if (idle && delayed && stamp) { - /* if we have a delayed presence, we need to add the delay to the idle - value */ - time_t offset = time(NULL) - purple_str_to_time(stamp, TRUE, NULL, NULL, - NULL); - purple_debug_info("jabber", "got delay %s yielding %ld s offset\n", - stamp, offset); - idle += offset; + + key = g_strdup_printf("%s %s", child->name, xmlnode_get_namespace(child)); + pih = g_hash_table_lookup(presence_handlers, key); + g_free(key); + if (pih) + pih(js, &presence, child); } - /* DEALING WITH CHATS */ - if(jid->node && (chat = jabber_chat_find(js, jid->node, jid->domain))) { - static int i = 1; - - if(state == JABBER_BUDDY_STATE_ERROR) { - char *title, *msg = jabber_parse_error(js, packet, NULL); - - if (!chat->conv) { - title = g_strdup_printf(_("Error joining chat %s"), from); - purple_serv_got_join_chat_failed(js->gc, chat->components); - } else { - title = g_strdup_printf(_("Error in chat %s"), from); - if (g_hash_table_size(chat->members) == 0) - serv_got_chat_left(js->gc, chat->id); - } - purple_notify_error(js->gc, title, title, msg); - g_free(title); - g_free(msg); - - if (g_hash_table_size(chat->members) == 0) - /* Only destroy the chat if the error happened while joining */ - jabber_chat_destroy(chat); - jabber_id_free(jid); - g_free(status); - g_free(avatar_hash); - g_free(nickname); - return; - } - - if (type == NULL) { - xmlnode *x; - const char *real_jid = NULL; - const char *affiliation = NULL; - const char *role = NULL; - gboolean is_our_resource = FALSE; /* Is the presence about us? */ - - /* - * XEP-0045 mandates the presence to include a resource (which is - * treated as the chat nick). Some non-compliant servers allow - * joining without a nick. - */ - if (!jid->resource) { - jabber_id_free(jid); - g_free(avatar_hash); - g_free(nickname); - g_free(status); - return; - } - - x = xmlnode_get_child_with_namespace(packet, "x", - "http://jabber.org/protocol/muc#user"); - if (x) { - xmlnode *status_node; - xmlnode *item_node; - - for (status_node = xmlnode_get_child(x, "status"); status_node; - status_node = xmlnode_get_next_twin(status_node)) { - const char *code = xmlnode_get_attrib(status_node, "code"); - if (!code) - continue; - - if (g_str_equal(code, "110")) { - is_our_resource = TRUE; - } else if (g_str_equal(code, "201")) { - if ((chat = jabber_chat_find(js, jid->node, jid->domain))) { - chat->config_dialog_type = PURPLE_REQUEST_ACTION; - chat->config_dialog_handle = - purple_request_action(js->gc, - _("Create New Room"), - _("Create New Room"), - _("You are creating a new room. Would" - " you like to configure it, or" - " accept the default settings?"), - /* Default Action */ 1, - account, NULL, chat->conv, - chat, 2, - _("_Configure Room"), G_CALLBACK(jabber_chat_request_room_configure), - _("_Accept Defaults"), G_CALLBACK(jabber_chat_create_instant_room)); - } - } else if (g_str_equal(code, "210")) { - /* server rewrote room-nick */ - if((chat = jabber_chat_find(js, jid->node, jid->domain))) { - g_free(chat->handle); - chat->handle = g_strdup(jid->resource); - } - } - } - - item_node = xmlnode_get_child(x, "item"); - if (item_node) { - real_jid = xmlnode_get_attrib(item_node, "jid"); - affiliation = xmlnode_get_attrib(item_node, "affiliation"); - role = xmlnode_get_attrib(item_node, "role"); - - if (purple_strequal(affiliation, "owner")) - flags |= PURPLE_CBFLAGS_FOUNDER; - if (role) { - if (g_str_equal(role, "moderator")) - flags |= PURPLE_CBFLAGS_OP; - else if (g_str_equal(role, "participant")) - flags |= PURPLE_CBFLAGS_VOICE; - } - } - } - - if(!chat->conv) { - char *room_jid = g_strdup_printf("%s@%s", jid->node, jid->domain); - chat->id = i++; - chat->muc = (x != NULL); - chat->conv = serv_got_joined_chat(js->gc, chat->id, room_jid); - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(chat->conv), chat->handle); - - jabber_chat_disco_traffic(chat); - g_free(room_jid); - } - - jbr = jabber_buddy_track_resource(jb, jid->resource, priority, state, - status); - jbr->commands_fetched = TRUE; - - jabber_chat_track_handle(chat, jid->resource, real_jid, affiliation, role); - - if(!jabber_chat_find_buddy(chat->conv, jid->resource)) - purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, - real_jid, flags, !delayed); - else - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(chat->conv), jid->resource, - flags); - } else if (g_str_equal(type, "unavailable")) { - xmlnode *x; - gboolean nick_change = FALSE; - gboolean kick = FALSE; - gboolean is_our_resource = FALSE; /* Is the presence about us? */ - - /* If the chat nick is invalid, we haven't yet joined, or we've - * already left (it was probably us leaving after we closed the - * chat), we don't care. - */ - if (!jid->resource || !chat->conv || chat->left) { - if (chat->left && - jid->resource && chat->handle && !strcmp(jid->resource, chat->handle)) - jabber_chat_destroy(chat); - jabber_id_free(jid); - g_free(status); - g_free(avatar_hash); - g_free(nickname); - return; - } - - is_our_resource = (0 == g_utf8_collate(jid->resource, chat->handle)); - - jabber_buddy_remove_resource(jb, jid->resource); - - x = xmlnode_get_child_with_namespace(packet, "x", - "http://jabber.org/protocol/muc#user"); - if (chat->muc && x) { - const char *nick; - const char *item_jid = NULL; - const char *to; - xmlnode *stat; - xmlnode *item; - - item = xmlnode_get_child(x, "item"); - if (item) - item_jid = xmlnode_get_attrib(item, "jid"); - - for (stat = xmlnode_get_child(x, "status"); stat; - stat = xmlnode_get_next_twin(stat)) { - const char *code = xmlnode_get_attrib(stat, "code"); - - if (!code) - continue; - - if (g_str_equal(code, "110")) { - is_our_resource = TRUE; - } else if(!strcmp(code, "301")) { - /* XXX: we got banned */ - } else if(!strcmp(code, "303") && item && - (nick = xmlnode_get_attrib(item, "nick"))) { - nick_change = TRUE; - if(!strcmp(jid->resource, chat->handle)) { - g_free(chat->handle); - chat->handle = g_strdup(nick); - } - - /* TODO: This should probably be moved out of the loop */ - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, nick); - jabber_chat_remove_handle(chat, jid->resource); - continue; - } else if(!strcmp(code, "307")) { - /* Someone was kicked from the room */ - xmlnode *reason = NULL, *actor = NULL; - const char *actor_name = NULL; - char *reason_text = NULL; - char *tmp; - - kick = TRUE; - - if (item) { - reason = xmlnode_get_child(item, "reason"); - actor = xmlnode_get_child(item, "actor"); - - if (reason != NULL) - reason_text = xmlnode_get_data(reason); - if (actor != NULL) - actor_name = xmlnode_get_attrib(actor, "jid"); - } - - if (reason_text == NULL) - reason_text = g_strdup(_("No reason")); - - if (is_our_resource) { - if (actor_name != NULL) - tmp = g_strdup_printf(_("You have been kicked by %s: (%s)"), - actor_name, reason_text); - else - tmp = g_strdup_printf(_("You have been kicked: (%s)"), - reason_text); - } else { - if (actor_name != NULL) - tmp = g_strdup_printf(_("Kicked by %s (%s)"), - actor_name, reason_text); - else - tmp = g_strdup_printf(_("Kicked (%s)"), - reason_text); - } - - g_free(reason_text); - g_free(status); - status = tmp; - } else if(!strcmp(code, "321")) { - /* XXX: removed due to an affiliation change */ - } else if(!strcmp(code, "322")) { - /* XXX: removed because room is now members-only */ - } else if(!strcmp(code, "332")) { - /* XXX: removed due to system shutdown */ - } - } - - /* - * Possibly another connected resource of our JID (see XEP-0045 - * v1.24 section 7.1.10) being disconnected. Should be - * distinguished by the item_jid. - * Also possibly works around bits of an Openfire bug. See - * #8319. - */ - to = xmlnode_get_attrib(packet, "to"); - if (is_our_resource && item_jid && !purple_strequal(to, item_jid)) { - /* TODO: When the above is a loop, this needs to still act - * sanely for all cases (this code is a little fragile). */ - if (!kick && !nick_change) - /* Presumably, kicks and nick changes also affect us. */ - is_our_resource = FALSE; - } - } - if(!nick_change) { - if (is_our_resource) { - if (kick) - purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), jid->resource, - status, PURPLE_MESSAGE_SYSTEM, time(NULL)); - - serv_got_chat_left(js->gc, chat->id); - jabber_chat_destroy(chat); - } else { - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, - status); - jabber_chat_remove_handle(chat, jid->resource); - } - } - } else { - /* A type that isn't available or unavailable */ - purple_debug_error("jabber", "MUC presence with bad type: %s\n", - type); - - jabber_id_free(jid); - g_free(avatar_hash); - g_free(status); - g_free(nickname); - g_return_if_reached(); - } - /* End of DEALING WITH CHATS...about 5000 lines ago */ - } else { - /* DEALING WITH CONTACT (i.e. not a chat) */ - PurpleConversation *conv; - - buddy_name = g_strdup_printf("%s%s%s", jid->node ? jid->node : "", - jid->node ? "@" : "", jid->domain); - - /* - * Unbind/unlock from sending messages to a specific resource on - * presence changes. This is locked to a specific resource when - * receiving a message (in message.c). - */ - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - buddy_name, account); - if (conv) { - purple_debug_info("jabber", "Changed conversation binding from %s to %s\n", - purple_conversation_get_name(conv), buddy_name); - purple_conversation_set_name(conv, buddy_name); - } - - if((b = purple_find_buddy(account, buddy_name)) == NULL) { - if (jb != js->user_jb) { - purple_debug_warning("jabber", "Got presence for unknown buddy %s on account %s (%p)\n", - buddy_name, purple_account_get_username(account), account); - jabber_id_free(jid); - g_free(avatar_hash); - g_free(buddy_name); - g_free(nickname); - g_free(status); - return; - } else { - /* this is a different resource of our own account. Resume even when this account isn't on our blist */ - } - } - - if(b && avatar_hash) { - const char *avatar_hash2 = purple_buddy_icons_get_checksum_for_user(b); - if(!avatar_hash2 || strcmp(avatar_hash, avatar_hash2)) { - JabberIq *iq; - xmlnode *vcard; - - /* XXX this is a crappy way of trying to prevent - * someone from spamming us with presence packets - * and causing us to DoS ourselves...what we really - * need is a queue system that can throttle itself, - * but i'm too tired to write that right now */ - if(!g_slist_find(js->pending_avatar_requests, jb)) { - - js->pending_avatar_requests = g_slist_prepend(js->pending_avatar_requests, jb); - - iq = jabber_iq_new(js, JABBER_IQ_GET); - xmlnode_set_attrib(iq->node, "to", buddy_name); - vcard = xmlnode_new_child(iq->node, "vCard"); - xmlnode_set_namespace(vcard, "vcard-temp"); - - jabber_iq_set_callback(iq, jabber_vcard_parse_avatar, NULL); - jabber_iq_send(iq); - } - } - } - - if(state == JABBER_BUDDY_STATE_ERROR || - (type && (g_str_equal(type, "unavailable") || - g_str_equal(type, "unsubscribed")))) { - jabber_buddy_remove_resource(jb, jid->resource); - } else { - jbr = jabber_buddy_track_resource(jb, jid->resource, priority, - state, status); - if (idle) { - jbr->idle = time(NULL) - idle; - } else { - jbr->idle = 0; - } - } - - if((found_jbr = jabber_buddy_find_resource(jb, NULL))) { - jabber_google_presence_incoming(js, buddy_name, found_jbr); - purple_prpl_got_user_status(account, buddy_name, jabber_buddy_state_get_status_id(found_jbr->state), "priority", found_jbr->priority, "message", found_jbr->status, NULL); - purple_prpl_got_user_idle(account, buddy_name, found_jbr->idle, found_jbr->idle); - if (nickname) - serv_got_alias(js->gc, buddy_name, nickname); - } else { - purple_prpl_got_user_status(account, buddy_name, "offline", status ? "message" : NULL, status, NULL); - } - g_free(buddy_name); + if (presence.delayed && presence.idle) { + /* Delayed and idle, so update idle time */ + presence.idle = presence.idle + (time(NULL) - presence.sent); } - if (caps && !type) { + /* TODO: Handle tracking jb(r) here? */ + + if (presence.chat) + ret = handle_presence_chat(js, &presence, packet); + else + ret = handle_presence_contact(js, &presence); + if (!ret) + goto out; + + if (presence.caps && presence.type == JABBER_PRESENCE_AVAILABLE) { /* handle Entity Capabilities (XEP-0115) */ - const char *node = xmlnode_get_attrib(caps, "node"); - const char *ver = xmlnode_get_attrib(caps, "ver"); - const char *hash = xmlnode_get_attrib(caps, "hash"); - const char *ext = xmlnode_get_attrib(caps, "ext"); + const char *node = xmlnode_get_attrib(presence.caps, "node"); + const char *ver = xmlnode_get_attrib(presence.caps, "ver"); + const char *hash = xmlnode_get_attrib(presence.caps, "hash"); + const char *ext = xmlnode_get_attrib(presence.caps, "ext"); /* v1.3 uses: node, ver, and optionally ext. * v1.5 uses: node, ver, and hash. */ if (node && *node && ver && *ver) { gchar **exts = ext && *ext ? g_strsplit(ext, " ", -1) : NULL; - jbr = jabber_buddy_find_resource(jb, jid->resource); + jbr = jabber_buddy_find_resource(presence.jb, presence.jid_from->resource); /* Look it up if we don't already have all this information */ if (!jbr || !jbr->caps.info || @@ -1084,9 +1039,9 @@ !jabber_caps_exts_known(jbr->caps.info, (gchar **)exts)) { JabberPresenceCapabilities *userdata = g_new0(JabberPresenceCapabilities, 1); userdata->js = js; - userdata->jb = jb; - userdata->from = g_strdup(from); - jabber_caps_get_info(js, from, node, ver, hash, exts, + userdata->jb = presence.jb; + userdata->from = g_strdup(presence.from); + jabber_caps_get_info(js, presence.from, node, ver, hash, exts, (jabber_caps_get_info_cb)jabber_presence_set_capabilities, userdata); } else { @@ -1096,10 +1051,12 @@ } } - g_free(nickname); - g_free(status); - jabber_id_free(jid); - g_free(avatar_hash); +out: + g_free(presence.nickname); + g_free(presence.status); + jabber_id_free(presence.jid_from); + g_free(presence.nickname); + g_free(presence.vcard_avatar_hash); } void jabber_presence_subscription_set(JabberStream *js, const char *who, const char *type) @@ -1142,3 +1099,170 @@ *priority = purple_status_get_attr_int(status, "priority"); } } + +/* Incoming presence handlers */ +static void +parse_priority(JabberStream *js, JabberPresence *presence, xmlnode *priority) +{ + char *p = xmlnode_get_data(priority); + + if (presence->priority != 0) + purple_debug_warning("jabber", "presence stanza received with multiple " + "priority children!?\n"); + + if (p) { + presence->priority = atoi(p); + g_free(p); + } else + purple_debug_warning("jabber", "Empty <priority/> in presence!\n"); +} + +static void +parse_show(JabberStream *js, JabberPresence *presence, xmlnode *show) +{ + char *cdata; + + if (presence->type != JABBER_PRESENCE_AVAILABLE) { + purple_debug_warning("jabber", "<show/> present on presence, but " + "type is not default ('available')\n"); + return; + } + + cdata = xmlnode_get_data(show); + if (cdata) { + presence->state = jabber_buddy_show_get_state(cdata); + g_free(cdata); + } else + purple_debug_warning("jabber", "<show/> present on presence, but " + "no contents!\n"); +} + +static void +parse_status(JabberStream *js, JabberPresence *presence, xmlnode *status) +{ + /* TODO: Check/track language attribute? */ + + g_free(presence->status); + presence->status = xmlnode_get_data(status); +} + +static void +parse_delay(JabberStream *js, JabberPresence *presence, xmlnode *delay) +{ + /* XXX: compare the time. Can happen on presence stanzas that aren't + * actually delayed. + */ + const char *stamp = xmlnode_get_attrib(delay, "stamp"); + presence->delayed = TRUE; + presence->sent = purple_str_to_time(stamp, TRUE, NULL, NULL, NULL); +} + +static void +parse_idle(JabberStream *js, JabberPresence *presence, xmlnode *query) +{ + const gchar *seconds = xmlnode_get_attrib(query, "seconds"); + if (seconds) { + presence->idle = atoi(seconds); + if (presence->idle < 0) { + purple_debug_warning("jabber", "Received bogus idle time %s\n", seconds); + presence->idle = 0; + } + } +} + +static void +parse_caps(JabberStream *js, JabberPresence *presence, xmlnode *c) +{ + /* TODO: Move the rest of the caps handling in here, after changing the + * the "do we have details about this (node, ver) and exts" to not + * require the jbr to be present (since that happens later). + */ + presence->caps = c; +} + +static void +parse_nickname(JabberStream *js, JabberPresence *presence, xmlnode *nick) +{ + g_free(presence->nickname); + presence->nickname = xmlnode_get_data(nick); +} + +static void +parse_vcard_avatar(JabberStream *js, JabberPresence *presence, xmlnode *x) +{ + xmlnode *photo = xmlnode_get_child(x, "photo"); + if (photo) { + g_free(presence->vcard_avatar_hash); + presence->vcard_avatar_hash = xmlnode_get_data(photo); + } +} + +static void +parse_muc_user(JabberStream *js, JabberPresence *presence, xmlnode *x) +{ + xmlnode *status; + + if (presence->chat == NULL) { + purple_debug_warning("jabber", "Ignoring MUC gloop on non-MUC presence\n"); + return; + } + + if (presence->chat->conv == NULL) + presence->chat->muc = TRUE; + + for (status = xmlnode_get_child(x, "status"); status; + status = xmlnode_get_next_twin(status)) { + const char *code = xmlnode_get_attrib(status, "code"); + int val; + if (!code) + continue; + + val = atoi(code); + if (val == 0 || val < 0) { + purple_debug_warning("jabber", "Ignoring bogus status code '%s'\n", + code); + continue; + } + + presence->chat_info.codes = g_slist_prepend(presence->chat_info.codes, GINT_TO_POINTER(val)); + } + + presence->chat_info.item = xmlnode_get_child(x, "item"); +} + +void jabber_presence_register_handler(const char *node, const char *xmlns, + JabberPresenceHandler *handler) +{ + /* + * 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(presence_handlers, key, handler); +} + +void jabber_presence_init(void) +{ + presence_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + + /* Core RFC things */ + jabber_presence_register_handler("priority", "jabber:client", parse_priority); + jabber_presence_register_handler("show", "jabber:client", parse_show); + jabber_presence_register_handler("status", "jabber:client", parse_status); + + /* XEPs */ + jabber_presence_register_handler("c", "http://jabber.org/protocol/caps", parse_caps); + jabber_presence_register_handler("delay", NS_DELAYED_DELIVERY, parse_delay); + jabber_presence_register_handler("nick", "http://jabber.org/protocol/nick", parse_nickname); + jabber_presence_register_handler("query", NS_LAST_ACTIVITY, parse_idle); + jabber_presence_register_handler("x", NS_DELAYED_DELIVERY_LEGACY, parse_delay); + jabber_presence_register_handler("x", "http://jabber.org/protocol/muc#user", parse_muc_user); + jabber_presence_register_handler("x", "vcard-temp:x:update", parse_vcard_avatar); +} + +void jabber_presence_uninit(void) +{ + g_hash_table_destroy(presence_handlers); + presence_handlers = NULL; +}
--- a/libpurple/protocols/jabber/presence.h Tue Mar 09 21:41:41 2010 +0000 +++ b/libpurple/protocols/jabber/presence.h Wed Mar 10 05:40:56 2010 +0000 @@ -24,10 +24,63 @@ #ifndef PURPLE_JABBER_PRESENCE_H_ #define PURPLE_JABBER_PRESENCE_H_ +typedef enum { + JABBER_PRESENCE_ERROR = -2, + JABBER_PRESENCE_PROBE = -1, + JABBER_PRESENCE_AVAILABLE, + JABBER_PRESENCE_UNAVAILABLE, + JABBER_PRESENCE_SUBSCRIBE, + JABBER_PRESENCE_SUBSCRIBED, + JABBER_PRESENCE_UNSUBSCRIBE, + JABBER_PRESENCE_UNSUBSCRIBED +} JabberPresenceType; + +typedef struct _JabberPresenceChatInfo JabberPresenceChatInfo; +typedef struct _JabberPresence JabberPresence; + #include "buddy.h" +#include "chat.h" #include "jabber.h" +#include "jutil.h" #include "xmlnode.h" +struct _JabberPresenceChatInfo { + GSList *codes; + xmlnode *item; +}; + +struct _JabberPresence { + JabberPresenceType type; + JabberID *jid_from; + const char *from; + const char *to; + const char *id; + + JabberBuddy *jb; + JabberChat *chat; + JabberPresenceChatInfo chat_info; + xmlnode *caps; /* TODO: Temporary, see presence.c:parse_caps */ + + JabberBuddyState state; + gchar *status; + int priority; + + char *vcard_avatar_hash; + char *nickname; + + gboolean delayed; + time_t sent; + int idle; +}; + +typedef void (JabberPresenceHandler)(JabberStream *js, JabberPresence *presence, + xmlnode *child); +void jabber_presence_register_handler(const char *node, const char *xmlns, + JabberPresenceHandler *handler); + +void jabber_presence_init(void); +void jabber_presence_uninit(void); + void jabber_set_status(PurpleAccount *account, PurpleStatus *status); /**
--- a/libpurple/protocols/msnp9/Makefile.am Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -EXTRA_DIST = \ - Makefile.mingw - -pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION) - -MSNP9SOURCES = \ - cmdproc.c \ - cmdproc.h \ - command.c \ - command.h \ - dialog.c \ - dialog.h \ - directconn.c \ - directconn.h \ - error.c \ - error.h \ - group.c \ - group.h \ - history.c \ - history.h \ - httpconn.c \ - httpconn.h \ - msg.c \ - msg.h \ - msn.c \ - msn.h \ - nexus.c \ - nexus.h \ - notification.c \ - notification.h \ - object.c \ - object.h \ - page.c \ - page.h \ - servconn.c \ - servconn.h \ - session.c \ - session.h \ - slp.c \ - slp.h \ - slpcall.c \ - slpcall.h \ - slplink.c \ - slplink.h \ - slpmsg.c \ - slpmsg.h \ - slpsession.c \ - slpsession.h \ - state.c \ - state.h \ - switchboard.c \ - switchboard.h \ - sync.c \ - sync.h \ - table.c \ - table.h \ - transaction.c \ - transaction.h \ - user.c \ - user.h \ - userlist.c \ - userlist.h \ - msn-utils.c \ - msn-utils.h - -AM_CFLAGS = $(st) - -libmsn_la_LDFLAGS = -module -avoid-version - -if STATIC_MSN - -st = -DPURPLE_STATIC_PRPL -noinst_LTLIBRARIES = libmsn.la -libmsn_la_SOURCES = $(MSNP9SOURCES) -libmsn_la_CFLAGS = $(AM_CFLAGS) - -else - -st = -pkg_LTLIBRARIES = libmsn.la -libmsn_la_SOURCES = $(MSNP9SOURCES) -libmsn_la_LIBADD = $(GLIB_LIBS) - -endif - -AM_CPPFLAGS = \ - -I$(top_srcdir)/libpurple \ - -I$(top_builddir)/libpurple \ - $(GLIB_CFLAGS) \ - $(DEBUG_CFLAGS)
--- a/libpurple/protocols/msnp9/Makefile.mingw Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -# -# Makefile.mingw -# -# Description: Makefile for win32 (mingw) version of libmsn -# - -PIDGIN_TREE_TOP := ../../.. -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak - -TARGET = libmsn -TYPE = PLUGIN - -# Static or Plugin... -ifeq ($(TYPE),STATIC) - DEFINES += -DSTATIC - DLL_INSTALL_DIR = $(PURPLE_INSTALL_DIR) -else -ifeq ($(TYPE),PLUGIN) - DLL_INSTALL_DIR = $(PURPLE_INSTALL_PLUGINS_DIR) -endif -endif - -## -## INCLUDE PATHS -## -INCLUDE_PATHS += -I. \ - -I$(GTK_TOP)/include \ - -I$(GTK_TOP)/include/glib-2.0 \ - -I$(GTK_TOP)/lib/glib-2.0/include \ - -I$(PURPLE_TOP) \ - -I$(PURPLE_TOP)/win32 \ - -I$(PIDGIN_TREE_TOP) - -LIB_PATHS += -L$(GTK_TOP)/lib \ - -L$(PURPLE_TOP) - -## -## SOURCES, OBJECTS -## -C_SRC = cmdproc.c \ - command.c \ - dialog.c \ - directconn.c \ - error.c \ - group.c \ - history.c \ - httpconn.c \ - msg.c \ - msn.c \ - nexus.c \ - notification.c \ - object.c \ - page.c \ - servconn.c \ - session.c \ - slp.c \ - slpcall.c \ - slplink.c \ - slpmsg.c \ - slpsession.c \ - state.c \ - switchboard.c \ - sync.c \ - table.c \ - transaction.c \ - user.c \ - userlist.c \ - msn-utils.c - -OBJECTS = $(C_SRC:%.c=%.o) - -## -## LIBRARIES -## -LIBS = \ - -lglib-2.0 \ - -lintl \ - -lws2_32 \ - -lpurple - -include $(PIDGIN_COMMON_RULES) - -## -## TARGET DEFINITIONS -## -.PHONY: all install clean - -all: $(TARGET).dll - -install: all $(DLL_INSTALL_DIR) - cp $(TARGET).dll $(DLL_INSTALL_DIR) - -$(OBJECTS): $(PURPLE_CONFIG_H) - -$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS) - $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll - -## -## CLEAN RULES -## -clean: - rm -f $(OBJECTS) - rm -f $(TARGET).dll - -include $(PIDGIN_COMMON_TARGETS)
--- a/libpurple/protocols/msnp9/cmdproc.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,344 +0,0 @@ -/** - * @file cmdproc.c MSN command processor functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "cmdproc.h" - -MsnCmdProc * -msn_cmdproc_new(MsnSession *session) -{ - MsnCmdProc *cmdproc; - - cmdproc = g_new0(MsnCmdProc, 1); - - cmdproc->session = session; - cmdproc->txqueue = g_queue_new(); - cmdproc->history = msn_history_new(); - - return cmdproc; -} - -void -msn_cmdproc_destroy(MsnCmdProc *cmdproc) -{ - MsnTransaction *trans; - - while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL) - msn_transaction_destroy(trans); - - g_queue_free(cmdproc->txqueue); - - msn_history_destroy(cmdproc->history); - - if (cmdproc->last_cmd != NULL) - msn_command_destroy(cmdproc->last_cmd); - - g_free(cmdproc); -} - -void -msn_cmdproc_process_queue(MsnCmdProc *cmdproc) -{ - MsnTransaction *trans; - - while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL) - msn_cmdproc_send_trans(cmdproc, trans); -} - -void -msn_cmdproc_queue_trans(MsnCmdProc *cmdproc, MsnTransaction *trans) -{ - g_return_if_fail(cmdproc != NULL); - g_return_if_fail(trans != NULL); - - g_queue_push_tail(cmdproc->txqueue, trans); -} - -static void -show_debug_cmd(MsnCmdProc *cmdproc, gboolean incoming, const char *command) -{ - MsnServConn *servconn; - const char *names[] = { "NS", "SB" }; - char *show; - char tmp; - size_t len; - - servconn = cmdproc->servconn; - len = strlen(command); - show = g_strdup(command); - - tmp = (incoming) ? 'S' : 'C'; - - if ((show[len - 1] == '\n') && (show[len - 2] == '\r')) - { - show[len - 2] = '\0'; - } - - purple_debug_misc("msn", "%c: %s %03d: %s\n", tmp, - names[servconn->type], servconn->num, show); - - g_free(show); -} - -void -msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans) -{ - MsnServConn *servconn; - char *data; - size_t len; - - g_return_if_fail(cmdproc != NULL); - g_return_if_fail(trans != NULL); - - servconn = cmdproc->servconn; - - if (!servconn->connected) - return; - - msn_history_add(cmdproc->history, trans); - - data = msn_transaction_to_string(trans); - - len = strlen(data); - - show_debug_cmd(cmdproc, FALSE, data); - - if (trans->callbacks == NULL) - trans->callbacks = g_hash_table_lookup(cmdproc->cbs_table->cmds, - trans->command); - - if (trans->payload != NULL) - { - data = g_realloc(data, len + trans->payload_len); - memcpy(data + len, trans->payload, trans->payload_len); - len += trans->payload_len; - - /* - * We're done with trans->payload. Free it so that the memory - * doesn't sit around in cmdproc->history. - */ - g_free(trans->payload); - trans->payload = NULL; - trans->payload_len = 0; - } - - msn_servconn_write(servconn, data, len); - - g_free(data); -} - -void -msn_cmdproc_send_quick(MsnCmdProc *cmdproc, const char *command, - const char *format, ...) -{ - MsnServConn *servconn; - char *data; - char *params = NULL; - va_list arg; - size_t len; - - g_return_if_fail(cmdproc != NULL); - g_return_if_fail(command != NULL); - - servconn = cmdproc->servconn; - - if (!servconn->connected) - return; - - if (format != NULL) - { - va_start(arg, format); - params = g_strdup_vprintf(format, arg); - va_end(arg); - } - - if (params != NULL) - data = g_strdup_printf("%s %s\r\n", command, params); - else - data = g_strdup_printf("%s\r\n", command); - - g_free(params); - - len = strlen(data); - - show_debug_cmd(cmdproc, FALSE, data); - - msn_servconn_write(servconn, data, len); - - g_free(data); -} - -void -msn_cmdproc_send(MsnCmdProc *cmdproc, const char *command, - const char *format, ...) -{ - MsnTransaction *trans; - va_list arg; - - g_return_if_fail(cmdproc != NULL); - g_return_if_fail(command != NULL); - - if (!cmdproc->servconn->connected) - return; - - trans = g_new0(MsnTransaction, 1); - - trans->command = g_strdup(command); - - if (format != NULL) - { - va_start(arg, format); - trans->params = g_strdup_vprintf(format, arg); - va_end(arg); - } - - msn_cmdproc_send_trans(cmdproc, trans); -} - -void -msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload, - int payload_len) -{ - MsnCommand *last; - - g_return_if_fail(cmdproc != NULL); - - last = cmdproc->last_cmd; - last->payload = g_memdup(payload, payload_len); - last->payload_len = payload_len; - - if (last->payload_cb != NULL) - last->payload_cb(cmdproc, last, payload, payload_len); -} - -void -msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - MsnMsgTypeCb cb; - - if (msn_message_get_content_type(msg) == NULL) - { - purple_debug_misc("msn", "failed to find message content\n"); - return; - } - - cb = g_hash_table_lookup(cmdproc->cbs_table->msgs, - msn_message_get_content_type(msg)); - - if (cb == NULL) - { - purple_debug_warning("msn", "Unhandled content-type '%s'\n", - msn_message_get_content_type(msg)); - - return; - } - - cb(cmdproc, msg); -} - -void -msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnTransCb cb = NULL; - MsnTransaction *trans = NULL; - - if (cmd->trId) - trans = msn_history_find(cmdproc->history, cmd->trId); - - if (trans != NULL) - if (trans->timer) - purple_timeout_remove(trans->timer); - - if (g_ascii_isdigit(cmd->command[0])) - { - if (trans != NULL) - { - MsnErrorCb error_cb = NULL; - int error; - - error = atoi(cmd->command); - - if (trans->error_cb != NULL) - error_cb = trans->error_cb; - - if (error_cb == NULL && cmdproc->cbs_table->errors != NULL) - error_cb = g_hash_table_lookup(cmdproc->cbs_table->errors, trans->command); - - if (error_cb != NULL) - { - error_cb(cmdproc, trans, error); - } - else - { -#if 1 - msn_error_handle(cmdproc->session, error); -#else - purple_debug_warning("msn", "Unhandled error '%s'\n", - cmd->command); -#endif - } - - return; - } - } - - if (cmdproc->cbs_table->async != NULL) - cb = g_hash_table_lookup(cmdproc->cbs_table->async, cmd->command); - - if (cb == NULL && trans != NULL) - { - cmd->trans = trans; - - if (trans->callbacks != NULL) - cb = g_hash_table_lookup(trans->callbacks, cmd->command); - } - - if (cb == NULL && cmdproc->cbs_table->fallback != NULL) - cb = g_hash_table_lookup(cmdproc->cbs_table->fallback, cmd->command); - - if (cb != NULL) - { - cb(cmdproc, cmd); - } - else - { - purple_debug_warning("msn", "Unhandled command '%s'\n", - cmd->command); - } - - if (trans != NULL && trans->pendent_cmd != NULL) - msn_transaction_unqueue_cmd(trans, cmdproc); -} - -void -msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command) -{ - show_debug_cmd(cmdproc, TRUE, command); - - if (cmdproc->last_cmd != NULL) - msn_command_destroy(cmdproc->last_cmd); - - cmdproc->last_cmd = msn_command_from_string(command); - - msn_cmdproc_process_cmd(cmdproc, cmdproc->last_cmd); -}
--- a/libpurple/protocols/msnp9/cmdproc.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/** - * @file cmdproc.h MSN command processor functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_CMDPROC_H_ -#define _MSN_CMDPROC_H_ - -typedef struct _MsnCmdProc MsnCmdProc; - -#include "session.h" -#include "servconn.h" -#include "error.h" -#include "command.h" -#include "table.h" -#include "history.h" - -struct _MsnCmdProc -{ - MsnSession *session; - MsnServConn *servconn; - - GQueue *txqueue; - - MsnCommand *last_cmd; - - MsnTable *cbs_table; - - MsnHistory *history; - - void *data; /**< Extra data, like the switchboard. */ -}; - -MsnCmdProc *msn_cmdproc_new(MsnSession *session); -void msn_cmdproc_destroy(MsnCmdProc *cmdproc); - -void msn_cmdproc_process_queue(MsnCmdProc *cmdproc); - -void msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans); -void msn_cmdproc_queue_trans(MsnCmdProc *cmdproc, - MsnTransaction *trans); -void msn_cmdproc_send(MsnCmdProc *cmdproc, const char *command, - const char *format, ...); -void msn_cmdproc_send_quick(MsnCmdProc *cmdproc, const char *command, - const char *format, ...); - -void msn_cmdproc_process_msg(MsnCmdProc *cmdproc, - MsnMessage *msg); -void msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd); -void msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command); -void msn_cmdproc_process_payload(MsnCmdProc *cmdproc, - char *payload, int payload_len); - -void msn_cmdproc_disconnect(MsnCmdProc *cmdproc); - -#endif /* _MSN_CMDPROC_H_ */
--- a/libpurple/protocols/msnp9/command.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/** - * @file command.c MSN command functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "command.h" - -static gboolean -is_num(char *str) -{ - char *c; - for (c = str; *c; c++) { - if (!(g_ascii_isdigit(*c))) - return FALSE; - } - - return TRUE; -} - -MsnCommand * -msn_command_from_string(const char *string) -{ - MsnCommand *cmd; - char *tmp; - char *param_start; - - g_return_val_if_fail(string != NULL, NULL); - - tmp = g_strdup(string); - param_start = strchr(tmp, ' '); - - cmd = g_new0(MsnCommand, 1); - cmd->command = tmp; - - if (param_start) - { - *param_start++ = '\0'; - cmd->params = g_strsplit(param_start, " ", 0); - } - - if (cmd->params != NULL) - { - int c; - - for (c = 0; cmd->params[c]; c++); - cmd->param_count = c; - - if (cmd->param_count) { - char *param = cmd->params[0]; - cmd->trId = is_num(param) ? atoi(param) : 0; - } else { - cmd->trId = 0; - } - } - else - cmd->trId = 0; - - msn_command_ref(cmd); - - return cmd; -} - -void -msn_command_destroy(MsnCommand *cmd) -{ - g_return_if_fail(cmd != NULL); - - if (cmd->ref_count > 0) - { - msn_command_unref(cmd); - return; - } - - if (cmd->payload != NULL) - g_free(cmd->payload); - - g_free(cmd->command); - g_strfreev(cmd->params); - g_free(cmd); -} - -MsnCommand * -msn_command_ref(MsnCommand *cmd) -{ - g_return_val_if_fail(cmd != NULL, NULL); - - cmd->ref_count++; - return cmd; -} - -MsnCommand * -msn_command_unref(MsnCommand *cmd) -{ - g_return_val_if_fail(cmd != NULL, NULL); - g_return_val_if_fail(cmd->ref_count > 0, NULL); - - cmd->ref_count--; - - if (cmd->ref_count == 0) - { - msn_command_destroy(cmd); - return NULL; - } - - return cmd; -}
--- a/libpurple/protocols/msnp9/command.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/** - * @file command.h MSN command functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_COMMAND_H -#define _MSN_COMMAND_H - -typedef struct _MsnCommand MsnCommand; - -#include "cmdproc.h" -#include "transaction.h" - -typedef void (*MsnPayloadCb)(MsnCmdProc *cmdproc, MsnCommand *cmd, - char *payload, size_t len); - -/** - * A received command. - */ -struct _MsnCommand -{ - unsigned int trId; - - char *command; - char **params; - int param_count; - - int ref_count; - - MsnTransaction *trans; - - char *payload; - size_t payload_len; - - MsnPayloadCb payload_cb; -}; - -MsnCommand *msn_command_from_string(const char *string); -void msn_command_destroy(MsnCommand *cmd); -MsnCommand *msn_command_ref(MsnCommand *cmd); -MsnCommand *msn_command_unref(MsnCommand *cmd); - -#endif /* _MSN_COMMAND_H */
--- a/libpurple/protocols/msnp9/dialog.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -/** - * @file dialog.c Dialog functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include "msn.h" -#include "dialog.h" - -typedef struct -{ - PurpleConnection *gc; - char *who; - char *group; - gboolean add; - -} MsnAddRemData; - -/* Remove the buddy referenced by the MsnAddRemData before the serverside list is changed. - * If the buddy will be added, he'll be added back; if he will be removed, he won't be. */ -static void -msn_complete_sync_issue(MsnAddRemData *data) -{ - PurpleBuddy *buddy; - PurpleGroup *group = NULL; - - if (data->group != NULL) - group = purple_find_group(data->group); - - if (group != NULL) - buddy = purple_find_buddy_in_group(purple_connection_get_account(data->gc), data->who, group); - else - buddy = purple_find_buddy(purple_connection_get_account(data->gc), data->who); - - if (buddy != NULL) - purple_blist_remove_buddy(buddy); -} - -static void -msn_add_cb(MsnAddRemData *data) -{ - MsnSession *session; - MsnUserList *userlist; - - msn_complete_sync_issue(data); - - session = data->gc->proto_data; - userlist = session->userlist; - - msn_userlist_add_buddy(userlist, data->who, MSN_LIST_FL, data->group); - - g_free(data->group); - g_free(data->who); - g_free(data); -} - -static void -msn_rem_cb(MsnAddRemData *data) -{ - MsnSession *session; - MsnUserList *userlist; - - msn_complete_sync_issue(data); - - session = data->gc->proto_data; - userlist = session->userlist; - - msn_userlist_rem_buddy(userlist, data->who, MSN_LIST_FL, data->group); - - g_free(data->group); - g_free(data->who); - g_free(data); -} - -void -msn_show_sync_issue(MsnSession *session, const char *passport, - const char *group_name) -{ - PurpleConnection *gc; - PurpleAccount *account; - MsnAddRemData *data; - char *msg, *reason; - - account = session->account; - gc = purple_account_get_connection(account); - - data = g_new0(MsnAddRemData, 1); - data->who = g_strdup(passport); - data->group = g_strdup(group_name); - data->gc = gc; - - msg = g_strdup_printf(_("Buddy list synchronization issue in %s (%s)"), - purple_account_get_username(account), - purple_account_get_protocol_name(account)); - - if (group_name != NULL) - { - reason = g_strdup_printf(_("%s on the local list is " - "inside the group \"%s\" but not on " - "the server list. " - "Do you want this buddy to be added?"), - passport, group_name); - } - else - { - reason = g_strdup_printf(_("%s is on the local list but " - "not on the server list. " - "Do you want this buddy to be added?"), - passport); - } - - purple_request_action(gc, NULL, msg, reason, PURPLE_DEFAULT_ACTION_NONE, - purple_connection_get_account(gc), data->who, NULL, - data, 2, - _("Yes"), G_CALLBACK(msn_add_cb), - _("No"), G_CALLBACK(msn_rem_cb)); - - g_free(reason); - g_free(msg); -}
--- a/libpurple/protocols/msnp9/dialog.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/** - * @file dialog.h Dialog functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_DIALOG_H_ -#define _MSN_DIALOG_H_ - -void msn_show_sync_issue(MsnSession *session, const char *passport, - const char *group_name); - -#endif /* _MSN_DIALOG_H_ */
--- a/libpurple/protocols/msnp9/directconn.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,505 +0,0 @@ -/** - * @file directconn.c MSN direct connection functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "directconn.h" - -#include "slp.h" -#include "slpmsg.h" - -/************************************************************************** - * Directconn Specific - **************************************************************************/ - -void -msn_directconn_send_handshake(MsnDirectConn *directconn) -{ - MsnSlpLink *slplink; - MsnSlpMessage *slpmsg; - - g_return_if_fail(directconn != NULL); - - slplink = directconn->slplink; - - slpmsg = msn_slpmsg_new(slplink); - slpmsg->flags = 0x100; - - if (directconn->nonce != NULL) - { - guint32 t1; - guint16 t2; - guint16 t3; - guint16 t4; - guint64 t5; - - sscanf (directconn->nonce, "%08X-%04hX-%04hX-%04hX-%012" G_GINT64_MODIFIER "X", &t1, &t2, &t3, &t4, &t5); - - t1 = GUINT32_TO_LE(t1); - t2 = GUINT16_TO_LE(t2); - t3 = GUINT16_TO_LE(t3); - t4 = GUINT16_TO_BE(t4); - t5 = GUINT64_TO_BE(t5); - - slpmsg->ack_id = t1; - slpmsg->ack_sub_id = t2 | (t3 << 16); - slpmsg->ack_size = t4 | t5; - } - - g_free(directconn->nonce); - - msn_slplink_send_slpmsg(slplink, slpmsg); - - directconn->acked =TRUE; -} - -/************************************************************************** - * Connection Functions - **************************************************************************/ - -#if 0 -static int -create_listener(int port) -{ - int fd; - int flags; - const int on = 1; - -#if 0 - struct addrinfo hints; - struct addrinfo *c, *res; - char port_str[5]; - - snprintf(port_str, sizeof(port_str), "%d", port); - - memset(&hints, 0, sizeof(hints)); - - hints.ai_flags = AI_PASSIVE; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - if (getaddrinfo(NULL, port_str, &hints, &res) != 0) - { - purple_debug_error("msn", "Could not get address info: %s.\n", - port_str); - return -1; - } - - for (c = res; c != NULL; c = c->ai_next) - { - fd = socket(c->ai_family, c->ai_socktype, c->ai_protocol); - - if (fd < 0) - continue; - - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - - if (bind(fd, c->ai_addr, c->ai_addrlen) == 0) - break; - - close(fd); - } - - if (c == NULL) - { - purple_debug_error("msn", "Could not find socket: %s.\n", port_str); - return -1; - } - - freeaddrinfo(res); -#else - struct sockaddr_in sockin; - - fd = socket(AF_INET, SOCK_STREAM, 0); - - if (fd < 0) - return -1; - - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) - { - close(fd); - return -1; - } - - memset(&sockin, 0, sizeof(struct sockaddr_in)); - sockin.sin_family = AF_INET; - sockin.sin_port = htons(port); - - if (bind(fd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) - { - close(fd); - return -1; - } -#endif - - if (listen (fd, 4) != 0) - { - close (fd); - return -1; - } - - flags = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); -#ifndef _WIN32 - fcntl(fd, F_SETFD, FD_CLOEXEC); -#endif - - return fd; -} -#endif - -static size_t -msn_directconn_write(MsnDirectConn *directconn, - const char *data, size_t len) -{ - char *buffer, *tmp; - size_t buf_size; - size_t ret; - guint32 sent_len; - - g_return_val_if_fail(directconn != NULL, 0); - - buf_size = len + 4; - buffer = tmp = g_malloc(buf_size); - - sent_len = GUINT32_TO_LE(len); - - memcpy(tmp, &sent_len, 4); - tmp += 4; - memcpy(tmp, data, len); - tmp += len; - - ret = write(directconn->fd, buffer, buf_size); - -#ifdef DEBUG_DC - char *str; - str = g_strdup_printf("%s/msntest/w%.4d.bin", g_get_home_dir(), directconn->c); - - FILE *tf = g_fopen(str, "w"); - fwrite(buffer, 1, buf_size, tf); - fclose(tf); - - g_free(str); -#endif - - g_free(buffer); - -#if 0 - /* Let's write the length of the data. */ - ret = write(directconn->fd, &len, sizeof(len)); - - /* Let's write the data. */ - ret = write(directconn->fd, data, len); - - char *str; - str = g_strdup_printf("/home/revo/msntest/w%.4d.bin", directconn->c); - - FILE *tf = g_fopen(str, "w"); - fwrite(&len, 1, sizeof(len), tf); - fwrite(data, 1, len, tf); - fclose(tf); - - g_free(str); -#endif - - directconn->c++; - - return ret; -} - -#if 0 -void -msn_directconn_parse_nonce(MsnDirectConn *directconn, const char *nonce) -{ - guint32 t1; - guint16 t2; - guint16 t3; - guint16 t4; - guint64 t5; - - g_return_if_fail(directconn != NULL); - g_return_if_fail(nonce != NULL); - - sscanf (nonce, "%08X-%04hX-%04hX-%04hX-%012llX", &t1, &t2, &t3, &t4, &t5); - - t1 = GUINT32_TO_LE(t1); - t2 = GUINT16_TO_LE(t2); - t3 = GUINT16_TO_LE(t3); - t4 = GUINT16_TO_BE(t4); - t5 = GUINT64_TO_BE(t5); - - directconn->slpheader = g_new0(MsnSlpHeader, 1); - - directconn->slpheader->ack_id = t1; - directconn->slpheader->ack_sub_id = t2 | (t3 << 16); - directconn->slpheader->ack_size = t4 | t5; -} -#endif - -void -msn_directconn_send_msg(MsnDirectConn *directconn, MsnMessage *msg) -{ - char *body; - size_t body_len; - - body = msn_message_gen_slp_body(msg, &body_len); - - msn_directconn_write(directconn, body, body_len); -} - -static void -msn_directconn_process_msg(MsnDirectConn *directconn, MsnMessage *msg) -{ - purple_debug_info("msn", "directconn: process_msg\n"); - - msn_slplink_process_msg(directconn->slplink, msg); -} - -static void -read_cb(gpointer data, gint source, PurpleInputCondition cond) -{ - MsnDirectConn* directconn; - char *body; - size_t len, body_len; - - purple_debug_info("msn", "read_cb: %d, %d\n", source, cond); - - directconn = data; - - /* Let's read the length of the data. */ - len = read(directconn->fd, &body_len, sizeof(body_len)); - - if (len <= 0) - { - /* ERROR */ - purple_debug_error("msn", "error reading\n"); - - msn_directconn_destroy(directconn); - - return; - } - - body_len = GUINT32_FROM_LE(body_len); - - purple_debug_info("msn", "body_len=%" G_GSIZE_FORMAT "\n", body_len); - - if (body_len <= 0) - { - /* ERROR */ - purple_debug_error("msn", "error reading\n"); - - msn_directconn_destroy(directconn); - - return; - } - - body = g_try_malloc(body_len); - - if (body != NULL) - { - /* Let's read the data. */ - len = read(directconn->fd, body, body_len); - - purple_debug_info("msn", "len=%" G_GSIZE_FORMAT "\n", len); - } - else - { - purple_debug_error("msn", "Failed to allocate memory for read\n"); - len = 0; - } - - if (len > 0) - { - MsnMessage *msg; - -#ifdef DEBUG_DC - str = g_strdup_printf("/home/revo/msntest/r%.4d.bin", directconn->c); - - FILE *tf = g_fopen(str, "w"); - fwrite(body, 1, len, tf); - fclose(tf); - - g_free(str); -#endif - - directconn->c++; - - msg = msn_message_new_msnslp(); - msn_message_parse_slp_body(msg, body, body_len); - - msn_directconn_process_msg(directconn, msg); - } - else - { - /* ERROR */ - purple_debug_error("msn", "error reading\n"); - - msn_directconn_destroy(directconn); - } - - g_free(body); -} - -static void -connect_cb(gpointer data, gint source, PurpleInputCondition cond) -{ - MsnDirectConn* directconn; - int fd; - - purple_debug_misc("msn", "directconn: connect_cb: %d\n", source); - - directconn = data; - directconn->connect_data = NULL; - - if (TRUE) - { - fd = source; - } - else - { - struct sockaddr_in client_addr; - socklen_t client; - fd = accept (source, (struct sockaddr *)&client_addr, &client); - } - - directconn->fd = fd; - - if (fd > 0) - { - directconn->inpa = purple_input_add(fd, PURPLE_INPUT_READ, read_cb, - directconn); - - if (TRUE) - { - /* Send foo. */ - msn_directconn_write(directconn, "foo", strlen("foo") + 1); - - /* Send Handshake */ - msn_directconn_send_handshake(directconn); - } - else - { - } - } - else - { - /* ERROR */ - purple_debug_error("msn", "could not add input\n"); - - if (directconn->inpa) - purple_input_remove(directconn->inpa); - - close(directconn->fd); - } -} - -static void -directconn_connect_cb(gpointer data, gint source, const gchar *error_message) -{ - if (error_message) - purple_debug_error("msn", "Error making direct connection: %s\n", error_message); - - connect_cb(data, source, PURPLE_INPUT_READ); -} - -gboolean -msn_directconn_connect(MsnDirectConn *directconn, const char *host, int port) -{ - MsnSession *session; - - g_return_val_if_fail(directconn != NULL, FALSE); - g_return_val_if_fail(host != NULL, TRUE); - g_return_val_if_fail(port > 0, FALSE); - - session = directconn->slplink->session; - -#if 0 - if (session->http_method) - { - servconn->http_data->gateway_host = g_strdup(host); - } -#endif - - directconn->connect_data = purple_proxy_connect(NULL, session->account, - host, port, directconn_connect_cb, directconn); - - return (directconn->connect_data != NULL); -} - -#if 0 -void -msn_directconn_listen(MsnDirectConn *directconn) -{ - int port; - int fd; - - port = 7000; - - for (fd = -1; fd < 0;) - fd = create_listener(++port); - - directconn->fd = fd; - - directconn->inpa = purple_input_add(fd, PURPLE_INPUT_READ, connect_cb, - directconn); - - directconn->port = port; - directconn->c = 0; -} -#endif - -MsnDirectConn* -msn_directconn_new(MsnSlpLink *slplink) -{ - MsnDirectConn *directconn; - - directconn = g_new0(MsnDirectConn, 1); - - directconn->slplink = slplink; - - if (slplink->directconn != NULL) - purple_debug_info("msn", "got_transresp: LEAK\n"); - - slplink->directconn = directconn; - - return directconn; -} - -void -msn_directconn_destroy(MsnDirectConn *directconn) -{ - if (directconn->connect_data != NULL) - purple_proxy_connect_cancel(directconn->connect_data); - - if (directconn->inpa != 0) - purple_input_remove(directconn->inpa); - - if (directconn->fd >= 0) - close(directconn->fd); - - if (directconn->nonce != NULL) - g_free(directconn->nonce); - - directconn->slplink->directconn = NULL; - - g_free(directconn); -}
--- a/libpurple/protocols/msnp9/directconn.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** - * @file directconn.h MSN direct connection functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_DIRECTCONN_H_ -#define _MSN_DIRECTCONN_H_ - -typedef struct _MsnDirectConn MsnDirectConn; - -#include "slplink.h" -#include "slp.h" -#include "msg.h" - -struct _MsnDirectConn -{ - MsnSlpLink *slplink; - MsnSlpCall *initial_call; - - PurpleProxyConnectData *connect_data; - - gboolean acked; - - char *nonce; - - int fd; - - int port; - int inpa; - - int c; -}; - -MsnDirectConn *msn_directconn_new(MsnSlpLink *slplink); -gboolean msn_directconn_connect(MsnDirectConn *directconn, - const char *host, int port); -#if 0 -void msn_directconn_listen(MsnDirectConn *directconn); -#endif -void msn_directconn_send_msg(MsnDirectConn *directconn, MsnMessage *msg); -void msn_directconn_parse_nonce(MsnDirectConn *directconn, const char *nonce); -void msn_directconn_destroy(MsnDirectConn *directconn); -void msn_directconn_send_handshake(MsnDirectConn *directconn); - -#endif /* _MSN_DIRECTCONN_H_ */
--- a/libpurple/protocols/msnp9/error.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,269 +0,0 @@ -/** - * @file error.c Error functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "error.h" - -const char * -msn_error_get_text(unsigned int type, gboolean *debug) -{ - static char msg[MSN_BUF_LEN]; - *debug = FALSE; - - switch (type) { - case 0: - g_snprintf(msg, sizeof(msg), - _("Unable to parse message")); - *debug = TRUE; - break; - case 200: - g_snprintf(msg, sizeof(msg), - _("Syntax Error (probably a client bug)")); - *debug = TRUE; - break; - case 201: - g_snprintf(msg, sizeof(msg), - _("Invalid email address")); - break; - case 205: - g_snprintf(msg, sizeof(msg), _("User does not exist")); - break; - case 206: - g_snprintf(msg, sizeof(msg), - _("Fully qualified domain name missing")); - break; - case 207: - g_snprintf(msg, sizeof(msg), _("Already logged in")); - break; - case 208: - g_snprintf(msg, sizeof(msg), _("Invalid username")); - break; - case 209: - g_snprintf(msg, sizeof(msg), _("Invalid friendly name")); - break; - case 210: - g_snprintf(msg, sizeof(msg), _("List full")); - break; - case 215: - g_snprintf(msg, sizeof(msg), _("Already there")); - *debug = TRUE; - break; - case 216: - g_snprintf(msg, sizeof(msg), _("Not on list")); - break; - case 217: - g_snprintf(msg, sizeof(msg), _("User is offline")); - break; - case 218: - g_snprintf(msg, sizeof(msg), _("Already in the mode")); - *debug = TRUE; - break; - case 219: - g_snprintf(msg, sizeof(msg), _("Already in opposite list")); - *debug = TRUE; - break; - case 223: - g_snprintf(msg, sizeof(msg), _("Too many groups")); - break; - case 224: - g_snprintf(msg, sizeof(msg), _("Invalid group")); - break; - case 225: - g_snprintf(msg, sizeof(msg), _("User not in group")); - break; - case 229: - g_snprintf(msg, sizeof(msg), _("Group name too long")); - break; - case 230: - g_snprintf(msg, sizeof(msg), _("Cannot remove group zero")); - *debug = TRUE; - break; - case 231: - g_snprintf(msg, sizeof(msg), - _("Tried to add a user to a group " - "that doesn't exist")); - break; - case 280: - g_snprintf(msg, sizeof(msg), _("Switchboard failed")); - *debug = TRUE; - break; - case 281: - g_snprintf(msg, sizeof(msg), _("Notify transfer failed")); - *debug = TRUE; - break; - - case 300: - g_snprintf(msg, sizeof(msg), _("Required fields missing")); - *debug = TRUE; - break; - case 301: - g_snprintf(msg, sizeof(msg), _("Too many hits to a FND")); - *debug = TRUE; - break; - case 302: - g_snprintf(msg, sizeof(msg), _("Not logged in")); - break; - - case 500: - g_snprintf(msg, sizeof(msg), _("Service temporarily unavailable")); - break; - case 501: - g_snprintf(msg, sizeof(msg), _("Database server error")); - *debug = TRUE; - break; - case 502: - g_snprintf(msg, sizeof(msg), _("Command disabled")); - *debug = TRUE; - break; - case 510: - g_snprintf(msg, sizeof(msg), _("File operation error")); - *debug = TRUE; - break; - case 520: - g_snprintf(msg, sizeof(msg), _("Memory allocation error")); - *debug = TRUE; - break; - case 540: - g_snprintf(msg, sizeof(msg), _("Wrong CHL value sent to server")); - *debug = TRUE; - break; - - case 600: - g_snprintf(msg, sizeof(msg), _("Server busy")); - break; - case 601: - g_snprintf(msg, sizeof(msg), _("Server unavailable")); - break; - case 602: - g_snprintf(msg, sizeof(msg), _("Peer notification server down")); - *debug = TRUE; - break; - case 603: - g_snprintf(msg, sizeof(msg), _("Database connect error")); - *debug = TRUE; - break; - case 604: - g_snprintf(msg, sizeof(msg), - _("Server is going down (abandon ship)")); - break; - case 605: - g_snprintf(msg, sizeof(msg), _("Server unavailable")); - break; - - case 707: - g_snprintf(msg, sizeof(msg), _("Error creating connection")); - *debug = TRUE; - break; - case 710: - g_snprintf(msg, sizeof(msg), - _("CVR parameters are either unknown or not allowed")); - *debug = TRUE; - break; - case 711: - g_snprintf(msg, sizeof(msg), _("Unable to write")); - break; - case 712: - g_snprintf(msg, sizeof(msg), _("Session overload")); - *debug = TRUE; - break; - case 713: - g_snprintf(msg, sizeof(msg), _("User is too active")); - break; - case 714: - g_snprintf(msg, sizeof(msg), _("Too many sessions")); - break; - case 715: - g_snprintf(msg, sizeof(msg), _("Passport not verified")); - break; - case 717: - g_snprintf(msg, sizeof(msg), _("Bad friend file")); - *debug = TRUE; - break; - case 731: - g_snprintf(msg, sizeof(msg), _("Not expected")); - *debug = TRUE; - break; - - case 800: - g_snprintf(msg, sizeof(msg), - _("Friendly name changes too rapidly")); - break; - - case 910: - case 912: - case 918: - case 919: - case 921: - case 922: - g_snprintf(msg, sizeof(msg), _("Server too busy")); - break; - case 911: - case 917: - g_snprintf(msg, sizeof(msg), _("Authentication failed")); - break; - case 913: - g_snprintf(msg, sizeof(msg), _("Not allowed when offline")); - break; - case 914: - case 915: - case 916: - g_snprintf(msg, sizeof(msg), _("Server unavailable")); - break; - case 920: - g_snprintf(msg, sizeof(msg), _("Not accepting new users")); - break; - case 923: - g_snprintf(msg, sizeof(msg), - _("Kids Passport without parental consent")); - break; - case 924: - g_snprintf(msg, sizeof(msg), - _("Passport account not yet verified")); - break; - case 928: - g_snprintf(msg, sizeof(msg), _("Bad ticket")); - *debug = TRUE; - break; - - default: - g_snprintf(msg, sizeof(msg), _("Unknown Error Code %d"), type); - *debug = TRUE; - break; - } - - return msg; -} - -void -msn_error_handle(MsnSession *session, unsigned int type) -{ - char buf[MSN_BUF_LEN]; - gboolean debug; - - g_snprintf(buf, sizeof(buf), _("MSN Error: %s\n"), - msn_error_get_text(type, &debug)); - if (debug) - purple_debug_warning("msn", "error %d: %s\n", type, buf); - else - purple_notify_error(session->account->gc, NULL, buf, NULL); -}
--- a/libpurple/protocols/msnp9/error.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/** - * @file error.h Error functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_ERROR_H_ -#define _MSN_ERROR_H_ - -#include "session.h" - -/** - * Returns the string representation of an error type. - * - * @param type The error type. - * @param debug Whether this should be treated as a debug log message or a user-visible error - * - * @return The string representation of the error type. - */ -const char *msn_error_get_text(unsigned int type, gboolean *debug); - -/** - * Handles an error. - * - * @param session The current session. - * @param type The error type. - */ -void msn_error_handle(MsnSession *session, unsigned int type); - -#endif /* _MSN_ERROR_H_ */
--- a/libpurple/protocols/msnp9/group.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/** - * @file group.c Group functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "group.h" - -MsnGroup * -msn_group_new(MsnUserList *userlist, int id, const char *name) -{ - MsnGroup *group; - - g_return_val_if_fail(id >= 0, NULL); - g_return_val_if_fail(name != NULL, NULL); - - group = g_new0(MsnGroup, 1); - - msn_userlist_add_group(userlist, group); - - group->id = id; - group->name = g_strdup(name); - - return group; -} - -void -msn_group_destroy(MsnGroup *group) -{ - g_return_if_fail(group != NULL); - - g_free(group->name); - g_free(group); -} - -void -msn_group_set_id(MsnGroup *group, int id) -{ - g_return_if_fail(group != NULL); - g_return_if_fail(id >= 0); - - group->id = id; -} - -void -msn_group_set_name(MsnGroup *group, const char *name) -{ - g_return_if_fail(group != NULL); - g_return_if_fail(name != NULL); - - if (group->name != NULL) - g_free(group->name); - - group->name = g_strdup(name); -} - -int -msn_group_get_id(const MsnGroup *group) -{ - g_return_val_if_fail(group != NULL, -1); - - return group->id; -} - -const char * -msn_group_get_name(const MsnGroup *group) -{ - g_return_val_if_fail(group != NULL, NULL); - - return group->name; -}
--- a/libpurple/protocols/msnp9/group.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/** - * @file group.h Group functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_GROUP_H_ -#define _MSN_GROUP_H_ - -typedef struct _MsnGroup MsnGroup; - -#include <stdio.h> - -#include "session.h" -#include "user.h" - -#include "userlist.h" - -/** - * A group. - */ -struct _MsnGroup -{ - MsnSession *session; /**< The MSN session. */ - - int id; /**< The group ID. */ - char *name; /**< The name of the group. */ -}; - -/**************************************************************************/ -/** @name Group API */ -/**************************************************************************/ -/*@{*/ - -/** - * Creates a new group structure. - * - * @param session The MSN session. - * @param id The group ID. - * @param name The name of the group. - * - * @return A new group structure. - */ -MsnGroup *msn_group_new(MsnUserList *userlist, int id, const char *name); - -/** - * Destroys a group structure. - * - * @param group The group to destroy. - */ -void msn_group_destroy(MsnGroup *group); - -/** - * Sets the ID for a group. - * - * @param group The group. - * @param id The ID. - */ -void msn_group_set_id(MsnGroup *group, int id); - -/** - * Sets the name for a group. - * - * @param group The group. - * @param name The name. - */ -void msn_group_set_name(MsnGroup *group, const char *name); - -/** - * Returns the ID for a group. - * - * @param group The group. - * - * @return The ID. - */ -int msn_group_get_id(const MsnGroup *group); - -/** - * Returns the name for a group. - * - * @param group The group. - * - * @return The name. - */ -const char *msn_group_get_name(const MsnGroup *group); -#endif /* _MSN_GROUP_H_ */
--- a/libpurple/protocols/msnp9/history.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -/** - * @file history.c MSN history functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "history.h" - -MsnHistory * -msn_history_new(void) -{ - MsnHistory *history = g_new0(MsnHistory, 1); - - history->trId = 1; - - history->queue = g_queue_new(); - - return history; -} - -void -msn_history_destroy(MsnHistory *history) -{ - MsnTransaction *trans; - - while ((trans = g_queue_pop_head(history->queue)) != NULL) - msn_transaction_destroy(trans); - - g_queue_free(history->queue); - g_free(history); -} - -MsnTransaction * -msn_history_find(MsnHistory *history, unsigned int trId) -{ - MsnTransaction *trans; - GList *list; - - for (list = history->queue->head; list != NULL; list = list->next) - { - trans = list->data; - if (trans->trId == trId) - return trans; - } - - return NULL; -} - -void -msn_history_add(MsnHistory *history, MsnTransaction *trans) -{ - GQueue *queue; - - g_return_if_fail(history != NULL); - g_return_if_fail(trans != NULL); - - queue = history->queue; - - trans->trId = history->trId++; - - g_queue_push_tail(queue, trans); - - if (queue->length > MSN_HIST_ELEMS) - { - trans = g_queue_pop_head(queue); - msn_transaction_destroy(trans); - } -}
--- a/libpurple/protocols/msnp9/history.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/** - * @file history.h MSN history functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_HISTORY_H -#define _MSN_HISTORY_H - -#define MSN_HIST_ELEMS 0x30 - -typedef struct _MsnHistory MsnHistory; - -#include "transaction.h" - -/** - * The history. - */ -struct _MsnHistory -{ - GQueue *queue; - unsigned int trId; -}; - -MsnHistory *msn_history_new(void); -void msn_history_destroy(MsnHistory *history); -MsnTransaction *msn_history_find(MsnHistory *history, unsigned int triId); -void msn_history_add(MsnHistory *history, MsnTransaction *trans); - -#endif /* _MSN_HISTORY_H */
--- a/libpurple/protocols/msnp9/httpconn.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,775 +0,0 @@ -/** - * @file httpmethod.c HTTP connection method - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "debug.h" -#include "httpconn.h" - -typedef struct -{ - MsnHttpConn *httpconn; - char *body; - size_t body_len; -} MsnHttpQueueData; - -static void -msn_httpconn_process_queue(MsnHttpConn *httpconn) -{ - httpconn->waiting_response = FALSE; - - if (httpconn->queue != NULL) - { - MsnHttpQueueData *queue_data; - - queue_data = (MsnHttpQueueData *)httpconn->queue->data; - - httpconn->queue = g_list_remove(httpconn->queue, queue_data); - - msn_httpconn_write(queue_data->httpconn, - queue_data->body, - queue_data->body_len); - - g_free(queue_data->body); - g_free(queue_data); - } -} - -static gboolean -msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf, - size_t size, char **ret_buf, size_t *ret_size, - gboolean *error) -{ - const char *s, *c; - char *header, *body; - const char *body_start; - char *tmp; - size_t body_len = 0; - gboolean wasted = FALSE; - - g_return_val_if_fail(httpconn != NULL, FALSE); - g_return_val_if_fail(buf != NULL, FALSE); - g_return_val_if_fail(size > 0, FALSE); - g_return_val_if_fail(ret_buf != NULL, FALSE); - g_return_val_if_fail(ret_size != NULL, FALSE); - g_return_val_if_fail(error != NULL, FALSE); - -#if 0 - purple_debug_info("msn", "HTTP: parsing data {%s}\n", buf); -#endif - - /* Healthy defaults. */ - body = NULL; - - *ret_buf = NULL; - *ret_size = 0; - *error = FALSE; - - /* First, some tests to see if we have a full block of stuff. */ - if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) && - (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) && - ((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) && - (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0))) - { - *error = TRUE; - - return FALSE; - } - - if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0) - { - if ((s = strstr(buf, "\r\n\r\n")) == NULL) - return FALSE; - - s += 4; - - if (*s == '\0') - { - *ret_buf = g_strdup(""); - *ret_size = 0; - - msn_httpconn_process_queue(httpconn); - - return TRUE; - } - - buf = s; - size -= (s - buf); - } - - if ((s = strstr(buf, "\r\n\r\n")) == NULL) - /* Need to wait for the full HTTP header to arrive */ - return FALSE; - - s += 4; /* Skip \r\n */ - header = g_strndup(buf, s - buf); - body_start = s; - body_len = size - (body_start - buf); - - if ((s = purple_strcasestr(header, "Content-Length: ")) != NULL) - { - int tmp_len; - - s += strlen("Content-Length: "); - - if ((c = strchr(s, '\r')) == NULL) - { - g_free(header); - - return FALSE; - } - - tmp = g_strndup(s, c - s); - tmp_len = atoi(tmp); - g_free(tmp); - - if (body_len != tmp_len) - { - /* Need to wait for the full packet to arrive */ - - g_free(header); - -#if 0 - purple_debug_warning("msn", - "body length (%d) != content length (%d)\n", - body_len, tmp_len); -#endif - - return FALSE; - } - } - - body = g_malloc0(body_len + 1); - memcpy(body, body_start, body_len); - -#ifdef MSN_DEBUG_HTTP - purple_debug_misc("msn", "Incoming HTTP buffer (header): {%s\r\n}\n", - header); -#endif - - /* Now we should be able to process the data. */ - if ((s = purple_strcasestr(header, "X-MSN-Messenger: ")) != NULL) - { - char *full_session_id, *gw_ip, *session_action; - char *t, *session_id; - char **elems, **cur, **tokens; - - full_session_id = gw_ip = session_action = NULL; - - s += strlen("X-MSN-Messenger: "); - - if ((c = strchr(s, '\r')) == NULL) - { - msn_session_set_error(httpconn->session, - MSN_ERROR_HTTP_MALFORMED, NULL); - purple_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}\n", - buf); - - g_free(body); - return FALSE; - } - - tmp = g_strndup(s, c - s); - - elems = g_strsplit(tmp, "; ", 0); - - for (cur = elems; *cur != NULL; cur++) - { - tokens = g_strsplit(*cur, "=", 2); - - if (strcmp(tokens[0], "SessionID") == 0) - full_session_id = tokens[1]; - else if (strcmp(tokens[0], "GW-IP") == 0) - gw_ip = tokens[1]; - else if (strcmp(tokens[0], "Session") == 0) - session_action = tokens[1]; - else - g_free(tokens[1]); - - g_free(tokens[0]); - /* Don't free each of the tokens, only the array. */ - g_free(tokens); - } - - g_strfreev(elems); - - g_free(tmp); - - if ((session_action != NULL) && (strcmp(session_action, "close") == 0)) - wasted = TRUE; - - g_free(session_action); - - t = strchr(full_session_id, '.'); - session_id = g_strndup(full_session_id, t - full_session_id); - - if (!wasted) - { - g_free(httpconn->full_session_id); - httpconn->full_session_id = full_session_id; - - g_free(httpconn->session_id); - httpconn->session_id = session_id; - - g_free(httpconn->host); - httpconn->host = gw_ip; - } - else - { - MsnServConn *servconn; - - /* It's going to die. */ - /* poor thing */ - - servconn = httpconn->servconn; - - /* I'll be honest, I don't fully understand all this, but this - * causes crashes, Stu. */ - /* if (servconn != NULL) - servconn->wasted = TRUE; */ - - g_free(full_session_id); - g_free(session_id); - g_free(gw_ip); - } - } - - g_free(header); - - *ret_buf = body; - *ret_size = body_len; - - msn_httpconn_process_queue(httpconn); - - return TRUE; -} - -static void -read_cb(gpointer data, gint source, PurpleInputCondition cond) -{ - MsnHttpConn *httpconn; - MsnServConn *servconn; - MsnSession *session; - char buf[MSN_BUF_LEN]; - char *cur, *end, *old_rx_buf; - int len, cur_len; - char *result_msg = NULL; - size_t result_len = 0; - gboolean error = FALSE; - - httpconn = data; - servconn = NULL; - session = httpconn->session; - - len = read(httpconn->fd, buf, sizeof(buf) - 1); - - if (len < 0 && errno == EAGAIN) - return; - else if (len <= 0) - { - purple_debug_error("msn", "HTTP: Read error\n"); - msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); - - return; - } - - buf[len] = '\0'; - - httpconn->rx_buf = g_realloc(httpconn->rx_buf, len + httpconn->rx_len + 1); - memcpy(httpconn->rx_buf + httpconn->rx_len, buf, len + 1); - httpconn->rx_len += len; - - if (!msn_httpconn_parse_data(httpconn, httpconn->rx_buf, httpconn->rx_len, - &result_msg, &result_len, &error)) - { - /* Either we must wait for more input, or something went wrong */ - if (error) - msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); - - return; - } - - httpconn->servconn->processing = FALSE; - - servconn = httpconn->servconn; - - if (error) - { - purple_debug_error("msn", "HTTP: Special error\n"); - msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); - - return; - } - - g_free(httpconn->rx_buf); - httpconn->rx_buf = NULL; - httpconn->rx_len = 0; - - if (result_len == 0) - { - /* Nothing to do here */ -#if 0 - purple_debug_info("msn", "HTTP: nothing to do here\n"); -#endif - g_free(result_msg); - return; - } - - g_free(servconn->rx_buf); - servconn->rx_buf = result_msg; - servconn->rx_len = result_len; - - end = old_rx_buf = servconn->rx_buf; - - servconn->processing = TRUE; - - do - { - cur = end; - - if (servconn->payload_len) - { - if (servconn->payload_len > servconn->rx_len) - /* The payload is still not complete. */ - break; - - cur_len = servconn->payload_len; - end += cur_len; - } - else - { - end = strstr(cur, "\r\n"); - - if (end == NULL) - /* The command is still not complete. */ - break; - - *end = '\0'; - end += 2; - cur_len = end - cur; - } - - servconn->rx_len -= cur_len; - - if (servconn->payload_len) - { - msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len); - servconn->payload_len = 0; - } - else - { - msn_cmdproc_process_cmd_text(servconn->cmdproc, cur); - } - } while (servconn->connected && servconn->rx_len > 0); - - if (servconn->connected) - { - if (servconn->rx_len > 0) - servconn->rx_buf = g_memdup(cur, servconn->rx_len); - else - servconn->rx_buf = NULL; - } - - servconn->processing = FALSE; - - if (servconn->wasted) - msn_servconn_destroy(servconn); - - g_free(old_rx_buf); -} - -static void -httpconn_write_cb(gpointer data, gint source, PurpleInputCondition cond) -{ - MsnHttpConn *httpconn; - int ret, writelen; - - httpconn = data; - writelen = purple_circ_buffer_get_max_read(httpconn->tx_buf); - - if (writelen == 0) - { - purple_input_remove(httpconn->tx_handler); - httpconn->tx_handler = 0; - return; - } - - ret = write(httpconn->fd, httpconn->tx_buf->outptr, writelen); - if (ret <= 0) - { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) - /* No worries */ - return; - - /* Error! */ - msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE); - return; - } - - purple_circ_buffer_mark_read(httpconn->tx_buf, ret); - - /* TODO: I don't think these 2 lines are needed. Remove them? */ - if (ret == writelen) - httpconn_write_cb(data, source, cond); -} - -static gboolean -write_raw(MsnHttpConn *httpconn, const char *data, size_t data_len) -{ - ssize_t res; /* result of the write operation */ - - if (httpconn->tx_handler == 0) - res = write(httpconn->fd, data, data_len); - else - { - res = -1; - errno = EAGAIN; - } - - if ((res <= 0) && ((errno != EAGAIN) && (errno != EWOULDBLOCK))) - { - msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE); - return FALSE; - } - - if (res < 0 || res < data_len) - { - if (res < 0) - res = 0; - if (httpconn->tx_handler == 0 && httpconn->fd) - httpconn->tx_handler = purple_input_add(httpconn->fd, - PURPLE_INPUT_WRITE, httpconn_write_cb, httpconn); - purple_circ_buffer_append(httpconn->tx_buf, data + res, - data_len - res); - } - - return TRUE; -} - -static char * -msn_httpconn_proxy_auth(MsnHttpConn *httpconn) -{ - PurpleAccount *account; - PurpleProxyInfo *gpi; - const char *username, *password; - char *auth = NULL; - - account = httpconn->session->account; - - gpi = purple_proxy_get_setup(account); - - if (gpi == NULL || !(purple_proxy_info_get_type(gpi) == PURPLE_PROXY_HTTP || - purple_proxy_info_get_type(gpi) == PURPLE_PROXY_USE_ENVVAR)) - return NULL; - - username = purple_proxy_info_get_username(gpi); - password = purple_proxy_info_get_password(gpi); - - if (username != NULL) { - char *tmp; - auth = g_strdup_printf("%s:%s", username, password ? password : ""); - tmp = purple_base64_encode((const guchar *)auth, strlen(auth)); - g_free(auth); - auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp); - g_free(tmp); - } - - return auth; -} - -static gboolean -msn_httpconn_poll(gpointer data) -{ - MsnHttpConn *httpconn; - char *header; - char *auth; - - httpconn = data; - - g_return_val_if_fail(httpconn != NULL, FALSE); - - if ((httpconn->host == NULL) || (httpconn->full_session_id == NULL)) - { - /* There's no need to poll if the session is not fully established */ - return TRUE; - } - - if (httpconn->waiting_response) - { - /* There's no need to poll if we're already waiting for a response */ - return TRUE; - } - - auth = msn_httpconn_proxy_auth(httpconn); - - header = g_strdup_printf( - "POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n" - "Accept: */*\r\n" - "Accept-Language: en-us\r\n" - "User-Agent: MSMSGS\r\n" - "Host: %s\r\n" - "Proxy-Connection: Keep-Alive\r\n" - "%s" /* Proxy auth */ - "Connection: Keep-Alive\r\n" - "Pragma: no-cache\r\n" - "Content-Type: application/x-msn-messenger\r\n" - "Content-Length: 0\r\n\r\n", - httpconn->host, - httpconn->full_session_id, - httpconn->host, - auth ? auth : ""); - - g_free(auth); - - if (write_raw(httpconn, header, strlen(header))) - httpconn->waiting_response = TRUE; - - g_free(header); - - return TRUE; -} - -ssize_t -msn_httpconn_write(MsnHttpConn *httpconn, const char *body, size_t body_len) -{ - char *params; - char *data; - int header_len; - char *auth; - const char *server_types[] = { "NS", "SB" }; - const char *server_type; - char *host; - MsnServConn *servconn; - - /* TODO: remove http data from servconn */ - - g_return_val_if_fail(httpconn != NULL, 0); - g_return_val_if_fail(body != NULL, 0); - g_return_val_if_fail(body_len > 0, 0); - - servconn = httpconn->servconn; - - if (httpconn->waiting_response) - { - MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1); - - queue_data->httpconn = httpconn; - queue_data->body = g_memdup(body, body_len); - queue_data->body_len = body_len; - - httpconn->queue = g_list_append(httpconn->queue, queue_data); - - return body_len; - } - - server_type = server_types[servconn->type]; - - if (httpconn->virgin) - { - host = "gateway.messenger.hotmail.com"; - - /* The first time servconn->host is the host we should connect to. */ - params = g_strdup_printf("Action=open&Server=%s&IP=%s", - server_type, - servconn->host); - httpconn->virgin = FALSE; - } - else - { - /* The rest of the times servconn->host is the gateway host. */ - host = httpconn->host; - - if (host == NULL || httpconn->full_session_id == NULL) - { - purple_debug_warning("msn", "Attempted HTTP write before session is established\n"); - return -1; - } - - params = g_strdup_printf("SessionID=%s", - httpconn->full_session_id); - } - - auth = msn_httpconn_proxy_auth(httpconn); - - data = g_strdup_printf( - "POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n" - "Accept: */*\r\n" - "Accept-Language: en-us\r\n" - "User-Agent: MSMSGS\r\n" - "Host: %s\r\n" - "Proxy-Connection: Keep-Alive\r\n" - "%s" /* Proxy auth */ - "Connection: Keep-Alive\r\n" - "Pragma: no-cache\r\n" - "Content-Type: application/x-msn-messenger\r\n" - "Content-Length: %d\r\n\r\n", - host, - params, - host, - auth ? auth : "", - (int) body_len); - - g_free(params); - - g_free(auth); - - header_len = strlen(data); - data = g_realloc(data, header_len + body_len); - memcpy(data + header_len, body, body_len); - - if (write_raw(httpconn, data, header_len + body_len)) - httpconn->waiting_response = TRUE; - - g_free(data); - - return body_len; -} - -MsnHttpConn * -msn_httpconn_new(MsnServConn *servconn) -{ - MsnHttpConn *httpconn; - - g_return_val_if_fail(servconn != NULL, NULL); - - httpconn = g_new0(MsnHttpConn, 1); - - purple_debug_info("msn", "new httpconn (%p)\n", httpconn); - - /* TODO: Remove this */ - httpconn->session = servconn->session; - - httpconn->servconn = servconn; - - httpconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN); - httpconn->tx_handler = 0; - - return httpconn; -} - -void -msn_httpconn_destroy(MsnHttpConn *httpconn) -{ - g_return_if_fail(httpconn != NULL); - - purple_debug_info("msn", "destroy httpconn (%p)\n", httpconn); - - if (httpconn->connected) - msn_httpconn_disconnect(httpconn); - - g_free(httpconn->full_session_id); - - g_free(httpconn->session_id); - - g_free(httpconn->host); - - purple_circ_buffer_destroy(httpconn->tx_buf); - if (httpconn->tx_handler > 0) - purple_input_remove(httpconn->tx_handler); - - g_free(httpconn); -} - -static void -connect_cb(gpointer data, gint source, const gchar *error_message) -{ - MsnHttpConn *httpconn; - - httpconn = data; - httpconn->connect_data = NULL; - httpconn->fd = source; - - if (source >= 0) - { - httpconn->inpa = purple_input_add(httpconn->fd, PURPLE_INPUT_READ, - read_cb, data); - - httpconn->timer = purple_timeout_add_seconds(3, msn_httpconn_poll, httpconn); - - msn_httpconn_process_queue(httpconn); - } - else - { - purple_debug_error("msn", "HTTP: Connection error\n"); - msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_CONNECT); - } -} - -gboolean -msn_httpconn_connect(MsnHttpConn *httpconn, const char *host, int port) -{ - g_return_val_if_fail(httpconn != NULL, FALSE); - g_return_val_if_fail(host != NULL, FALSE); - g_return_val_if_fail(port > 0, FALSE); - - if (httpconn->connected) - msn_httpconn_disconnect(httpconn); - - httpconn->connect_data = purple_proxy_connect(NULL, httpconn->session->account, - host, 80, connect_cb, httpconn); - - if (httpconn->connect_data != NULL) - { - httpconn->waiting_response = TRUE; - httpconn->connected = TRUE; - } - - return httpconn->connected; -} - -void -msn_httpconn_disconnect(MsnHttpConn *httpconn) -{ - g_return_if_fail(httpconn != NULL); - - if (!httpconn->connected) - return; - - if (httpconn->connect_data != NULL) - { - purple_proxy_connect_cancel(httpconn->connect_data); - httpconn->connect_data = NULL; - } - - if (httpconn->timer) - { - purple_timeout_remove(httpconn->timer); - httpconn->timer = 0; - } - - if (httpconn->inpa > 0) - { - purple_input_remove(httpconn->inpa); - httpconn->inpa = 0; - } - - close(httpconn->fd); - httpconn->fd = -1; - - g_free(httpconn->rx_buf); - httpconn->rx_buf = NULL; - httpconn->rx_len = 0; - - httpconn->connected = FALSE; - - /* msn_servconn_disconnect(httpconn->servconn); */ -}
--- a/libpurple/protocols/msnp9/httpconn.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/** - * @file httpconn.h HTTP connection - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_HTTPCONN_H_ -#define _MSN_HTTPCONN_H_ - -typedef struct _MsnHttpConn MsnHttpConn; - -#include "circbuffer.h" -#include "servconn.h" - -/** - * An HTTP Connection. - */ -struct _MsnHttpConn -{ - MsnSession *session; /**< The MSN Session. */ - MsnServConn *servconn; /**< The connection object. */ - - PurpleProxyConnectData *connect_data; - - char *full_session_id; /**< The full session id. */ - char *session_id; /**< The trimmed session id. */ - - int timer; /**< The timer for polling. */ - - gboolean waiting_response; /**< The flag that states if we are waiting - a response from the server. */ - gboolean connected; /**< The flag that states if the connection is on. */ - gboolean virgin; /**< The flag that states if this connection - should specify the host (not gateway) to - connect to. */ - - char *host; /**< The HTTP gateway host. */ - GList *queue; /**< The queue of data chunks to write. */ - - int fd; /**< The connection's file descriptor. */ - guint inpa; /**< The connection's input handler. */ - - char *rx_buf; /**< The receive buffer. */ - int rx_len; /**< The receive buffer length. */ - - PurpleCircBuffer *tx_buf; - guint tx_handler; -}; - -/** - * Creates a new HTTP connection object. - * - * @param servconn The connection object. - * - * @return The new object. - */ -MsnHttpConn *msn_httpconn_new(MsnServConn *servconn); - -/** - * Destroys an HTTP connection object. - * - * @param httpconn The HTTP connection object. - */ -void msn_httpconn_destroy(MsnHttpConn *httpconn); - -/** - * Writes a chunk of data to the HTTP connection. - * - * @param servconn The server connection. - * @param data The data to write. - * @param data_len The size of the data to write. - * - * @return The number of bytes written. - */ -ssize_t msn_httpconn_write(MsnHttpConn *httpconn, const char *data, size_t data_len); - -/** - * Connects the HTTP connection object to a host. - * - * @param httpconn The HTTP connection object. - * @param host The host to connect to. - * @param port The port to connect to. - */ -gboolean msn_httpconn_connect(MsnHttpConn *httpconn, - const char *host, int port); - -/** - * Disconnects the HTTP connection object. - * - * @param httpconn The HTTP connection object. - */ -void msn_httpconn_disconnect(MsnHttpConn *httpconn); - -#endif /* _MSN_HTTPCONN_H_ */
--- a/libpurple/protocols/msnp9/msg.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,787 +0,0 @@ -/** - * @file msg.c Message functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "msg.h" - -MsnMessage * -msn_message_new(MsnMsgType type) -{ - MsnMessage *msg; - - msg = g_new0(MsnMessage, 1); - msg->type = type; - -#ifdef MSN_DEBUG_MSG - purple_debug_info("msn", "message new (%p)(%d)\n", msg, type); -#endif - - msg->attr_table = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - - msn_message_ref(msg); - - return msg; -} - -void -msn_message_destroy(MsnMessage *msg) -{ - g_return_if_fail(msg != NULL); - - if (msg->ref_count > 0) - { - msn_message_unref(msg); - - return; - } - -#ifdef MSN_DEBUG_MSG - purple_debug_info("msn", "message destroy (%p)\n", msg); -#endif - - if (msg->remote_user != NULL) - g_free(msg->remote_user); - - if (msg->body != NULL) - g_free(msg->body); - - if (msg->content_type != NULL) - g_free(msg->content_type); - - if (msg->charset != NULL) - g_free(msg->charset); - - g_hash_table_destroy(msg->attr_table); - g_list_free(msg->attr_list); - - g_free(msg); -} - -MsnMessage * -msn_message_ref(MsnMessage *msg) -{ - g_return_val_if_fail(msg != NULL, NULL); - - msg->ref_count++; - -#ifdef MSN_DEBUG_MSG - purple_debug_info("msn", "message ref (%p)[%d]\n", msg, msg->ref_count); -#endif - - return msg; -} - -MsnMessage * -msn_message_unref(MsnMessage *msg) -{ - g_return_val_if_fail(msg != NULL, NULL); - g_return_val_if_fail(msg->ref_count > 0, NULL); - - msg->ref_count--; - -#ifdef MSN_DEBUG_MSG - purple_debug_info("msn", "message unref (%p)[%d]\n", msg, msg->ref_count); -#endif - - if (msg->ref_count == 0) - { - msn_message_destroy(msg); - - return NULL; - } - - return msg; -} - -MsnMessage * -msn_message_new_plain(const char *message) -{ - MsnMessage *msg; - char *message_cr; - - msg = msn_message_new(MSN_MSG_TEXT); - msn_message_set_attr(msg, "User-Agent", PACKAGE_NAME "/" DISPLAY_VERSION); - msn_message_set_content_type(msg, "text/plain"); - msn_message_set_charset(msg, "UTF-8"); - msn_message_set_flag(msg, 'A'); - msn_message_set_attr(msg, "X-MMS-IM-Format", - "FN=MS%20Sans%20Serif; EF=; CO=0; PF=0"); - - message_cr = purple_str_add_cr(message); - msn_message_set_bin_data(msg, message_cr, strlen(message_cr)); - g_free(message_cr); - - return msg; -} - -MsnMessage * -msn_message_new_msnslp(void) -{ - MsnMessage *msg; - - msg = msn_message_new(MSN_MSG_SLP); - - msn_message_set_attr(msg, "User-Agent", NULL); - - msg->msnslp_message = TRUE; - - msn_message_set_flag(msg, 'D'); - msn_message_set_content_type(msg, "application/x-msnmsgrp2p"); - - return msg; -} - -MsnMessage * -msn_message_new_nudge(void) -{ - MsnMessage *msg; - - msg = msn_message_new(MSN_MSG_NUDGE); - msn_message_set_content_type(msg, "text/x-msnmsgr-datacast"); - msn_message_set_flag(msg, 'N'); - msn_message_set_bin_data(msg, "ID: 1\r\n", 7); - - return msg; -} - -void -msn_message_parse_slp_body(MsnMessage *msg, const char *body, size_t len) -{ - MsnSlpHeader header; - const char *tmp; - int body_len; - - tmp = body; - - if (len < sizeof(header)) { - g_return_if_reached(); - } - - /* Import the header. */ - memcpy(&header, tmp, sizeof(header)); - tmp += sizeof(header); - - msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id); - msg->msnslp_header.id = GUINT32_FROM_LE(header.id); - msg->msnslp_header.offset = GUINT64_FROM_LE(header.offset); - msg->msnslp_header.total_size = GUINT64_FROM_LE(header.total_size); - msg->msnslp_header.length = GUINT32_FROM_LE(header.length); - msg->msnslp_header.flags = GUINT32_FROM_LE(header.flags); - msg->msnslp_header.ack_id = GUINT32_FROM_LE(header.ack_id); - msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id); - msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size); - - /* Import the body. */ - body_len = len - (tmp - body); - /* msg->body_len = msg->msnslp_header.length; */ - - if (body_len > 0) { - msg->body_len = len - (tmp - body); - msg->body = g_malloc0(msg->body_len + 1); - memcpy(msg->body, tmp, msg->body_len); - tmp += body_len; - } -} - -void -msn_message_parse_payload(MsnMessage *msg, - const char *payload, size_t payload_len) -{ - char *tmp_base, *tmp; - const char *content_type; - char *end; - char **elems, **cur, **tokens; - - g_return_if_fail(payload != NULL); - - tmp_base = tmp = g_malloc0(payload_len + 1); - memcpy(tmp_base, payload, payload_len); - - /* Parse the attributes. */ - end = strstr(tmp, "\r\n\r\n"); - /* TODO? some clients use \r delimiters instead of \r\n, the official client - * doesn't send such messages, but does handle receiving them. We'll just - * avoid crashing for now */ - if (end == NULL) { - g_free(tmp_base); - g_return_if_reached(); - } - *end = '\0'; - - elems = g_strsplit(tmp, "\r\n", 0); - - for (cur = elems; *cur != NULL; cur++) - { - const char *key, *value; - - tokens = g_strsplit(*cur, ": ", 2); - - key = tokens[0]; - value = tokens[1]; - - if (!strcmp(key, "MIME-Version")) - { - g_strfreev(tokens); - continue; - } - - if (!strcmp(key, "Content-Type")) - { - char *charset, *c; - - if ((c = strchr(value, ';')) != NULL) - { - if ((charset = strchr(c, '=')) != NULL) - { - charset++; - msn_message_set_charset(msg, charset); - } - - *c = '\0'; - } - - msn_message_set_content_type(msg, value); - } - else - { - msn_message_set_attr(msg, key, value); - } - - g_strfreev(tokens); - } - - g_strfreev(elems); - - /* Proceed to the end of the "\r\n\r\n" */ - tmp = end + 4; - - /* Now we *should* be at the body. */ - content_type = msn_message_get_content_type(msg); - - if (content_type != NULL && - !strcmp(content_type, "application/x-msnmsgrp2p")) - { - MsnSlpHeader header; - MsnSlpFooter footer; - int body_len; - - if (payload_len - (tmp - tmp_base) < sizeof(header)) { - g_free(tmp_base); - g_return_if_reached(); - } - - msg->msnslp_message = TRUE; - - /* Import the header. */ - memcpy(&header, tmp, sizeof(header)); - tmp += sizeof(header); - - msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id); - msg->msnslp_header.id = GUINT32_FROM_LE(header.id); - msg->msnslp_header.offset = GUINT64_FROM_LE(header.offset); - msg->msnslp_header.total_size = GUINT64_FROM_LE(header.total_size); - msg->msnslp_header.length = GUINT32_FROM_LE(header.length); - msg->msnslp_header.flags = GUINT32_FROM_LE(header.flags); - msg->msnslp_header.ack_id = GUINT32_FROM_LE(header.ack_id); - msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id); - msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size); - - body_len = payload_len - (tmp - tmp_base) - sizeof(footer); - - /* Import the body. */ - if (body_len > 0) { - msg->body_len = body_len; - msg->body = g_malloc0(msg->body_len + 1); - memcpy(msg->body, tmp, msg->body_len); - tmp += body_len; - } - - /* Import the footer. */ - if (body_len >= 0) { - memcpy(&footer, tmp, sizeof(footer)); - tmp += sizeof(footer); - msg->msnslp_footer.value = GUINT32_FROM_BE(footer.value); - } - } - else - { - if (payload_len - (tmp - tmp_base) > 0) { - msg->body_len = payload_len - (tmp - tmp_base); - msg->body = g_malloc0(msg->body_len + 1); - memcpy(msg->body, tmp, msg->body_len); - } - } - - g_free(tmp_base); -} - -MsnMessage * -msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd) -{ - MsnMessage *msg; - - g_return_val_if_fail(cmd != NULL, NULL); - - msg = msn_message_new(MSN_MSG_UNKNOWN); - - msg->remote_user = g_strdup(cmd->params[0]); - /* msg->size = atoi(cmd->params[2]); */ - msg->cmd = cmd; - - return msg; -} - -char * -msn_message_gen_slp_body(MsnMessage *msg, size_t *ret_size) -{ - MsnSlpHeader header; - - char *tmp, *base; - const void *body; - size_t len, body_len; - - g_return_val_if_fail(msg != NULL, NULL); - - len = MSN_BUF_LEN; - - base = tmp = g_malloc(len + 1); - - body = msn_message_get_bin_data(msg, &body_len); - - header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id); - header.id = GUINT32_TO_LE(msg->msnslp_header.id); - header.offset = GUINT64_TO_LE(msg->msnslp_header.offset); - header.total_size = GUINT64_TO_LE(msg->msnslp_header.total_size); - header.length = GUINT32_TO_LE(msg->msnslp_header.length); - header.flags = GUINT32_TO_LE(msg->msnslp_header.flags); - header.ack_id = GUINT32_TO_LE(msg->msnslp_header.ack_id); - header.ack_sub_id = GUINT32_TO_LE(msg->msnslp_header.ack_sub_id); - header.ack_size = GUINT64_TO_LE(msg->msnslp_header.ack_size); - - memcpy(tmp, &header, 48); - tmp += 48; - - if (body != NULL) - { - memcpy(tmp, body, body_len); - tmp += body_len; - } - - if (ret_size != NULL) - *ret_size = tmp - base; - - return base; -} - -char * -msn_message_gen_payload(MsnMessage *msg, size_t *ret_size) -{ - GList *l; - char *n, *base, *end; - int len; - size_t body_len = 0; - const void *body; - - g_return_val_if_fail(msg != NULL, NULL); - - len = MSN_BUF_LEN; - - base = n = end = g_malloc(len + 1); - end += len; - - /* Standard header. */ - if (msg->charset == NULL) - { - g_snprintf(n, len, - "MIME-Version: 1.0\r\n" - "Content-Type: %s\r\n", - msg->content_type); - } - else - { - g_snprintf(n, len, - "MIME-Version: 1.0\r\n" - "Content-Type: %s; charset=%s\r\n", - msg->content_type, msg->charset); - } - - n += strlen(n); - - for (l = msg->attr_list; l != NULL; l = l->next) - { - const char *key; - const char *value; - - key = l->data; - value = msn_message_get_attr(msg, key); - - g_snprintf(n, end - n, "%s: %s\r\n", key, value); - n += strlen(n); - } - - n += g_strlcpy(n, "\r\n", end - n); - - body = msn_message_get_bin_data(msg, &body_len); - - if (msg->msnslp_message) - { - MsnSlpHeader header; - MsnSlpFooter footer; - - header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id); - header.id = GUINT32_TO_LE(msg->msnslp_header.id); - header.offset = GUINT64_TO_LE(msg->msnslp_header.offset); - header.total_size = GUINT64_TO_LE(msg->msnslp_header.total_size); - header.length = GUINT32_TO_LE(msg->msnslp_header.length); - header.flags = GUINT32_TO_LE(msg->msnslp_header.flags); - header.ack_id = GUINT32_TO_LE(msg->msnslp_header.ack_id); - header.ack_sub_id = GUINT32_TO_LE(msg->msnslp_header.ack_sub_id); - header.ack_size = GUINT64_TO_LE(msg->msnslp_header.ack_size); - - memcpy(n, &header, 48); - n += 48; - - if (body != NULL) - { - memcpy(n, body, body_len); - - n += body_len; - } - - footer.value = GUINT32_TO_BE(msg->msnslp_footer.value); - - memcpy(n, &footer, 4); - n += 4; - } - else - { - if (body != NULL) - { - memcpy(n, body, body_len); - n += body_len; - } - } - - if (ret_size != NULL) - { - *ret_size = n - base; - - if (*ret_size > 1664) - *ret_size = 1664; - } - - return base; -} - -void -msn_message_set_flag(MsnMessage *msg, char flag) -{ - g_return_if_fail(msg != NULL); - g_return_if_fail(flag != 0); - - msg->flag = flag; -} - -char -msn_message_get_flag(const MsnMessage *msg) -{ - g_return_val_if_fail(msg != NULL, 0); - - return msg->flag; -} - -void -msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len) -{ - g_return_if_fail(msg != NULL); - - /* There is no need to waste memory on data we cannot send anyway */ - if (len > 1664) - len = 1664; - - if (msg->body != NULL) - g_free(msg->body); - - if (data != NULL && len > 0) - { - msg->body = g_malloc0(len + 1); - memcpy(msg->body, data, len); - msg->body_len = len; - } - else - { - msg->body = NULL; - msg->body_len = 0; - } -} - -const void * -msn_message_get_bin_data(const MsnMessage *msg, size_t *len) -{ - g_return_val_if_fail(msg != NULL, NULL); - - if (len) - *len = msg->body_len; - - return msg->body; -} - -void -msn_message_set_content_type(MsnMessage *msg, const char *type) -{ - g_return_if_fail(msg != NULL); - - if (msg->content_type != NULL) - g_free(msg->content_type); - - msg->content_type = (type != NULL) ? g_strdup(type) : NULL; -} - -const char * -msn_message_get_content_type(const MsnMessage *msg) -{ - g_return_val_if_fail(msg != NULL, NULL); - - return msg->content_type; -} - -void -msn_message_set_charset(MsnMessage *msg, const char *charset) -{ - g_return_if_fail(msg != NULL); - - if (msg->charset != NULL) - g_free(msg->charset); - - msg->charset = (charset != NULL) ? g_strdup(charset) : NULL; -} - -const char * -msn_message_get_charset(const MsnMessage *msg) -{ - g_return_val_if_fail(msg != NULL, NULL); - - return msg->charset; -} - -void -msn_message_set_attr(MsnMessage *msg, const char *attr, const char *value) -{ - const char *temp; - char *new_attr; - - g_return_if_fail(msg != NULL); - g_return_if_fail(attr != NULL); - - temp = msn_message_get_attr(msg, attr); - - if (value == NULL) - { - if (temp != NULL) - { - GList *l; - - for (l = msg->attr_list; l != NULL; l = l->next) - { - if (!g_ascii_strcasecmp(l->data, attr)) - { - msg->attr_list = g_list_remove(msg->attr_list, l->data); - - break; - } - } - - g_hash_table_remove(msg->attr_table, attr); - } - - return; - } - - new_attr = g_strdup(attr); - - g_hash_table_insert(msg->attr_table, new_attr, g_strdup(value)); - - if (temp == NULL) - msg->attr_list = g_list_append(msg->attr_list, new_attr); -} - -const char * -msn_message_get_attr(const MsnMessage *msg, const char *attr) -{ - g_return_val_if_fail(msg != NULL, NULL); - g_return_val_if_fail(attr != NULL, NULL); - - return g_hash_table_lookup(msg->attr_table, attr); -} - -GHashTable * -msn_message_get_hashtable_from_body(const MsnMessage *msg) -{ - GHashTable *table; - size_t body_len; - const char *body; - char **elems, **cur, **tokens, *body_str; - - g_return_val_if_fail(msg != NULL, NULL); - - table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - - body = msn_message_get_bin_data(msg, &body_len); - - g_return_val_if_fail(body != NULL, NULL); - - body_str = g_strndup(body, body_len); - elems = g_strsplit(body_str, "\r\n", 0); - g_free(body_str); - - for (cur = elems; *cur != NULL; cur++) - { - if (**cur == '\0') - break; - - tokens = g_strsplit(*cur, ": ", 2); - - if (tokens[0] != NULL && tokens[1] != NULL) - g_hash_table_insert(table, tokens[0], tokens[1]); - - g_free(tokens); - } - - g_strfreev(elems); - - return table; -} - -char * -msn_message_to_string(MsnMessage *msg) -{ - size_t body_len; - const char *body; - - g_return_val_if_fail(msg != NULL, NULL); - g_return_val_if_fail(msg->type == MSN_MSG_TEXT, NULL); - - body = msn_message_get_bin_data(msg, &body_len); - - return g_strndup(body, body_len); -} - -void -msn_message_show_readable(MsnMessage *msg, const char *info, - gboolean text_body) -{ - GString *str; - size_t body_len; - const char *body; - GList *l; - - g_return_if_fail(msg != NULL); - - str = g_string_new(NULL); - - /* Standard header. */ - if (msg->charset == NULL) - { - g_string_append_printf(str, - "MIME-Version: 1.0\r\n" - "Content-Type: %s\r\n", - msg->content_type); - } - else - { - g_string_append_printf(str, - "MIME-Version: 1.0\r\n" - "Content-Type: %s; charset=%s\r\n", - msg->content_type, msg->charset); - } - - for (l = msg->attr_list; l; l = l->next) - { - char *key; - const char *value; - - key = l->data; - value = msn_message_get_attr(msg, key); - - g_string_append_printf(str, "%s: %s\r\n", key, value); - } - - g_string_append(str, "\r\n"); - - body = msn_message_get_bin_data(msg, &body_len); - - if (msg->msnslp_message) - { - g_string_append_printf(str, "Session ID: %u\r\n", msg->msnslp_header.session_id); - g_string_append_printf(str, "ID: %u\r\n", msg->msnslp_header.id); - g_string_append_printf(str, "Offset: %" G_GUINT64_FORMAT "\r\n", msg->msnslp_header.offset); - g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", msg->msnslp_header.total_size); - g_string_append_printf(str, "Length: %u\r\n", msg->msnslp_header.length); - g_string_append_printf(str, "Flags: 0x%x\r\n", msg->msnslp_header.flags); - g_string_append_printf(str, "ACK ID: %u\r\n", msg->msnslp_header.ack_id); - g_string_append_printf(str, "SUB ID: %u\r\n", msg->msnslp_header.ack_sub_id); - g_string_append_printf(str, "ACK Size: %" G_GUINT64_FORMAT "\r\n", msg->msnslp_header.ack_size); - -#ifdef MSN_DEBUG_SLP_VERBOSE - if (body != NULL) - { - if (text_body) - { - g_string_append_len(str, body, body_len); - if (body[body_len - 1] == '\0') - { - str->len--; - g_string_append(str, " 0x00"); - } - g_string_append(str, "\r\n"); - } - else - { - int i; - for (i = 0; i < msg->body_len; i++) - { - g_string_append_printf(str, "%.2hhX ", body[i]); - if ((i % 16) == 15) - g_string_append(str, "\r\n"); - } - g_string_append(str, "\r\n"); - } - } -#endif - - g_string_append_printf(str, "Footer: %u\r\n", msg->msnslp_footer.value); - } - else - { - if (body != NULL) - { - g_string_append_len(str, body, body_len); - g_string_append(str, "\r\n"); - } - } - - purple_debug_info("msn", "Message %s:\n{%s}\n", info, str->str); - - g_string_free(str, TRUE); -}
--- a/libpurple/protocols/msnp9/msg.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,349 +0,0 @@ -/** - * @file msg.h Message functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_MSG_H_ -#define _MSN_MSG_H_ - -typedef struct _MsnMessage MsnMessage; - -#include "session.h" -#include "user.h" - -#include "command.h" -#include "transaction.h" - -typedef void (*MsnMsgCb)(MsnMessage *, void *data); - -/* -typedef enum -{ - MSN_MSG_NORMAL, - MSN_MSG_SLP_SB, - MSN_MSG_SLP_DC - -} MsnMsgType; -*/ - -typedef enum -{ - MSN_MSG_UNKNOWN, - MSN_MSG_TEXT, - MSN_MSG_TYPING, - MSN_MSG_CAPS, - MSN_MSG_SLP, - MSN_MSG_NUDGE - -} MsnMsgType; - -typedef enum -{ - MSN_MSG_ERROR_NONE, /**< No error. */ - MSN_MSG_ERROR_TIMEOUT, /**< The message timedout. */ - MSN_MSG_ERROR_NAK, /**< The message could not be sent. */ - MSN_MSG_ERROR_SB, /**< The error comes from the switchboard. */ - MSN_MSG_ERROR_UNKNOWN /**< An unknown error occurred. */ - -} MsnMsgErrorType; - -typedef struct -{ - guint32 session_id; - guint32 id; - guint64 offset; - guint64 total_size; - guint32 length; - guint32 flags; - guint32 ack_id; - guint32 ack_sub_id; - guint64 ack_size; - -} MsnSlpHeader; - -typedef struct -{ - guint32 value; - -} MsnSlpFooter; - -/** - * A message. - */ -struct _MsnMessage -{ - size_t ref_count; /**< The reference count. */ - - MsnMsgType type; - - gboolean msnslp_message; - - char *remote_user; - char flag; - - char *content_type; - char *charset; - char *body; - gsize body_len; - - MsnSlpHeader msnslp_header; - MsnSlpFooter msnslp_footer; - - GHashTable *attr_table; - GList *attr_list; - - gboolean ack_ref; /**< A flag that states if this message has - been ref'ed for using it in a callback. */ - - MsnCommand *cmd; - MsnTransaction *trans; - - MsnMsgCb ack_cb; /**< The callback to call when we receive an ACK of this - message. */ - MsnMsgCb nak_cb; /**< The callback to call when we receive a NAK of this - message. */ - void *ack_data; /**< The data used by callbacks. */ - - MsnMsgErrorType error; /**< The error of the message. */ -}; - -/** - * Creates a new, empty message. - * - * @return A new message. - */ -MsnMessage *msn_message_new(MsnMsgType type); - -/** - * Creates a new, empty MSNSLP message. - * - * @return A new MSNSLP message. - */ -MsnMessage *msn_message_new_msnslp(void); - -/** - * Creates a new nudge message. - * - * @return A new nudge message. - */ -MsnMessage *msn_message_new_nudge(void); - -/** - * Creates a new plain message. - * - * @return A new plain message. - */ -MsnMessage *msn_message_new_plain(const char *message); - -/** - * Creates a MSNSLP ack message. - * - * @param acked_msg The message to acknowledge. - * - * @return A new MSNSLP ack message. - */ -MsnMessage *msn_message_new_msnslp_ack(MsnMessage *acked_msg); - -/** - * Creates a new message based off a command. - * - * @param session The MSN session. - * @param cmd The command. - * - * @return The new message. - */ -MsnMessage *msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd); - -/** - * Parses the payload of a message. - * - * @param msg The message. - * @param payload The payload. - * @param payload_len The length of the payload. - */ -void msn_message_parse_payload(MsnMessage *msg, const char *payload, - size_t payload_len); - -/** - * Destroys a message. - * - * @param msg The message to destroy. - */ -void msn_message_destroy(MsnMessage *msg); - -/** - * Increments the reference count on a message. - * - * @param msg The message. - * - * @return @a msg - */ -MsnMessage *msn_message_ref(MsnMessage *msg); - -/** - * Decrements the reference count on a message. - * - * This will destroy the structure if the count hits 0. - * - * @param msg The message. - * - * @return @a msg, or @c NULL if the new count is 0. - */ -MsnMessage *msn_message_unref(MsnMessage *msg); - -/** - * Generates the payload data of a message. - * - * @param msg The message. - * @param ret_size The returned size of the payload. - * - * @return The payload data of the message. - */ -char *msn_message_gen_payload(MsnMessage *msg, size_t *ret_size); - -/** - * Sets the flag for an outgoing message. - * - * @param msg The message. - * @param flag The flag. - */ -void msn_message_set_flag(MsnMessage *msg, char flag); - -/** - * Returns the flag for an outgoing message. - * - * @param msg The message. - * - * @return The flag. - */ -char msn_message_get_flag(const MsnMessage *msg); - -#if 0 -/** - * Sets the body of a message. - * - * @param msg The message. - * @param body The body of the message. - */ -void msn_message_set_body(MsnMessage *msg, const char *body); - -/** - * Returns the body of the message. - * - * @param msg The message. - * - * @return The body of the message. - */ -const char *msn_message_get_body(const MsnMessage *msg); -#endif -/** - * Sets the binary content of the message. - * - * @param msg The message. - * @param data The binary data. - * @param len The length of the data. - */ -void msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len); - -/** - * Returns the binary content of the message. - * - * @param msg The message. - * @param len The returned length of the data. - * - * @return The binary data. - */ -const void *msn_message_get_bin_data(const MsnMessage *msg, size_t *len); - -/** - * Sets the content type in a message. - * - * @param msg The message. - * @param type The content-type. - */ -void msn_message_set_content_type(MsnMessage *msg, const char *type); - -/** - * Returns the content type in a message. - * - * @param msg The message. - * - * @return The content-type. - */ -const char *msn_message_get_content_type(const MsnMessage *msg); - -/** - * Sets the charset in a message. - * - * @param msg The message. - * @param charset The charset. - */ -void msn_message_set_charset(MsnMessage *msg, const char *charset); - -/** - * Returns the charset in a message. - * - * @param msg The message. - * - * @return The charset. - */ -const char *msn_message_get_charset(const MsnMessage *msg); - -/** - * Sets an attribute in a message. - * - * @param msg The message. - * @param attr The attribute name. - * @param value The attribute value. - */ -void msn_message_set_attr(MsnMessage *msg, const char *attr, - const char *value); - -/** - * Returns an attribute from a message. - * - * @param msg The message. - * @param attr The attribute. - * - * @return The value, or @c NULL if not found. - */ -const char *msn_message_get_attr(const MsnMessage *msg, const char *attr); - -/** - * Parses the body and returns it in the form of a hashtable. - * - * @param msg The message. - * - * @return The resulting hashtable. - */ -GHashTable *msn_message_get_hashtable_from_body(const MsnMessage *msg); - -void msn_message_show_readable(MsnMessage *msg, const char *info, - gboolean text_body); - -void msn_message_parse_slp_body(MsnMessage *msg, const char *body, - size_t len); - -char *msn_message_gen_slp_body(MsnMessage *msg, size_t *ret_size); - -char *msn_message_to_string(MsnMessage *msg); - -#endif /* _MSN_MSG_H_ */
--- a/libpurple/protocols/msnp9/msn-utils.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,441 +0,0 @@ -/** - * @file msn-utils.c Utility functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "msn-utils.h" - -void -msn_parse_format(const char *mime, char **pre_ret, char **post_ret) -{ - char *cur; - GString *pre = g_string_new(NULL); - GString *post = g_string_new(NULL); - unsigned int colors[3]; - - if (pre_ret != NULL) *pre_ret = NULL; - if (post_ret != NULL) *post_ret = NULL; - - cur = strstr(mime, "FN="); - - if (cur && (*(cur = cur + 3) != ';')) - { - pre = g_string_append(pre, "<FONT FACE=\""); - - while (*cur && *cur != ';') - { - pre = g_string_append_c(pre, *cur); - cur++; - } - - pre = g_string_append(pre, "\">"); - post = g_string_prepend(post, "</FONT>"); - } - - cur = strstr(mime, "EF="); - - if (cur && (*(cur = cur + 3) != ';')) - { - while (*cur && *cur != ';') - { - pre = g_string_append_c(pre, '<'); - pre = g_string_append_c(pre, *cur); - pre = g_string_append_c(pre, '>'); - post = g_string_prepend_c(post, '>'); - post = g_string_prepend_c(post, *cur); - post = g_string_prepend_c(post, '/'); - post = g_string_prepend_c(post, '<'); - cur++; - } - } - - cur = strstr(mime, "CO="); - - if (cur && (*(cur = cur + 3) != ';')) - { - int i; - - i = sscanf(cur, "%02x%02x%02x;", &colors[0], &colors[1], &colors[2]); - - if (i > 0) - { - char tag[64]; - - if (i == 1) - { - colors[1] = 0; - colors[2] = 0; - } - else if (i == 2) - { - unsigned int temp = colors[0]; - - colors[0] = colors[1]; - colors[1] = temp; - colors[2] = 0; - } - else if (i == 3) - { - unsigned int temp = colors[2]; - - colors[2] = colors[0]; - colors[0] = temp; - } - - g_snprintf(tag, sizeof(tag), - "<FONT COLOR=\"#%02hhx%02hhx%02hhx\">", - colors[0], colors[1], colors[2]); - - pre = g_string_append(pre, tag); - post = g_string_prepend(post, "</FONT>"); - } - } - - cur = strstr(mime, "RL="); - - if (cur && (*(cur = cur + 3) != ';')) - { - if (*cur == '1') - { - /* RTL text was received */ - pre = g_string_append(pre, "<SPAN style=\"direction:rtl;text-align:right;\">"); - post = g_string_prepend(post, "</SPAN>"); - } - } - - cur = g_strdup(purple_url_decode(pre->str)); - g_string_free(pre, TRUE); - - if (pre_ret != NULL) - *pre_ret = cur; - else - g_free(cur); - - cur = g_strdup(purple_url_decode(post->str)); - g_string_free(post, TRUE); - - if (post_ret != NULL) - *post_ret = cur; - else - g_free(cur); -} - -/* - * We need this because we're only supposed to encode spaces in the font - * names. purple_url_encode() isn't acceptable. - */ -static const char * -encode_spaces(const char *str) -{ - static char buf[BUF_LEN]; - const char *c; - char *d; - - g_return_val_if_fail(str != NULL, NULL); - - for (c = str, d = buf; *c != '\0'; c++) - { - if (*c == ' ') - { - *d++ = '%'; - *d++ = '2'; - *d++ = '0'; - } - else - *d++ = *c; - } - *d = '\0'; - - return buf; -} - -/* - * Taken from the zephyr plugin. - * This parses HTML formatting (put out by one of the gtkimhtml widgets - * and converts it to msn formatting. It doesn't deal with the tag closing, - * but gtkimhtml widgets give valid html. - * It currently deals properly with <b>, <u>, <i>, <font face=...>, - * <font color=...>, <span dir=...>, <span style="direction: ...">. - * It ignores <font back=...> and <font size=...> - */ -void -msn_import_html(const char *html, char **attributes, char **message) -{ - int len, retcount = 0; - const char *c; - char *msg; - char *fontface = NULL; - char fonteffect[4]; - char fontcolor[7]; - char direction = '0'; - - gboolean has_bold = FALSE; - gboolean has_italic = FALSE; - gboolean has_underline = FALSE; - gboolean has_strikethrough = FALSE; - - g_return_if_fail(html != NULL); - g_return_if_fail(attributes != NULL); - g_return_if_fail(message != NULL); - - len = strlen(html); - msg = g_malloc0(len + 1); - - memset(fontcolor, 0, sizeof(fontcolor)); - strcat(fontcolor, "0"); - memset(fonteffect, 0, sizeof(fonteffect)); - - for (c = html; *c != '\0';) - { - if (*c == '<') - { - if (!g_ascii_strncasecmp(c + 1, "br>", 3)) - { - msg[retcount++] = '\r'; - msg[retcount++] = '\n'; - c += 4; - } - else if (!g_ascii_strncasecmp(c + 1, "i>", 2)) - { - if (!has_italic) - { - strcat(fonteffect, "I"); - has_italic = TRUE; - } - c += 3; - } - else if (!g_ascii_strncasecmp(c + 1, "b>", 2)) - { - if (!has_bold) - { - strcat(fonteffect, "B"); - has_bold = TRUE; - } - c += 3; - } - else if (!g_ascii_strncasecmp(c + 1, "u>", 2)) - { - if (!has_underline) - { - strcat(fonteffect, "U"); - has_underline = TRUE; - } - c += 3; - } - else if (!g_ascii_strncasecmp(c + 1, "s>", 2)) - { - if (!has_strikethrough) - { - strcat(fonteffect, "S"); - has_strikethrough = TRUE; - } - c += 3; - } - else if (!g_ascii_strncasecmp(c + 1, "a href=\"", 8)) - { - c += 9; - - if (!g_ascii_strncasecmp(c, "mailto:", 7)) - c += 7; - - while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2)) - msg[retcount++] = *c++; - - if (*c != '\0') - c += 2; - - /* ignore descriptive string */ - while ((*c != '\0') && g_ascii_strncasecmp(c, "</a>", 4)) - c++; - - if (*c != '\0') - c += 4; - } - else if (!g_ascii_strncasecmp(c + 1, "span", 4)) - { - /* Bi-directional text support using CSS properties in span tags */ - c += 5; - - while (*c != '\0' && *c != '>') - { - while (*c == ' ') - c++; - if (!g_ascii_strncasecmp(c, "dir=\"rtl\"", 9)) - { - c += 9; - direction = '1'; - } - else if (!g_ascii_strncasecmp(c, "style=\"", 7)) - { - /* Parse inline CSS attributes */ - char *attributes; - int attr_len = 0; - c += 7; - while (*(c + attr_len) != '\0' && *(c + attr_len) != '"') - attr_len++; - if (*(c + attr_len) == '"') - { - char *attr_dir; - attributes = g_strndup(c, attr_len); - attr_dir = purple_markup_get_css_property(attributes, "direction"); - if (attr_dir && (!g_ascii_strncasecmp(attr_dir, "RTL", 3))) - direction = '1'; - g_free(attr_dir); - g_free(attributes); - } - - } - else - { - c++; - } - } - if (*c == '>') - c++; - } - else if (!g_ascii_strncasecmp(c + 1, "font", 4)) - { - c += 5; - - while ((*c != '\0') && !g_ascii_strncasecmp(c, " ", 1)) - c++; - - if (!g_ascii_strncasecmp(c, "color=\"#", 7)) - { - c += 8; - - fontcolor[0] = *(c + 4); - fontcolor[1] = *(c + 5); - fontcolor[2] = *(c + 2); - fontcolor[3] = *(c + 3); - fontcolor[4] = *c; - fontcolor[5] = *(c + 1); - - c += 8; - } - else if (!g_ascii_strncasecmp(c, "face=\"", 6)) - { - const char *end = NULL; - const char *comma = NULL; - unsigned int namelen = 0; - - c += 6; - end = strchr(c, '\"'); - comma = strchr(c, ','); - - if (comma == NULL || comma > end) - namelen = (unsigned int)(end - c); - else - namelen = (unsigned int)(comma - c); - - fontface = g_strndup(c, namelen); - c = end + 2; - } - else - { - /* Drop all unrecognized/misparsed font tags */ - while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2)) - c++; - - if (*c != '\0') - c += 2; - } - } - else - { - while ((*c != '\0') && (*c != '>')) - c++; - if (*c != '\0') - c++; - } - } - else if (*c == '&') - { - if (!g_ascii_strncasecmp(c, "<", 4)) - { - msg[retcount++] = '<'; - c += 4; - } - else if (!g_ascii_strncasecmp(c, ">", 4)) - { - msg[retcount++] = '>'; - c += 4; - } - else if (!g_ascii_strncasecmp(c, " ", 6)) - { - msg[retcount++] = ' '; - c += 6; - } - else if (!g_ascii_strncasecmp(c, """, 6)) - { - msg[retcount++] = '"'; - c += 6; - } - else if (!g_ascii_strncasecmp(c, "&", 5)) - { - msg[retcount++] = '&'; - c += 5; - } - else if (!g_ascii_strncasecmp(c, "'", 6)) - { - msg[retcount++] = '\''; - c += 6; - } - else - msg[retcount++] = *c++; - } - else - msg[retcount++] = *c++; - } - - if (fontface == NULL) - fontface = g_strdup("MS Sans Serif"); - - *attributes = g_strdup_printf("FN=%s; EF=%s; CO=%s; PF=0; RL=%c", - encode_spaces(fontface), - fonteffect, fontcolor, direction); - *message = g_strdup(msg); - - g_free(fontface); - g_free(msg); -} - -void -msn_parse_socket(const char *str, char **ret_host, int *ret_port) -{ - char *host; - char *c; - int port; - - host = g_strdup(str); - - if ((c = strchr(host, ':')) != NULL) - { - *c = '\0'; - port = atoi(c + 1); - } - else - port = 1863; - - *ret_host = host; - *ret_port = port; -}
--- a/libpurple/protocols/msnp9/msn-utils.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/** - * @file msn-utils.h Utility functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_UTILS_H_ -#define _MSN_UTILS_H_ - -/** - * Parses the MSN message formatting into a format compatible with Purple. - * - * @param mime The mime header with the formatting. - * @param pre_ret The returned prefix string. - * @param post_ret The returned postfix string. - * - * @return The new message. - */ -void msn_parse_format(const char *mime, char **pre_ret, char **post_ret); - -/** - * Parses the Purple message formatting (html) into the MSN format. - * - * @param html The html message to format. - * @param attributes The returned attributes string. - * @param message The returned message string. - * - * @return The new message. - */ -void msn_import_html(const char *html, char **attributes, char **message); - -void msn_parse_socket(const char *str, char **ret_host, int *ret_port); - -#endif /* _MSN_UTILS_H_ */
--- a/libpurple/protocols/msnp9/msn.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2363 +0,0 @@ -/** - * @file msn.c The MSN protocol plugin - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#define PHOTO_SUPPORT 1 - -#include <glib.h> - -#include "msn.h" -#include "accountopt.h" -#include "eventloop.h" -#include "msg.h" -#include "page.h" -#include "pluginpref.h" -#include "prefs.h" -#include "session.h" -#include "smiley.h" -#include "state.h" -#include "util.h" -#include "cmds.h" -#include "core.h" -#include "prpl.h" -#include "msn-utils.h" -#include "version.h" - -#include "switchboard.h" -#include "notification.h" -#include "sync.h" -#include "slplink.h" - -#if PHOTO_SUPPORT -#include "imgstore.h" -#endif - -typedef struct -{ - PurpleConnection *gc; - const char *passport; - -} MsnMobileData; - -typedef struct -{ - PurpleConnection *gc; - char *name; - -} MsnGetInfoData; - -typedef struct -{ - MsnGetInfoData *info_data; - char *stripped; - char *url_buffer; - PurpleNotifyUserInfo *user_info; - char *photo_url_text; - -} MsnGetInfoStepTwoData; - -typedef struct -{ - PurpleConnection *gc; - const char *who; - char *msg; - PurpleMessageFlags flags; - time_t when; -} MsnIMData; - -typedef struct -{ - char *smile; - MsnObject *obj; -} MsnEmoticon; - -static const char * -msn_normalize(const PurpleAccount *account, const char *str) -{ - static char buf[BUF_LEN]; - char *tmp; - - g_return_val_if_fail(str != NULL, NULL); - - g_snprintf(buf, sizeof(buf), "%s%s", str, - (strchr(str, '@') ? "" : "@hotmail.com")); - - tmp = g_utf8_strdown(buf, -1); - strncpy(buf, tmp, sizeof(buf)); - g_free(tmp); - - return buf; -} - -static gboolean -msn_send_attention(PurpleConnection *gc, const char *username, guint type) -{ - MsnMessage *msg; - MsnSession *session; - MsnSwitchBoard *swboard; - - msg = msn_message_new_nudge(); - session = gc->proto_data; - swboard = msn_session_get_swboard(session, username, MSN_SB_FLAG_IM); - - if (swboard == NULL) - return FALSE; - - msn_switchboard_send_msg(swboard, msg, TRUE); - msn_message_destroy(msg); - - return TRUE; -} - -static GList * -msn_attention_types(PurpleAccount *account) -{ - static GList *list = NULL; - - if (!list) { - list = g_list_append(list, purple_attention_type_new("Nudge", _("Nudge"), - _("%s has nudged you!"), _("Nudging %s..."))); - } - - return list; -} - -static GHashTable * -msn_get_account_text_table(PurpleAccount *unused) -{ - GHashTable *table; - - table = g_hash_table_new(g_str_hash, g_str_equal); - - g_hash_table_insert(table, "login_label", (gpointer)_("Email Address...")); - - return table; -} - -static PurpleCmdRet -msn_cmd_nudge(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data) -{ - PurpleAccount *account = purple_conversation_get_account(conv); - PurpleConnection *gc = purple_account_get_connection(account); - const gchar *username; - - username = purple_conversation_get_name(conv); - - purple_prpl_send_attention(gc, username, MSN_NUDGE); - - return PURPLE_CMD_RET_OK; -} - -static void -msn_act_id(PurpleConnection *gc, const char *entry) -{ - MsnCmdProc *cmdproc; - MsnSession *session; - PurpleAccount *account; - const char *alias; - - session = gc->proto_data; - cmdproc = session->notification->cmdproc; - account = purple_connection_get_account(gc); - - if(entry && strlen(entry)) - alias = purple_url_encode(entry); - else - alias = ""; - - if (strlen(alias) > BUDDY_ALIAS_MAXLEN) - { - purple_notify_error(gc, NULL, - _("Your new MSN friendly name is too long."), NULL); - return; - } - - msn_cmdproc_send(cmdproc, "REA", "%s %s", - purple_account_get_username(account), - alias); -} - -static void -msn_set_prp(PurpleConnection *gc, const char *type, const char *entry) -{ - MsnCmdProc *cmdproc; - MsnSession *session; - - session = gc->proto_data; - cmdproc = session->notification->cmdproc; - - if (entry == NULL || *entry == '\0') - { - msn_cmdproc_send(cmdproc, "PRP", "%s", type); - } - else - { - msn_cmdproc_send(cmdproc, "PRP", "%s %s", type, - purple_url_encode(entry)); - } -} - -static void -msn_set_home_phone_cb(PurpleConnection *gc, const char *entry) -{ - msn_set_prp(gc, "PHH", entry); -} - -static void -msn_set_work_phone_cb(PurpleConnection *gc, const char *entry) -{ - msn_set_prp(gc, "PHW", entry); -} - -static void -msn_set_mobile_phone_cb(PurpleConnection *gc, const char *entry) -{ - msn_set_prp(gc, "PHM", entry); -} - -static void -enable_msn_pages_cb(PurpleConnection *gc) -{ - msn_set_prp(gc, "MOB", "Y"); -} - -static void -disable_msn_pages_cb(PurpleConnection *gc) -{ - msn_set_prp(gc, "MOB", "N"); -} - -static void -send_to_mobile(PurpleConnection *gc, const char *who, const char *entry) -{ - MsnTransaction *trans; - MsnSession *session; - MsnCmdProc *cmdproc; - MsnPage *page; - char *payload; - size_t payload_len; - - session = gc->proto_data; - cmdproc = session->notification->cmdproc; - - page = msn_page_new(); - msn_page_set_body(page, entry); - - payload = msn_page_gen_payload(page, &payload_len); - - trans = msn_transaction_new(cmdproc, "PGD", "%s 1 %d", who, payload_len); - - msn_transaction_set_payload(trans, payload, payload_len); - - msn_page_destroy(page); - - msn_cmdproc_send_trans(cmdproc, trans); -} - -static void -send_to_mobile_cb(MsnMobileData *data, const char *entry) -{ - send_to_mobile(data->gc, data->passport, entry); - g_free(data); -} - -static void -close_mobile_page_cb(MsnMobileData *data, const char *entry) -{ - g_free(data); -} - -/* -- */ - -static void -msn_show_set_friendly_name(PurplePluginAction *action) -{ - PurpleConnection *gc; - - gc = (PurpleConnection *) action->context; - - purple_request_input(gc, NULL, _("Set your friendly name."), - _("This is the name that other MSN buddies will " - "see you as."), - purple_connection_get_display_name(gc), FALSE, FALSE, NULL, - _("OK"), G_CALLBACK(msn_act_id), - _("Cancel"), NULL, - purple_connection_get_account(gc), NULL, NULL, - gc); -} - -static void -msn_show_set_home_phone(PurplePluginAction *action) -{ - PurpleConnection *gc; - MsnSession *session; - - gc = (PurpleConnection *) action->context; - session = gc->proto_data; - - purple_request_input(gc, NULL, _("Set your home phone number."), NULL, - msn_user_get_home_phone(session->user), FALSE, FALSE, NULL, - _("OK"), G_CALLBACK(msn_set_home_phone_cb), - _("Cancel"), NULL, - purple_connection_get_account(gc), NULL, NULL, - gc); -} - -static void -msn_show_set_work_phone(PurplePluginAction *action) -{ - PurpleConnection *gc; - MsnSession *session; - - gc = (PurpleConnection *) action->context; - session = gc->proto_data; - - purple_request_input(gc, NULL, _("Set your work phone number."), NULL, - msn_user_get_work_phone(session->user), FALSE, FALSE, NULL, - _("OK"), G_CALLBACK(msn_set_work_phone_cb), - _("Cancel"), NULL, - purple_connection_get_account(gc), NULL, NULL, - gc); -} - -static void -msn_show_set_mobile_phone(PurplePluginAction *action) -{ - PurpleConnection *gc; - MsnSession *session; - - gc = (PurpleConnection *) action->context; - session = gc->proto_data; - - purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL, - msn_user_get_mobile_phone(session->user), FALSE, FALSE, NULL, - _("OK"), G_CALLBACK(msn_set_mobile_phone_cb), - _("Cancel"), NULL, - purple_connection_get_account(gc), NULL, NULL, - gc); -} - -static void -msn_show_set_mobile_pages(PurplePluginAction *action) -{ - PurpleConnection *gc; - - gc = (PurpleConnection *) action->context; - - purple_request_action(gc, NULL, _("Allow MSN Mobile pages?"), - _("Do you want to allow or disallow people on " - "your buddy list to send you MSN Mobile pages " - "to your cell phone or other mobile device?"), - PURPLE_DEFAULT_ACTION_NONE, - purple_connection_get_account(gc), NULL, NULL, - gc, 3, - _("Allow"), G_CALLBACK(enable_msn_pages_cb), - _("Disallow"), G_CALLBACK(disable_msn_pages_cb), - _("Cancel"), NULL); -} - -static void -msn_show_hotmail_inbox(PurplePluginAction *action) -{ - PurpleConnection *gc; - MsnSession *session; - - gc = (PurpleConnection *) action->context; - session = gc->proto_data; - - if (session->passport_info.file == NULL) - { - purple_notify_error(gc, NULL, - _("This Hotmail account may not be active."), NULL); - return; - } - - purple_notify_uri(gc, session->passport_info.file); -} - -static void -show_send_to_mobile_cb(PurpleBlistNode *node, gpointer ignored) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - MsnSession *session; - MsnMobileData *data; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(buddy->account); - - session = gc->proto_data; - - data = g_new0(MsnMobileData, 1); - data->gc = gc; - data->passport = buddy->name; - - purple_request_input(gc, NULL, _("Send a mobile message."), NULL, - NULL, TRUE, FALSE, NULL, - _("Page"), G_CALLBACK(send_to_mobile_cb), - _("Close"), G_CALLBACK(close_mobile_page_cb), - purple_connection_get_account(gc), purple_buddy_get_name(buddy), NULL, - data); -} - -static gboolean -msn_offline_message(const PurpleBuddy *buddy) { - MsnUser *user; - if (buddy == NULL) - return FALSE; - user = buddy->proto_data; - return user && user->mobile; -} - -static void -initiate_chat_cb(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - MsnSession *session; - MsnSwitchBoard *swboard; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(buddy->account); - - session = gc->proto_data; - - swboard = msn_switchboard_new(session); - msn_switchboard_request(swboard); - msn_switchboard_request_add_user(swboard, buddy->name); - - /* TODO: This might move somewhere else, after USR might be */ - swboard->chat_id = msn_switchboard_get_chat_id(); - swboard->conv = serv_got_joined_chat(gc, swboard->chat_id, "MSN Chat"); - swboard->flag = MSN_SB_FLAG_IM; - - purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), - purple_account_get_username(buddy->account), NULL, PURPLE_CBFLAGS_NONE, TRUE); -} - -static void -t_msn_xfer_init(PurpleXfer *xfer) -{ - MsnSlpLink *slplink = xfer->data; - msn_slplink_request_ft(slplink, xfer); -} - -static PurpleXfer* -msn_new_xfer(PurpleConnection *gc, const char *who) -{ - MsnSession *session; - MsnSlpLink *slplink; - PurpleXfer *xfer; - - session = gc->proto_data; - - xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); - if (xfer) - { - slplink = msn_session_get_slplink(session, who); - - xfer->data = slplink; - - purple_xfer_set_init_fnc(xfer, t_msn_xfer_init); - } - - return xfer; -} - -static void -msn_send_file(PurpleConnection *gc, const char *who, const char *file) -{ - PurpleXfer *xfer = msn_new_xfer(gc, who); - - if (file) - purple_xfer_request_accepted(xfer, file); - else - purple_xfer_request(xfer); -} - -static gboolean -msn_can_receive_file(PurpleConnection *gc, const char *who) -{ - PurpleAccount *account; - char *normal; - gboolean ret; - - account = purple_connection_get_account(gc); - - normal = g_strdup(msn_normalize(account, purple_account_get_username(account))); - - ret = strcmp(normal, msn_normalize(account, who)); - - g_free(normal); - - return ret; -} - -/************************************************************************** - * Protocol Plugin ops - **************************************************************************/ - -static const char * -msn_list_icon(PurpleAccount *a, PurpleBuddy *b) -{ - return "msn"; -} - -static char * -msn_status_text(PurpleBuddy *buddy) -{ - PurplePresence *presence; - PurpleStatus *status; - - presence = purple_buddy_get_presence(buddy); - status = purple_presence_get_active_status(presence); - - if (!purple_presence_is_available(presence) && !purple_presence_is_idle(presence)) - { - return g_strdup(purple_status_get_name(status)); - } - - return NULL; -} - -static void -msn_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full) -{ - MsnUser *user; - PurplePresence *presence = purple_buddy_get_presence(buddy); - PurpleStatus *status = purple_presence_get_active_status(presence); - - user = buddy->proto_data; - - - if (purple_presence_is_online(presence)) - { - purple_notify_user_info_add_pair(user_info, _("Status"), - (purple_presence_is_idle(presence) ? _("Idle") : purple_status_get_name(status))); - } - - if (full && user) - { - purple_notify_user_info_add_pair(user_info, _("Has you"), - ((user->list_op & (1 << MSN_LIST_RL)) ? _("Yes") : _("No"))); - } - - /* XXX: This is being shown in non-full tooltips because the - * XXX: blocked icon overlay isn't always accurate for MSN. - * XXX: This can die as soon as purple_privacy_check() knows that - * XXX: this prpl always honors both the allow and deny lists. */ - /* While the above comment may be strictly correct (the privacy API needs - * rewriteing), purple_privacy_check() is going to be more accurate at - * indicating whether a particular buddy is going to be able to message - * you, which is the important information that this is trying to convey. */ - if (full && user) - { - const char *phone; - - purple_notify_user_info_add_pair(user_info, _("Blocked"), - ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No"))); - - phone = msn_user_get_home_phone(user); - if (phone != NULL) - purple_notify_user_info_add_pair(user_info, _("Home Phone Number"), phone); - - phone = msn_user_get_work_phone(user); - if (phone != NULL) - purple_notify_user_info_add_pair(user_info, _("Work Phone Number"), phone); - - phone = msn_user_get_mobile_phone(user); - if (phone != NULL) - purple_notify_user_info_add_pair(user_info, _("Mobile Phone Number"), phone); - } -} - -static GList * -msn_status_types(PurpleAccount *account) -{ - PurpleStatusType *status; - GList *types = NULL; - - status = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, - NULL, NULL, FALSE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_AWAY, - NULL, NULL, FALSE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_AWAY, - "brb", _("Be Right Back"), FALSE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, - "busy", _("Busy"), FALSE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, - "phone", _("On the Phone"), FALSE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_AWAY, - "lunch", _("Out to Lunch"), FALSE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE, - NULL, NULL, FALSE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, - NULL, NULL, FALSE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_MOBILE, - "mobile", NULL, FALSE, FALSE, TRUE); - types = g_list_append(types, status); - - return types; -} - -static GList * -msn_actions(PurplePlugin *plugin, gpointer context) -{ - PurpleConnection *gc = (PurpleConnection *)context; - PurpleAccount *account; - const char *user; - - GList *m = NULL; - PurplePluginAction *act; - - act = purple_plugin_action_new(_("Set Friendly Name..."), - msn_show_set_friendly_name); - m = g_list_append(m, act); - m = g_list_append(m, NULL); - - act = purple_plugin_action_new(_("Set Home Phone Number..."), - msn_show_set_home_phone); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("Set Work Phone Number..."), - msn_show_set_work_phone); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("Set Mobile Phone Number..."), - msn_show_set_mobile_phone); - m = g_list_append(m, act); - m = g_list_append(m, NULL); - -#if 0 - act = purple_plugin_action_new(_("Enable/Disable Mobile Devices..."), - msn_show_set_mobile_support); - m = g_list_append(m, act); -#endif - - act = purple_plugin_action_new(_("Allow/Disallow Mobile Pages..."), - msn_show_set_mobile_pages); - m = g_list_append(m, act); - - account = purple_connection_get_account(gc); - user = msn_normalize(account, purple_account_get_username(account)); - - if ((strstr(user, "@hotmail.") != NULL) || - (strstr(user, "@msn.com") != NULL)) - { - m = g_list_append(m, NULL); - act = purple_plugin_action_new(_("Open Hotmail Inbox"), - msn_show_hotmail_inbox); - m = g_list_append(m, act); - } - - return m; -} - -static GList * -msn_buddy_menu(PurpleBuddy *buddy) -{ - MsnUser *user; - - GList *m = NULL; - PurpleMenuAction *act; - - g_return_val_if_fail(buddy != NULL, NULL); - - user = buddy->proto_data; - - if (user != NULL) - { - if (user->mobile) - { - act = purple_menu_action_new(_("Send to Mobile"), - PURPLE_CALLBACK(show_send_to_mobile_cb), - NULL, NULL); - m = g_list_append(m, act); - } - } - - if (g_ascii_strcasecmp(buddy->name, - purple_account_get_username(buddy->account))) - { - act = purple_menu_action_new(_("Initiate _Chat"), - PURPLE_CALLBACK(initiate_chat_cb), - NULL, NULL); - m = g_list_append(m, act); - } - - return m; -} - -static GList * -msn_blist_node_menu(PurpleBlistNode *node) -{ - if(PURPLE_BLIST_NODE_IS_BUDDY(node)) - { - return msn_buddy_menu((PurpleBuddy *) node); - } - else - { - return NULL; - } -} - -static void -msn_login(PurpleAccount *account) -{ - PurpleConnection *gc; - MsnSession *session; - const char *username; - const char *host; - gboolean http_method = FALSE; - int port; - - gc = purple_account_get_connection(account); - - if (!purple_ssl_is_supported()) - { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, - - _("SSL support is needed for MSN. Please install a supported " - "SSL library.")); - return; - } - - http_method = purple_account_get_bool(account, "http_method", FALSE); - - if (http_method) - host = purple_account_get_string(account, "http_method_server", MSN_HTTPCONN_SERVER); - else - host = purple_account_get_string(account, "server", MSN_SERVER); - port = purple_account_get_int(account, "port", MSN_PORT); - - session = msn_session_new(account); - - gc->proto_data = session; - gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR | - PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY | - PURPLE_CONNECTION_ALLOW_ATTENTION; - - msn_session_set_login_step(session, MSN_LOGIN_STEP_START); - - /* Hmm, I don't like this. */ - /* XXX shx: Me neither */ - username = msn_normalize(account, purple_account_get_username(account)); - - if (strcmp(username, purple_account_get_username(account))) - purple_account_set_username(account, username); - - if (!msn_session_connect(session, host, port, http_method)) - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to connect")); -} - -static void -msn_close(PurpleConnection *gc) -{ - MsnSession *session; - - session = gc->proto_data; - - g_return_if_fail(session != NULL); - - msn_session_destroy(session); - - gc->proto_data = NULL; -} - -static gboolean -msn_send_me_im(gpointer data) -{ - MsnIMData *imdata = data; - serv_got_im(imdata->gc, imdata->who, imdata->msg, imdata->flags, imdata->when); - g_free(imdata->msg); - g_free(imdata); - return FALSE; -} - -static GString* -msn_msg_emoticon_add(GString *current, MsnEmoticon *emoticon) -{ - MsnObject *obj; - char *strobj; - - if (emoticon == NULL) - return current; - - obj = emoticon->obj; - - if (!obj) - return current; - - strobj = msn_object_to_string(obj); - - if (current) - g_string_append_printf(current, "\t%s\t%s", - emoticon->smile, strobj); - else { - current = g_string_new(""); - g_string_printf(current,"%s\t%s", - emoticon->smile, strobj); - } - - g_free(strobj); - - return current; -} - -static void -msn_send_emoticons(MsnSwitchBoard *swboard, GString *body) -{ - MsnMessage *msg; - - g_return_if_fail(body != NULL); - - msg = msn_message_new(MSN_MSG_SLP); - msn_message_set_content_type(msg, "text/x-mms-emoticon"); - msn_message_set_flag(msg, 'N'); - msn_message_set_bin_data(msg, body->str, body->len); - - msn_switchboard_send_msg(swboard, msg, TRUE); - msn_message_destroy(msg); -} - -static void msn_emoticon_destroy(MsnEmoticon *emoticon) -{ - if (emoticon->obj) - msn_object_destroy(emoticon->obj); - g_free(emoticon->smile); - g_free(emoticon); -} - -static GSList* msn_msg_grab_emoticons(const char *msg, const char *username) -{ - GSList *list; - GList *smileys; - PurpleSmiley *smiley; - PurpleStoredImage *img; - char *ptr; - MsnEmoticon *emoticon; - int length; - - list = NULL; - smileys = purple_smileys_get_all(); - length = strlen(msg); - - for (; smileys; smileys = g_list_delete_link(smileys, smileys)) { - smiley = (PurpleSmiley*)smileys->data; - - ptr = g_strstr_len(msg, length, purple_smiley_get_shortcut(smiley)); - - if (!ptr) - continue; - - img = purple_smiley_get_stored_image(smiley); - - emoticon = g_new0(MsnEmoticon, 1); - emoticon->smile = g_strdup(purple_smiley_get_shortcut(smiley)); - emoticon->obj = msn_object_new_from_image(img, - purple_imgstore_get_filename(img), - username, MSN_OBJECT_EMOTICON); - - purple_imgstore_unref(img); - list = g_slist_prepend(list, emoticon); - } - - return list; -} - -static int -msn_send_im(PurpleConnection *gc, const char *who, const char *message, - PurpleMessageFlags flags) -{ - PurpleAccount *account; - PurpleBuddy *buddy = purple_find_buddy(gc->account, who); - MsnMessage *msg; - char *msgformat; - char *msgtext; - const char *username; - - account = purple_connection_get_account(gc); - username = purple_account_get_username(account); - - if (buddy) { - PurplePresence *p = purple_buddy_get_presence(buddy); - if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) { - char *text = purple_markup_strip_html(message); - send_to_mobile(gc, who, text); - g_free(text); - return 1; - } - } - - msn_import_html(message, &msgformat, &msgtext); - - if (strlen(msgtext) + strlen(msgformat) + strlen(DISPLAY_VERSION) > 1564) - { - g_free(msgformat); - g_free(msgtext); - - return -E2BIG; - } - - msg = msn_message_new_plain(msgtext); - msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); - - g_free(msgformat); - g_free(msgtext); - - if (g_ascii_strcasecmp(who, username)) - { - MsnSession *session; - MsnSwitchBoard *swboard; - MsnEmoticon *smile; - GSList *smileys; - GString *emoticons = NULL; - - session = gc->proto_data; - swboard = msn_session_get_swboard(session, who, MSN_SB_FLAG_IM); - smileys = msn_msg_grab_emoticons(message, username); - - while (smileys) { - smile = (MsnEmoticon*)smileys->data; - emoticons = msn_msg_emoticon_add(emoticons,smile); - msn_emoticon_destroy(smile); - smileys = g_slist_delete_link(smileys, smileys); - } - - if (emoticons) { - msn_send_emoticons(swboard, emoticons); - g_string_free(emoticons, TRUE); - } - - msn_switchboard_send_msg(swboard, msg, TRUE); - } - else - { - char *body_str, *body_enc, *pre, *post; - const char *format; - MsnIMData *imdata = g_new0(MsnIMData, 1); - /* - * In MSN, you can't send messages to yourself, so - * we'll fake like we received it ;) - */ - body_str = msn_message_to_string(msg); - body_enc = g_markup_escape_text(body_str, -1); - g_free(body_str); - - format = msn_message_get_attr(msg, "X-MMS-IM-Format"); - msn_parse_format(format, &pre, &post); - body_str = g_strdup_printf("%s%s%s", pre ? pre : "", - body_enc ? body_enc : "", post ? post : ""); - g_free(body_enc); - g_free(pre); - g_free(post); - - serv_got_typing_stopped(gc, who); - imdata->gc = gc; - imdata->who = who; - imdata->msg = body_str; - imdata->flags = flags; - imdata->when = time(NULL); - purple_timeout_add(0, msn_send_me_im, imdata); - } - - msn_message_destroy(msg); - - return 1; -} - -static unsigned int -msn_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) -{ - PurpleAccount *account; - MsnSession *session; - MsnSwitchBoard *swboard; - MsnMessage *msg; - - account = purple_connection_get_account(gc); - session = gc->proto_data; - - /* - * TODO: I feel like this should be "if (state != PURPLE_TYPING)" - * but this is how it was before, and I don't want to break - * anything. --KingAnt - */ - if (state == PURPLE_NOT_TYPING) - return 0; - - if (!g_ascii_strcasecmp(who, purple_account_get_username(account))) - { - /* We'll just fake it, since we're sending to ourself. */ - serv_got_typing(gc, who, MSN_TYPING_RECV_TIMEOUT, PURPLE_TYPING); - - return MSN_TYPING_SEND_TIMEOUT; - } - - swboard = msn_session_find_swboard(session, who); - - if (swboard == NULL || !msn_switchboard_can_send(swboard)) - return 0; - - swboard->flag |= MSN_SB_FLAG_IM; - - msg = msn_message_new(MSN_MSG_TYPING); - msn_message_set_content_type(msg, "text/x-msmsgscontrol"); - msn_message_set_flag(msg, 'U'); - msn_message_set_attr(msg, "TypingUser", - purple_account_get_username(account)); - msn_message_set_bin_data(msg, "\r\n", 2); - - msn_switchboard_send_msg(swboard, msg, FALSE); - - msn_message_destroy(msg); - - return MSN_TYPING_SEND_TIMEOUT; -} - -static void -msn_set_status(PurpleAccount *account, PurpleStatus *status) -{ - PurpleConnection *gc; - MsnSession *session; - - gc = purple_account_get_connection(account); - - if (gc != NULL) - { - session = gc->proto_data; - msn_change_status(session); - } -} - -static void -msn_set_idle(PurpleConnection *gc, int idle) -{ - MsnSession *session; - - session = gc->proto_data; - - msn_change_status(session); -} - -#if 0 -static void -fake_userlist_add_buddy(MsnUserList *userlist, - const char *who, int list_id, - const char *group_name) -{ - MsnUser *user; - static int group_id_c = 1; - int group_id; - - group_id = -1; - - if (group_name != NULL) - { - MsnGroup *group; - group = msn_group_new(userlist, group_id_c, group_name); - group_id = group_id_c++; - } - - user = msn_userlist_find_user(userlist, who); - - if (user == NULL) - { - user = msn_user_new(userlist, who, NULL); - msn_userlist_add_user(userlist, user); - } - else - if (user->list_op & (1 << list_id)) - { - if (list_id == MSN_LIST_FL) - { - if (group_id >= 0) - if (g_list_find(user->group_ids, - GINT_TO_POINTER(group_id))) - return; - } - else - return; - } - - if (group_id >= 0) - { - user->group_ids = g_list_append(user->group_ids, - GINT_TO_POINTER(group_id)); - } - - user->list_op |= (1 << list_id); -} -#endif - -static void -msn_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) -{ - MsnSession *session; - MsnUserList *userlist; - const char *who; - - session = gc->proto_data; - userlist = session->userlist; - who = msn_normalize(gc->account, buddy->name); - - if (!session->logged_in) - { -#if 0 - fake_userlist_add_buddy(session->sync_userlist, who, MSN_LIST_FL, - group ? group->name : NULL); -#else - purple_debug_error("msn", "msn_add_buddy called before connected\n"); -#endif - - return; - } - -#if 0 - if (group != NULL && group->name != NULL) - purple_debug_info("msn", "msn_add_buddy: %s, %s\n", who, group->name); - else - purple_debug_info("msn", "msn_add_buddy: %s\n", who); -#endif - -#if 0 - /* Which is the max? */ - if (session->fl_users_count >= 150) - { - purple_debug_info("msn", "Too many buddies\n"); - /* Buddy list full */ - /* TODO: purple should be notified of this */ - return; - } -#endif - - /* XXX - Would group ever be NULL here? I don't think so... - * shx: Yes it should; MSN handles non-grouped buddies, and this is only - * internal. */ - msn_userlist_add_buddy(userlist, who, MSN_LIST_FL, - group ? group->name : NULL); -} - -static void -msn_rem_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) -{ - MsnSession *session; - MsnUserList *userlist; - - session = gc->proto_data; - userlist = session->userlist; - - if (!session->logged_in) - return; - - /* XXX - Does buddy->name need to be msn_normalize'd here? --KingAnt */ - msn_userlist_rem_buddy(userlist, buddy->name, MSN_LIST_FL, group->name); -} - -static void -msn_add_permit(PurpleConnection *gc, const char *who) -{ - MsnSession *session; - MsnUserList *userlist; - MsnUser *user; - - session = gc->proto_data; - userlist = session->userlist; - user = msn_userlist_find_user(userlist, who); - - if (!session->logged_in) - return; - - if (user != NULL && user->list_op & MSN_LIST_BL_OP) - msn_userlist_rem_buddy(userlist, who, MSN_LIST_BL, NULL); - - msn_userlist_add_buddy(userlist, who, MSN_LIST_AL, NULL); -} - -static void -msn_add_deny(PurpleConnection *gc, const char *who) -{ - MsnSession *session; - MsnUserList *userlist; - MsnUser *user; - - session = gc->proto_data; - userlist = session->userlist; - user = msn_userlist_find_user(userlist, who); - - if (!session->logged_in) - return; - - if (user != NULL && user->list_op & MSN_LIST_AL_OP) - msn_userlist_rem_buddy(userlist, who, MSN_LIST_AL, NULL); - - msn_userlist_add_buddy(userlist, who, MSN_LIST_BL, NULL); -} - -static void -msn_rem_permit(PurpleConnection *gc, const char *who) -{ - MsnSession *session; - MsnUserList *userlist; - MsnUser *user; - - session = gc->proto_data; - userlist = session->userlist; - - if (!session->logged_in) - return; - - user = msn_userlist_find_user(userlist, who); - - msn_userlist_rem_buddy(userlist, who, MSN_LIST_AL, NULL); - - if (user != NULL && user->list_op & MSN_LIST_RL_OP) - msn_userlist_add_buddy(userlist, who, MSN_LIST_BL, NULL); -} - -static void -msn_rem_deny(PurpleConnection *gc, const char *who) -{ - MsnSession *session; - MsnUserList *userlist; - MsnUser *user; - - session = gc->proto_data; - userlist = session->userlist; - - if (!session->logged_in) - return; - - user = msn_userlist_find_user(userlist, who); - - msn_userlist_rem_buddy(userlist, who, MSN_LIST_BL, NULL); - - if (user != NULL && user->list_op & MSN_LIST_RL_OP) - msn_userlist_add_buddy(userlist, who, MSN_LIST_AL, NULL); -} - -static void -msn_set_permit_deny(PurpleConnection *gc) -{ - PurpleAccount *account; - MsnSession *session; - MsnCmdProc *cmdproc; - - account = purple_connection_get_account(gc); - session = gc->proto_data; - cmdproc = session->notification->cmdproc; - - if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL || - account->perm_deny == PURPLE_PRIVACY_DENY_USERS) - { - msn_cmdproc_send(cmdproc, "BLP", "%s", "AL"); - } - else - { - msn_cmdproc_send(cmdproc, "BLP", "%s", "BL"); - } -} - -static void -msn_chat_invite(PurpleConnection *gc, int id, const char *msg, - const char *who) -{ - MsnSession *session; - MsnSwitchBoard *swboard; - - session = gc->proto_data; - - swboard = msn_session_find_swboard_with_id(session, id); - - if (swboard == NULL) - { - /* if we have no switchboard, everyone else left the chat already */ - swboard = msn_switchboard_new(session); - msn_switchboard_request(swboard); - swboard->chat_id = id; - swboard->conv = purple_find_chat(gc, id); - } - - swboard->flag |= MSN_SB_FLAG_IM; - - msn_switchboard_request_add_user(swboard, who); -} - -static void -msn_chat_leave(PurpleConnection *gc, int id) -{ - MsnSession *session; - MsnSwitchBoard *swboard; - PurpleConversation *conv; - - session = gc->proto_data; - - swboard = msn_session_find_swboard_with_id(session, id); - - /* if swboard is NULL we were the only person left anyway */ - if (swboard == NULL) - return; - - conv = swboard->conv; - - msn_switchboard_release(swboard, MSN_SB_FLAG_IM); - - /* If other switchboards managed to associate themselves with this - * conv, make sure they know it's gone! */ - if (conv != NULL) - { - while ((swboard = msn_session_find_swboard_with_conv(session, conv)) != NULL) - swboard->conv = NULL; - } -} - -static int -msn_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) -{ - PurpleAccount *account; - MsnSession *session; - MsnSwitchBoard *swboard; - MsnMessage *msg; - char *msgformat; - char *msgtext; - - account = purple_connection_get_account(gc); - session = gc->proto_data; - swboard = msn_session_find_swboard_with_id(session, id); - - if (swboard == NULL) - return -EINVAL; - - if (!swboard->ready) - return 0; - - swboard->flag |= MSN_SB_FLAG_IM; - - msn_import_html(message, &msgformat, &msgtext); - - if (strlen(msgtext) + strlen(msgformat) + strlen(DISPLAY_VERSION) > 1564) - { - g_free(msgformat); - g_free(msgtext); - - return -E2BIG; - } - - msg = msn_message_new_plain(msgtext); - msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); - msn_switchboard_send_msg(swboard, msg, FALSE); - msn_message_destroy(msg); - - g_free(msgformat); - g_free(msgtext); - - serv_got_chat_in(gc, id, purple_account_get_username(account), flags, - message, time(NULL)); - - return 0; -} - -static void -msn_keepalive(PurpleConnection *gc) -{ - MsnSession *session; - - session = gc->proto_data; - - if (!session->http_method) - { - MsnCmdProc *cmdproc; - - cmdproc = session->notification->cmdproc; - - msn_cmdproc_send_quick(cmdproc, "PNG", NULL, NULL); - } -} - -static void -msn_group_buddy(PurpleConnection *gc, const char *who, - const char *old_group_name, const char *new_group_name) -{ - MsnSession *session; - MsnUserList *userlist; - - session = gc->proto_data; - userlist = session->userlist; - - msn_userlist_move_buddy(userlist, who, old_group_name, new_group_name); -} - -static void -msn_rename_group(PurpleConnection *gc, const char *old_name, - PurpleGroup *group, GList *moved_buddies) -{ - MsnSession *session; - MsnCmdProc *cmdproc; - int old_gid; - const char *enc_new_group_name; - - session = gc->proto_data; - cmdproc = session->notification->cmdproc; - enc_new_group_name = purple_url_encode(group->name); - - old_gid = msn_userlist_find_group_id(session->userlist, old_name); - - if (old_gid >= 0) - { - msn_cmdproc_send(cmdproc, "REG", "%d %s 0", old_gid, - enc_new_group_name); - } - else - { - msn_cmdproc_send(cmdproc, "ADG", "%s 0", enc_new_group_name); - } -} - -static void -msn_convo_closed(PurpleConnection *gc, const char *who) -{ - MsnSession *session; - MsnSwitchBoard *swboard; - PurpleConversation *conv; - - session = gc->proto_data; - - swboard = msn_session_find_swboard(session, who); - - /* - * Don't perform an assertion here. If swboard is NULL, then the - * switchboard was either closed by the other party, or the person - * is talking to himself. - */ - if (swboard == NULL) - return; - - conv = swboard->conv; - - /* If we release the switchboard here, it may still have messages - pending ACK which would result in incorrect unsent message errors. - Just let it timeout... This is *so* going to screw with people who - use dumb clients that report "User has closed the conversation window" */ - /* msn_switchboard_release(swboard, MSN_SB_FLAG_IM); */ - swboard->conv = NULL; - - /* If other switchboards managed to associate themselves with this - * conv, make sure they know it's gone! */ - if (conv != NULL) - { - while ((swboard = msn_session_find_swboard_with_conv(session, conv)) != NULL) - swboard->conv = NULL; - } -} - -static void -msn_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img) -{ - MsnSession *session; - MsnUser *user; - - session = gc->proto_data; - user = session->user; - - msn_user_set_buddy_icon(user, img); - - msn_change_status(session); -} - -static void -msn_remove_group(PurpleConnection *gc, PurpleGroup *group) -{ - MsnSession *session; - MsnCmdProc *cmdproc; - int group_id; - - session = gc->proto_data; - cmdproc = session->notification->cmdproc; - - if ((group_id = msn_userlist_find_group_id(session->userlist, group->name)) >= 0) - { - msn_cmdproc_send(cmdproc, "RMG", "%d", group_id); - } -} - -/** - * Extract info text from info_data and add it to user_info - */ -static gboolean -msn_tooltip_extract_info_text(PurpleNotifyUserInfo *user_info, MsnGetInfoData *info_data) -{ - PurpleBuddy *b; - - b = purple_find_buddy(purple_connection_get_account(info_data->gc), - info_data->name); - - if (b) - { - char *tmp; - - if (b->alias && b->alias[0]) - { - char *aliastext = g_markup_escape_text(b->alias, -1); - purple_notify_user_info_add_pair(user_info, _("Alias"), aliastext); - g_free(aliastext); - } - - if (b->server_alias) - { - char *nicktext = g_markup_escape_text(b->server_alias, -1); - tmp = g_strdup_printf("<font sml=\"msn\">%s</font><br>", nicktext); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); - g_free(tmp); - g_free(nicktext); - } - - /* Add the tooltip information */ - msn_tooltip_text(b, user_info, TRUE); - - return TRUE; - } - - return FALSE; -} - -#if PHOTO_SUPPORT - -static char * -msn_get_photo_url(const char *url_text) -{ - char *p, *q; - - if ((p = strstr(url_text, " contactparams:photopreauthurl=\"")) != NULL) - { - p += strlen(" contactparams:photopreauthurl=\""); - } - - if (p && (strncmp(p, "http://", 8) == 0) && ((q = strchr(p, '"')) != NULL)) - return g_strndup(p, q - p); - - return NULL; -} - -static void msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data, - const gchar *url_text, size_t len, const gchar *error_message); - -#endif - -#if 0 -static char *msn_info_date_reformat(const char *field, size_t len) -{ - char *tmp = g_strndup(field, len); - time_t t = purple_str_to_time(tmp, FALSE, NULL, NULL, NULL); - - g_free(tmp); - return g_strdup(purple_date_format_short(localtime(&t))); -} -#endif - -#define MSN_GOT_INFO_GET_FIELD(a, b) \ - found = purple_markup_extract_info_field(stripped, stripped_len, user_info, \ - "\n" a ":", 0, "\n", 0, "Undisclosed", b, 0, NULL, NULL); \ - if (found) \ - sect_info = TRUE; - -#define MSN_GOT_INFO_GET_FIELD_NO_SEARCH(a, b) \ - found = purple_markup_extract_info_field(stripped, stripped_len, user_info, \ - "\n" a ":", 0, "\n", 0, "Undisclosed", b, 0, NULL, msn_info_strip_search_link); \ - if (found) \ - sect_info = TRUE; - -static char * -msn_info_strip_search_link(const char *field, size_t len) -{ - const char *c; - if ((c = strstr(field, " (http://")) == NULL) - return g_strndup(field, len); - return g_strndup(field, c - field); -} - -static void -msn_got_info(PurpleUtilFetchUrlData *url_data, gpointer data, - const gchar *url_text, size_t len, const gchar *error_message) -{ - MsnGetInfoData *info_data = (MsnGetInfoData *)data; - PurpleNotifyUserInfo *user_info; - char *stripped, *p, *q, *tmp; - char *user_url = NULL; - gboolean found; - gboolean has_tooltip_text = FALSE; - gboolean has_info = FALSE; - gboolean sect_info = FALSE; - gboolean has_contact_info = FALSE; - char *url_buffer; - int stripped_len; -#if PHOTO_SUPPORT - char *photo_url_text = NULL; - MsnGetInfoStepTwoData *info2_data = NULL; -#endif - - purple_debug_info("msn", "In msn_got_info\n"); - - /* Make sure the connection is still valid */ - if (g_list_find(purple_connections_get_all(), info_data->gc) == NULL) - { - purple_debug_warning("msn", "invalid connection. ignoring buddy info.\n"); - g_free(info_data->name); - g_free(info_data); - return; - } - - user_info = purple_notify_user_info_new(); - has_tooltip_text = msn_tooltip_extract_info_text(user_info, info_data); - - if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0) - { - tmp = g_strdup_printf("<b>%s</b>", _("Error retrieving profile")); - purple_notify_user_info_add_pair(user_info, NULL, tmp); - g_free(tmp); - - purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL); - purple_notify_user_info_destroy(user_info); - - g_free(info_data->name); - g_free(info_data); - return; - } - - url_buffer = g_strdup(url_text); - - /* If they have a homepage link, MSN masks it such that we need to - * fetch the url out before purple_markup_strip_html() nukes it */ - /* I don't think this works with the new spaces profiles - Stu 3/2/06 */ - if ((p = strstr(url_text, - "Take a look at my </font><A class=viewDesc title=\"")) != NULL) - { - p += 50; - - if ((q = strchr(p, '"')) != NULL) - user_url = g_strndup(p, q - p); - } - - /* - * purple_markup_strip_html() doesn't strip out character entities like - * and · - */ - while ((p = strstr(url_buffer, " ")) != NULL) - { - *p = ' '; /* Turn 's into ordinary blanks */ - p += 1; - memmove(p, p + 5, strlen(p + 5)); - url_buffer[strlen(url_buffer) - 5] = '\0'; - } - - while ((p = strstr(url_buffer, "·")) != NULL) - { - memmove(p, p + 6, strlen(p + 6)); - url_buffer[strlen(url_buffer) - 6] = '\0'; - } - - /* Nuke the nasty \r's that just get in the way */ - purple_str_strip_char(url_buffer, '\r'); - - /* MSN always puts in ' for apostrophes...replace them */ - while ((p = strstr(url_buffer, "'")) != NULL) - { - *p = '\''; - memmove(p + 1, p + 5, strlen(p + 5)); - url_buffer[strlen(url_buffer) - 4] = '\0'; - } - - /* Nuke the html, it's easier than trying to parse the horrid stuff */ - stripped = purple_markup_strip_html(url_buffer); - stripped_len = strlen(stripped); - - purple_debug_misc("msn", "stripped = %p\n", stripped); - purple_debug_misc("msn", "url_buffer = %p\n", url_buffer); - - /* General section header */ - if (has_tooltip_text) - purple_notify_user_info_add_section_break(user_info); - - purple_notify_user_info_add_section_header(user_info, _("General")); - - /* Extract their Name and put it in */ - MSN_GOT_INFO_GET_FIELD("Name", _("Name")); - - /* General */ - MSN_GOT_INFO_GET_FIELD("Nickname", _("Nickname")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Age", _("Age")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Gender", _("Gender")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Occupation", _("Occupation")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Location", _("Location")); - - /* Extract their Interests and put it in */ - found = purple_markup_extract_info_field(stripped, stripped_len, user_info, - "\nInterests\t", 0, " (/default.aspx?page=searchresults", 0, - "Undisclosed", _("Hobbies and Interests") /* _("Interests") */, - 0, NULL, NULL); - - if (found) - sect_info = TRUE; - - MSN_GOT_INFO_GET_FIELD("More about me", _("A Little About Me")); - - if (sect_info) - { - has_info = TRUE; - sect_info = FALSE; - } - else - { - /* Remove the section header */ - purple_notify_user_info_remove_last_item(user_info); - if (has_tooltip_text) - purple_notify_user_info_remove_last_item(user_info); - } - - /* Social */ - purple_notify_user_info_add_section_break(user_info); - purple_notify_user_info_add_section_header(user_info, _("Social")); - - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Marital status", _("Marital Status")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Interested in", _("Interests")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Pets", _("Pets")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Hometown", _("Hometown")); - MSN_GOT_INFO_GET_FIELD("Places lived", _("Places Lived")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Fashion", _("Fashion")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Humor", _("Humor")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Music", _("Music")); - MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Favorite quote", _("Favorite Quote")); - - if (sect_info) - { - has_info = TRUE; - sect_info = FALSE; - } - else - { - /* Remove the section header */ - purple_notify_user_info_remove_last_item(user_info); - purple_notify_user_info_remove_last_item(user_info); - } - - /* Contact Info */ - /* Personal */ - purple_notify_user_info_add_section_break(user_info); - purple_notify_user_info_add_section_header(user_info, _("Contact Info")); - purple_notify_user_info_add_section_header(user_info, _("Personal")); - - MSN_GOT_INFO_GET_FIELD("Name", _("Name")); - MSN_GOT_INFO_GET_FIELD("Significant other", _("Significant Other")); - MSN_GOT_INFO_GET_FIELD("Home phone", _("Home Phone")); - MSN_GOT_INFO_GET_FIELD("Home phone 2", _("Home Phone 2")); - MSN_GOT_INFO_GET_FIELD("Home address", _("Home Address")); - MSN_GOT_INFO_GET_FIELD("Personal Mobile", _("Personal Mobile")); - MSN_GOT_INFO_GET_FIELD("Home fax", _("Home Fax")); - MSN_GOT_INFO_GET_FIELD("Personal email", _("Personal Email")); - MSN_GOT_INFO_GET_FIELD("Personal IM", _("Personal IM")); - MSN_GOT_INFO_GET_FIELD("Birthday", _("Birthday")); - MSN_GOT_INFO_GET_FIELD("Anniversary", _("Anniversary")); - MSN_GOT_INFO_GET_FIELD("Notes", _("Notes")); - - if (sect_info) - { - has_info = TRUE; - sect_info = FALSE; - has_contact_info = TRUE; - } - else - { - /* Remove the section header */ - purple_notify_user_info_remove_last_item(user_info); - } - - /* Business */ - purple_notify_user_info_add_section_header(user_info, _("Work")); - MSN_GOT_INFO_GET_FIELD("Name", _("Name")); - MSN_GOT_INFO_GET_FIELD("Job title", _("Job Title")); - MSN_GOT_INFO_GET_FIELD("Company", _("Company")); - MSN_GOT_INFO_GET_FIELD("Department", _("Department")); - MSN_GOT_INFO_GET_FIELD("Profession", _("Profession")); - MSN_GOT_INFO_GET_FIELD("Work phone 1", _("Work Phone")); - MSN_GOT_INFO_GET_FIELD("Work phone 2", _("Work Phone 2")); - MSN_GOT_INFO_GET_FIELD("Work address", _("Work Address")); - MSN_GOT_INFO_GET_FIELD("Work mobile", _("Work Mobile")); - MSN_GOT_INFO_GET_FIELD("Work pager", _("Work Pager")); - MSN_GOT_INFO_GET_FIELD("Work fax", _("Work Fax")); - MSN_GOT_INFO_GET_FIELD("Work email", _("Work Email")); - MSN_GOT_INFO_GET_FIELD("Work IM", _("Work IM")); - MSN_GOT_INFO_GET_FIELD("Start date", _("Start Date")); - MSN_GOT_INFO_GET_FIELD("Notes", _("Notes")); - - if (sect_info) - { - has_info = TRUE; - sect_info = FALSE; - has_contact_info = TRUE; - } - else - { - /* Remove the section header */ - purple_notify_user_info_remove_last_item(user_info); - } - - if (!has_contact_info) - { - /* Remove the Contact Info section header */ - purple_notify_user_info_remove_last_item(user_info); - } - -#if 0 /* these probably don't show up any more */ - /* - * The fields, 'A Little About Me', 'Favorite Things', 'Hobbies - * and Interests', 'Favorite Quote', and 'My Homepage' may or may - * not appear, in any combination. However, they do appear in - * certain order, so we can successively search to pin down the - * distinct values. - */ - - /* Check if they have A Little About Me */ - found = purple_markup_extract_info_field(stripped, stripped_len, s, - " A Little About Me \n\n", 0, "Favorite Things", '\n', NULL, - _("A Little About Me"), 0, NULL, NULL); - - if (!found) - { - found = purple_markup_extract_info_field(stripped, stripped_len, s, - " A Little About Me \n\n", 0, "Hobbies and Interests", '\n', - NULL, _("A Little About Me"), 0, NULL, NULL); - } - - if (!found) - { - found = purple_markup_extract_info_field(stripped, stripped_len, s, - " A Little About Me \n\n", 0, "Favorite Quote", '\n', NULL, - _("A Little About Me"), 0, NULL, NULL); - } - - if (!found) - { - found = purple_markup_extract_info_field(stripped, stripped_len, s, - " A Little About Me \n\n", 0, "My Homepage \n\nTake a look", - '\n', - NULL, _("A Little About Me"), 0, NULL, NULL); - } - - if (!found) - { - purple_markup_extract_info_field(stripped, stripped_len, s, - " A Little About Me \n\n", 0, "last updated", '\n', NULL, - _("A Little About Me"), 0, NULL, NULL); - } - - if (found) - has_info = TRUE; - - /* Check if they have Favorite Things */ - found = purple_markup_extract_info_field(stripped, stripped_len, s, - " Favorite Things \n\n", 0, "Hobbies and Interests", '\n', NULL, - _("Favorite Things"), 0, NULL, NULL); - - if (!found) - { - found = purple_markup_extract_info_field(stripped, stripped_len, s, - " Favorite Things \n\n", 0, "Favorite Quote", '\n', NULL, - _("Favorite Things"), 0, NULL, NULL); - } - - if (!found) - { - found = purple_markup_extract_info_field(stripped, stripped_len, s, - " Favorite Things \n\n", 0, "My Homepage \n\nTake a look", '\n', - NULL, _("Favorite Things"), 0, NULL, NULL); - } - - if (!found) - { - purple_markup_extract_info_field(stripped, stripped_len, s, - " Favorite Things \n\n", 0, "last updated", '\n', NULL, - _("Favorite Things"), 0, NULL, NULL); - } - - if (found) - has_info = TRUE; - - /* Check if they have Hobbies and Interests */ - found = purple_markup_extract_info_field(stripped, stripped_len, s, - " Hobbies and Interests \n\n", 0, "Favorite Quote", '\n', NULL, - _("Hobbies and Interests"), 0, NULL, NULL); - - if (!found) - { - found = purple_markup_extract_info_field(stripped, stripped_len, s, - " Hobbies and Interests \n\n", 0, "My Homepage \n\nTake a look", - '\n', NULL, _("Hobbies and Interests"), 0, NULL, NULL); - } - - if (!found) - { - purple_markup_extract_info_field(stripped, stripped_len, s, - " Hobbies and Interests \n\n", 0, "last updated", '\n', NULL, - _("Hobbies and Interests"), 0, NULL, NULL); - } - - if (found) - has_info = TRUE; - - /* Check if they have Favorite Quote */ - found = purple_markup_extract_info_field(stripped, stripped_len, s, - "Favorite Quote \n\n", 0, "My Homepage \n\nTake a look", '\n', NULL, - _("Favorite Quote"), 0, NULL, NULL); - - if (!found) - { - purple_markup_extract_info_field(stripped, stripped_len, s, - "Favorite Quote \n\n", 0, "last updated", '\n', NULL, - _("Favorite Quote"), 0, NULL, NULL); - } - - if (found) - has_info = TRUE; - - /* Extract the last updated date and put it in */ - found = purple_markup_extract_info_field(stripped, stripped_len, s, - " last updated:", 1, "\n", 0, NULL, _("Last Updated"), 0, - NULL, msn_info_date_reformat); - - if (found) - has_info = TRUE; -#endif - - /* If we were able to fetch a homepage url earlier, stick it in there */ - if (user_url != NULL) - { - tmp = g_strdup_printf("<a href=\"%s\">%s</a>", user_url, user_url); - purple_notify_user_info_add_pair(user_info, _("Homepage"), tmp); - g_free(tmp); - g_free(user_url); - - has_info = TRUE; - } - - if (!has_info) - { - /* MSN doesn't actually distinguish between "unknown member" and - * a known member with an empty profile. Try to explain this fact. - * Note that if we have a nonempty tooltip_text, we know the user - * exists. - */ - /* This doesn't work with the new spaces profiles - Stu 3/2/06 - char *p = strstr(url_buffer, "Unknown Member </TITLE>"); - * This might not work for long either ... */ - /* Nope, it failed some time before 5/2/07 :( - char *p = strstr(url_buffer, "form id=\"SpacesSearch\" name=\"SpacesSearch\""); - * Let's see how long this one holds out for ... */ - char *p = strstr(url_buffer, "<form id=\"profile_form\" name=\"profile_form\" action=\"http://spaces.live.com/profile.aspx?cid=0\""); - PurpleBuddy *b = purple_find_buddy - (purple_connection_get_account(info_data->gc), info_data->name); - purple_notify_user_info_add_pair(user_info, _("Error retrieving profile"), - ((p && b) ? _("The user has not created a public profile.") : - (p ? _("MSN reported not being able to find the user's profile. " - "This either means that the user does not exist, " - "or that the user exists " - "but has not created a public profile.") : - _("Could not find " /* This should never happen */ - "any information in the user's profile. " - "The user most likely does not exist.")))); - } - - /* put a link to the actual profile URL */ - tmp = g_strdup_printf("<a href=\"%s%s\">%s%s</a>", - PROFILE_URL, info_data->name, PROFILE_URL, info_data->name); - purple_notify_user_info_add_pair(user_info, _("Profile URL"), tmp); - g_free(tmp); - -#if PHOTO_SUPPORT - /* Find the URL to the photo; must be before the marshalling [Bug 994207] */ - photo_url_text = msn_get_photo_url(url_text); - - /* Marshall the existing state */ - info2_data = g_malloc0(sizeof(MsnGetInfoStepTwoData)); - info2_data->info_data = info_data; - info2_data->stripped = stripped; - info2_data->url_buffer = url_buffer; - info2_data->user_info = user_info; - info2_data->photo_url_text = photo_url_text; - - /* Try to put the photo in there too, if there's one */ - if (photo_url_text) - { - purple_util_fetch_url(photo_url_text, FALSE, NULL, FALSE, msn_got_photo, - info2_data); - } - else - { - /* Emulate a callback */ - /* TODO: Huh? */ - msn_got_photo(NULL, info2_data, NULL, 0, NULL); - } -} - -static void -msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer user_data, - const gchar *url_text, size_t len, const gchar *error_message) -{ - MsnGetInfoStepTwoData *info2_data = (MsnGetInfoStepTwoData *)user_data; - int id = -1; - - /* Unmarshall the saved state */ - MsnGetInfoData *info_data = info2_data->info_data; - char *stripped = info2_data->stripped; - char *url_buffer = info2_data->url_buffer; - PurpleNotifyUserInfo *user_info = info2_data->user_info; - char *photo_url_text = info2_data->photo_url_text; - - /* Make sure the connection is still valid if we got here by fetching a photo url */ - if (url_text && (error_message != NULL || - g_list_find(purple_connections_get_all(), info_data->gc) == NULL)) - { - purple_debug_warning("msn", "invalid connection. ignoring buddy photo info.\n"); - g_free(stripped); - g_free(url_buffer); - purple_notify_user_info_destroy(user_info); - g_free(info_data->name); - g_free(info_data); - g_free(photo_url_text); - g_free(info2_data); - - return; - } - - /* Try to put the photo in there too, if there's one and is readable */ - if (user_data && url_text && len != 0) - { - if (strstr(url_text, "400 Bad Request") - || strstr(url_text, "403 Forbidden") - || strstr(url_text, "404 Not Found")) - { - - purple_debug_info("msn", "Error getting %s: %s\n", - photo_url_text, url_text); - } - else - { - char buf[1024]; - purple_debug_info("msn", "%s is %" G_GSIZE_FORMAT - " bytes\n", photo_url_text, len); - id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL); - g_snprintf(buf, sizeof(buf), "<img id=\"%d\"><br>", id); - purple_notify_user_info_prepend_pair(user_info, NULL, buf); - } - } - - /* We continue here from msn_got_info, as if nothing has happened */ -#endif - purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL); - - g_free(stripped); - g_free(url_buffer); - purple_notify_user_info_destroy(user_info); - g_free(info_data->name); - g_free(info_data); -#if PHOTO_SUPPORT - g_free(photo_url_text); - g_free(info2_data); - if (id != -1) - purple_imgstore_unref_by_id(id); -#endif -} - -static void -msn_get_info(PurpleConnection *gc, const char *name) -{ - MsnGetInfoData *data; - char *url; - - data = g_new0(MsnGetInfoData, 1); - data->gc = gc; - data->name = g_strdup(name); - - url = g_strdup_printf("%s%s", PROFILE_URL, name); - - purple_util_fetch_url(url, FALSE, - "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", - TRUE, msn_got_info, data); - - g_free(url); -} - -static gboolean msn_load(PurplePlugin *plugin) -{ - msn_notification_init(); - msn_switchboard_init(); - msn_sync_init(); - - return TRUE; -} - -static gboolean msn_unload(PurplePlugin *plugin) -{ - msn_notification_end(); - msn_switchboard_end(); - msn_sync_end(); - - return TRUE; -} - -static PurpleAccount *find_acct(const char *prpl, const char *acct_id) -{ - PurpleAccount *acct = NULL; - - /* If we have a specific acct, use it */ - if (acct_id) { - acct = purple_accounts_find(acct_id, prpl); - if (acct && !purple_account_is_connected(acct)) - acct = NULL; - } else { /* Otherwise find an active account for the protocol */ - GList *l = purple_accounts_get_all(); - while (l) { - if (!strcmp(prpl, purple_account_get_protocol_id(l->data)) - && purple_account_is_connected(l->data)) { - acct = l->data; - break; - } - l = l->next; - } - } - - return acct; -} - -static gboolean msn_uri_handler(const char *proto, const char *cmd, GHashTable *params) -{ - char *acct_id = g_hash_table_lookup(params, "account"); - PurpleAccount *acct; - - if (g_ascii_strcasecmp(proto, "msnim")) - return FALSE; - - acct = find_acct("prpl-msn", acct_id); - - if (!acct) - return FALSE; - - /* msnim:chat?contact=user@domain.tld */ - if (!g_ascii_strcasecmp(cmd, "Chat")) { - char *sname = g_hash_table_lookup(params, "contact"); - if (sname) { - PurpleConversation *conv = purple_find_conversation_with_account( - PURPLE_CONV_TYPE_IM, sname, acct); - if (conv == NULL) - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, sname); - purple_conversation_present(conv); - } - /*else - **If pidgindialogs_im() was in the core, we could use it here. - * It is all purple_request_* based, but I'm not sure it really belongs in the core - pidgindialogs_im();*/ - - return TRUE; - } - /* msnim:add?contact=user@domain.tld */ - else if (!g_ascii_strcasecmp(cmd, "Add")) { - char *name = g_hash_table_lookup(params, "contact"); - purple_blist_request_add_buddy(acct, name, NULL, NULL); - return TRUE; - } - - return FALSE; -} - - -static PurplePluginProtocolInfo prpl_info = -{ - OPT_PROTO_MAIL_CHECK, - NULL, /* user_splits */ - NULL, /* protocol_options */ - {"png", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */ - msn_list_icon, /* list_icon */ - NULL, /* list_emblems */ - msn_status_text, /* status_text */ - msn_tooltip_text, /* tooltip_text */ - msn_status_types, /* away_states */ - msn_blist_node_menu, /* blist_node_menu */ - NULL, /* chat_info */ - NULL, /* chat_info_defaults */ - msn_login, /* login */ - msn_close, /* close */ - msn_send_im, /* send_im */ - NULL, /* set_info */ - msn_send_typing, /* send_typing */ - msn_get_info, /* get_info */ - msn_set_status, /* set_away */ - msn_set_idle, /* set_idle */ - NULL, /* change_passwd */ - msn_add_buddy, /* add_buddy */ - NULL, /* add_buddies */ - msn_rem_buddy, /* remove_buddy */ - NULL, /* remove_buddies */ - msn_add_permit, /* add_permit */ - msn_add_deny, /* add_deny */ - msn_rem_permit, /* rem_permit */ - msn_rem_deny, /* rem_deny */ - msn_set_permit_deny, /* set_permit_deny */ - NULL, /* join_chat */ - NULL, /* reject chat invite */ - NULL, /* get_chat_name */ - msn_chat_invite, /* chat_invite */ - msn_chat_leave, /* chat_leave */ - NULL, /* chat_whisper */ - msn_chat_send, /* chat_send */ - msn_keepalive, /* keepalive */ - NULL, /* register_user */ - NULL, /* get_cb_info */ - NULL, /* get_cb_away */ - NULL, /* alias_buddy */ - msn_group_buddy, /* group_buddy */ - msn_rename_group, /* rename_group */ - NULL, /* buddy_free */ - msn_convo_closed, /* convo_closed */ - msn_normalize, /* normalize */ - msn_set_buddy_icon, /* set_buddy_icon */ - msn_remove_group, /* remove_group */ - NULL, /* get_cb_real_name */ - NULL, /* set_chat_topic */ - NULL, /* find_blist_chat */ - NULL, /* roomlist_get_list */ - NULL, /* roomlist_cancel */ - NULL, /* roomlist_expand_category */ - msn_can_receive_file, /* can_receive_file */ - msn_send_file, /* send_file */ - msn_new_xfer, /* new_xfer */ - msn_offline_message, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ - NULL, /* send_raw */ - NULL, /* roomlist_room_serialize */ - NULL, /* unregister_user */ - msn_send_attention, /* send_attention */ - msn_attention_types, /* attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ - msn_get_account_text_table, /* get_account_text_table */ - NULL, /* initiate_media */ - NULL /* can_do_media */ -}; - -static PurplePluginInfo info = -{ - PURPLE_PLUGIN_MAGIC, - PURPLE_MAJOR_VERSION, - PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_PROTOCOL, /**< type */ - NULL, /**< ui_requirement */ - 0, /**< flags */ - NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ - - "prpl-msn", /**< id */ - "MSN", /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("MSN Protocol Plugin"), - /** description */ - N_("MSN Protocol Plugin"), - "Christian Hammond <chipx86@gnupdate.org>", /**< author */ - PURPLE_WEBSITE, /**< homepage */ - - msn_load, /**< load */ - msn_unload, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, /**< prefs_info */ - msn_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin *plugin) -{ - PurpleAccountOption *option; - - option = purple_account_option_string_new(_("Server"), "server", - MSN_SERVER); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); - - option = purple_account_option_int_new(_("Port"), "port", 1863); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); - - option = purple_account_option_bool_new(_("Use HTTP Method"), - "http_method", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); - - option = purple_account_option_string_new(_("HTTP Method Server"), - "http_method_server", MSN_HTTPCONN_SERVER); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); - - option = purple_account_option_bool_new(_("Show custom smileys"), - "custom_smileys", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); - - purple_cmd_register("nudge", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-msn", msn_cmd_nudge, - _("nudge: nudge a user to get their attention"), NULL); - - purple_prefs_remove("/plugins/prpl/msn"); - - purple_signal_connect(purple_get_core(), "uri-handler", plugin, - PURPLE_CALLBACK(msn_uri_handler), NULL); -} - -PURPLE_INIT_PLUGIN(msnp9, init_plugin, info);
--- a/libpurple/protocols/msnp9/msn.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/** - * @file msn.h The MSN protocol plugin - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_H_ -#define _MSN_H_ - -/* #define MSN_DEBUG_MSG 1 */ -/* #define MSN_DEBUG_SLPMSG 1 */ -/* #define MSN_DEBUG_HTTP 1 */ - -/* #define MSN_DEBUG_SLP 1 */ -/* #define MSN_DEBUG_SLP_VERBOSE 1 */ -/* #define MSN_DEBUG_SLP_FILES 1 */ - -/* #define MSN_DEBUG_NS 1 */ -/* #define MSN_DEBUG_SB 1 */ - -#include "internal.h" - -#include "account.h" -#include "accountopt.h" -#include "blist.h" -#include "connection.h" -#include "conversation.h" -#include "debug.h" -#include "cipher.h" -#include "notify.h" -#include "privacy.h" -#include "proxy.h" -#include "prpl.h" -#include "request.h" -#include "servconn.h" -#include "sslconn.h" -#include "util.h" - -#include "ft.h" - -#define MSN_BUF_LEN 8192 - -#define USEROPT_MSNSERVER 3 -#define MSN_SERVER "messenger.hotmail.com" -#define MSN_HTTPCONN_SERVER "gateway.messenger.hotmail.com" -#define USEROPT_MSNPORT 4 -#define MSN_PORT 1863 - -#define MSN_TYPING_RECV_TIMEOUT 6 -#define MSN_TYPING_SEND_TIMEOUT 4 - -#define HOTMAIL_URL "http://www.hotmail.com/cgi-bin/folders" -#define PASSPORT_URL "http://lc1.law13.hotmail.passport.com/cgi-bin/dologin?login=" -#define PROFILE_URL "http://spaces.live.com/profile.aspx?mem=" - -#define USEROPT_HOTMAIL 0 - -#define BUDDY_ALIAS_MAXLEN 387 - -#define MSN_FT_GUID "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" - -#define MSN_CLIENTINFO \ - "Client-Name: Purple/" VERSION "\r\n" \ - "Chat-Logging: Y\r\n" - -/* Index into attention_types */ -#define MSN_NUDGE 0 - -typedef enum -{ - MSN_LIST_FL_OP = 0x01, - MSN_LIST_AL_OP = 0x02, - MSN_LIST_BL_OP = 0x04, - MSN_LIST_RL_OP = 0x08 - -} MsnListOp; - -typedef enum -{ - MSN_CLIENT_CAP_WIN_MOBILE = 0x00001, - MSN_CLIENT_CAP_UNKNOWN_1 = 0x00002, - MSN_CLIENT_CAP_INK_GIF = 0x00004, - MSN_CLIENT_CAP_INK_ISF = 0x00008, - MSN_CLIENT_CAP_VIDEO_CHAT = 0x00010, - MSN_CLIENT_CAP_BASE = 0x00020, - MSN_CLIENT_CAP_MSNMOBILE = 0x00040, - MSN_CLIENT_CAP_MSNDIRECT = 0x00080, - MSN_CLIENT_CAP_WEBMSGR = 0x00100, - MSN_CLIENT_CAP_DIRECTIM = 0x04000, - MSN_CLIENT_CAP_WINKS = 0x08000, - MSN_CLIENT_CAP_SEARCH = 0x10000 - -} MsnClientCaps; - -typedef enum -{ - MSN_CLIENT_VER_5_0 = 0x00, - MSN_CLIENT_VER_6_0 = 0x10, /* MSNC1 */ - MSN_CLIENT_VER_6_1 = 0x20, /* MSNC2 */ - MSN_CLIENT_VER_6_2 = 0x30, /* MSNC3 */ - MSN_CLIENT_VER_7_0 = 0x40, /* MSNC4 */ - MSN_CLIENT_VER_7_5 = 0x50 /* MSNC5 */ - -} MsnClientVerId; - -#define MSN_CLIENT_ID_VERSION MSN_CLIENT_VER_7_0 -#define MSN_CLIENT_ID_RESERVED_1 0x00 -#define MSN_CLIENT_ID_RESERVED_2 0x00 -#define MSN_CLIENT_ID_CAPABILITIES MSN_CLIENT_CAP_BASE - -#define MSN_CLIENT_ID \ - ((MSN_CLIENT_ID_VERSION << 24) | \ - (MSN_CLIENT_ID_RESERVED_1 << 16) | \ - (MSN_CLIENT_ID_RESERVED_2 << 8) | \ - (MSN_CLIENT_ID_CAPABILITIES)) - -#endif /* _MSN_H_ */
--- a/libpurple/protocols/msnp9/nexus.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,513 +0,0 @@ -/** - * @file nexus.c MSN Nexus functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "nexus.h" -#include "notification.h" - -/************************************************************************** - * Main - **************************************************************************/ - -MsnNexus * -msn_nexus_new(MsnSession *session) -{ - MsnNexus *nexus; - - nexus = g_new0(MsnNexus, 1); - nexus->session = session; - nexus->challenge_data = g_hash_table_new_full(g_str_hash, - g_str_equal, g_free, g_free); - - return nexus; -} - -void -msn_nexus_destroy(MsnNexus *nexus) -{ - if (nexus->gsc) - purple_ssl_close(nexus->gsc); - - g_free(nexus->login_host); - - g_free(nexus->login_path); - - if (nexus->challenge_data != NULL) - g_hash_table_destroy(nexus->challenge_data); - - if (nexus->input_handler > 0) - purple_input_remove(nexus->input_handler); - g_free(nexus->write_buf); - g_free(nexus->read_buf); - - g_free(nexus); -} - -/************************************************************************** - * Util - **************************************************************************/ - -static gssize -msn_ssl_read(MsnNexus *nexus) -{ - gssize len; - char temp_buf[4096]; - - if ((len = purple_ssl_read(nexus->gsc, temp_buf, - sizeof(temp_buf))) > 0) - { - nexus->read_buf = g_realloc(nexus->read_buf, - nexus->read_len + len + 1); - strncpy(nexus->read_buf + nexus->read_len, temp_buf, len); - nexus->read_len += len; - nexus->read_buf[nexus->read_len] = '\0'; - } - - return len; -} - -static void -nexus_write_cb(gpointer data, gint source, PurpleInputCondition cond) -{ - MsnNexus *nexus = data; - int len, total_len; - - total_len = strlen(nexus->write_buf); - - len = purple_ssl_write(nexus->gsc, - nexus->write_buf + nexus->written_len, - total_len - nexus->written_len); - - if (len < 0 && errno == EAGAIN) - return; - else if (len <= 0) { - purple_input_remove(nexus->input_handler); - nexus->input_handler = 0; - /* TODO: notify of the error */ - return; - } - nexus->written_len += len; - - if (nexus->written_len < total_len) - return; - - purple_input_remove(nexus->input_handler); - nexus->input_handler = 0; - - g_free(nexus->write_buf); - nexus->write_buf = NULL; - nexus->written_len = 0; - - nexus->written_cb(nexus, source, 0); -} - -/************************************************************************** - * Login - **************************************************************************/ - -static void -login_connect_cb(gpointer data, PurpleSslConnection *gsc, - PurpleInputCondition cond); - -static void -login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data) -{ - MsnNexus *nexus; - MsnSession *session; - - nexus = data; - g_return_if_fail(nexus != NULL); - - nexus->gsc = NULL; - - session = nexus->session; - g_return_if_fail(session != NULL); - - msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Unable to connect")); - /* the above line will result in nexus being destroyed, so we don't want - * to destroy it here, or we'd crash */ -} - -static void -nexus_login_written_cb(gpointer data, gint source, PurpleInputCondition cond) -{ - MsnNexus *nexus = data; - MsnSession *session; - int len; - - session = nexus->session; - g_return_if_fail(session != NULL); - - if (nexus->input_handler == 0) - /* TODO: Use purple_ssl_input_add()? */ - nexus->input_handler = purple_input_add(nexus->gsc->fd, - PURPLE_INPUT_READ, nexus_login_written_cb, nexus); - - - len = msn_ssl_read(nexus); - - if (len < 0 && errno == EAGAIN) - return; - else if (len <= 0) { - purple_input_remove(nexus->input_handler); - nexus->input_handler = 0; - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - /* TODO: error handling */ - return; - } - - if (g_strstr_len(nexus->read_buf, nexus->read_len, - "\r\n\r\n") == NULL) - return; - - purple_input_remove(nexus->input_handler); - nexus->input_handler = 0; - - purple_ssl_close(nexus->gsc); - nexus->gsc = NULL; - - purple_debug_misc("msn", "ssl buffer: {%s}\n", nexus->read_buf); - - if (strstr(nexus->read_buf, "HTTP/1.1 302") != NULL) - { - /* Redirect. */ - char *location, *c; - - location = strstr(nexus->read_buf, "Location: "); - if (location == NULL) - { - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - - return; - } - location = strchr(location, ' ') + 1; - - if ((c = strchr(location, '\r')) != NULL) - *c = '\0'; - - /* Skip the http:// */ - if ((c = strchr(location, '/')) != NULL) - location = c + 2; - - if ((c = strchr(location, '/')) != NULL) - { - g_free(nexus->login_path); - nexus->login_path = g_strdup(c); - - *c = '\0'; - } - - g_free(nexus->login_host); - nexus->login_host = g_strdup(location); - - nexus->gsc = purple_ssl_connect(session->account, - nexus->login_host, PURPLE_SSL_DEFAULT_PORT, - login_connect_cb, login_error_cb, nexus); - } - else if (strstr(nexus->read_buf, "HTTP/1.1 401 Unauthorized") != NULL) - { - const char *error; - - if ((error = strstr(nexus->read_buf, "WWW-Authenticate")) != NULL) - { - if ((error = strstr(error, "cbtxt=")) != NULL) - { - const char *c; - char *temp; - - error += strlen("cbtxt="); - - if ((c = strchr(error, '\n')) == NULL) - c = error + strlen(error); - - temp = g_strndup(error, c - error); - error = purple_url_decode(temp); - g_free(temp); - if ((temp = strstr(error, " Do one of the following or try again:")) != NULL) - *temp = '\0'; - } - } - - msn_session_set_error(session, MSN_ERROR_AUTH, error); - } - else if (strstr(nexus->read_buf, "HTTP/1.1 503 Service Unavailable")) - { - msn_session_set_error(session, MSN_ERROR_SERV_UNAVAILABLE, NULL); - } - else if (strstr(nexus->read_buf, "HTTP/1.1 200 OK")) - { - char *base, *c; - char *login_params; - -#if 0 - /* All your base are belong to us. */ - base = buffer; - - /* For great cookie! */ - while ((base = strstr(base, "Set-Cookie: ")) != NULL) - { - base += strlen("Set-Cookie: "); - - c = strchr(base, ';'); - - session->login_cookies = - g_list_append(session->login_cookies, - g_strndup(base, c - base)); - } -#endif - - base = strstr(nexus->read_buf, "Authentication-Info: "); - - g_return_if_fail(base != NULL); - - base = strstr(base, "from-PP='"); - base += strlen("from-PP='"); - c = strchr(base, '\''); - - login_params = g_strndup(base, c - base); - - msn_got_login_params(session, login_params); - - g_free(login_params); - - msn_nexus_destroy(nexus); - session->nexus = NULL; - return; - } - - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - -} - -/* this guards against missing hash entries */ -static char * -nexus_challenge_data_lookup(GHashTable *challenge_data, const char *key) -{ - char *entry; - - return (entry = (char *)g_hash_table_lookup(challenge_data, key)) ? - entry : "(null)"; -} - -void -login_connect_cb(gpointer data, PurpleSslConnection *gsc, - PurpleInputCondition cond) -{ - MsnNexus *nexus; - MsnSession *session; - char *username, *password, *encpass; - char *request_str, *head, *tail; - char *buffer = NULL; - guint32 ctint; - - nexus = data; - g_return_if_fail(nexus != NULL); - - session = nexus->session; - g_return_if_fail(session != NULL); - - msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); - - username = - g_strdup(purple_url_encode(purple_account_get_username(session->account))); - - password = g_utf8_strncpy(g_strdup(purple_connection_get_password(session->account->gc)), - purple_connection_get_password(session->account->gc), 16); - encpass = g_strdup(purple_url_encode(password)); - g_free(password); - - ctint = strtoul((char *)g_hash_table_lookup(nexus->challenge_data, "ct"), NULL, 10) + 200; - - head = g_strdup_printf( - "GET %s HTTP/1.1\r\n" - "Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s", - nexus->login_path, - (char *)g_hash_table_lookup(nexus->challenge_data, "ru"), - username); - - tail = g_strdup_printf( - "lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%" G_GUINT32_FORMAT ",kpp=%s,kv=%s,ver=%s,tpf=%s\r\n" - "User-Agent: MSMSGS\r\n" - "Host: %s\r\n" - "Connection: Keep-Alive\r\n" - "Cache-Control: no-cache\r\n", - nexus_challenge_data_lookup(nexus->challenge_data, "lc"), - nexus_challenge_data_lookup(nexus->challenge_data, "id"), - nexus_challenge_data_lookup(nexus->challenge_data, "tw"), - nexus_challenge_data_lookup(nexus->challenge_data, "fs"), - nexus_challenge_data_lookup(nexus->challenge_data, "ru"), - ctint, - nexus_challenge_data_lookup(nexus->challenge_data, "kpp"), - nexus_challenge_data_lookup(nexus->challenge_data, "kv"), - nexus_challenge_data_lookup(nexus->challenge_data, "ver"), - nexus_challenge_data_lookup(nexus->challenge_data, "tpf"), - nexus->login_host); - - buffer = g_strdup_printf("%s,pwd=XXXXXXXX,%s\r\n", head, tail); - request_str = g_strdup_printf("%s,pwd=%s,%s\r\n", head, encpass, tail); - - purple_debug_misc("msn", "Sending: {%s}\n", buffer); - - g_free(buffer); - g_free(head); - g_free(tail); - g_free(username); - g_free(encpass); - - nexus->write_buf = request_str; - nexus->written_len = 0; - - nexus->read_len = 0; - - nexus->written_cb = nexus_login_written_cb; - - nexus->input_handler = purple_input_add(gsc->fd, PURPLE_INPUT_WRITE, - nexus_write_cb, nexus); - - nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE); - - return; - - -} - -static void -nexus_connect_written_cb(gpointer data, gint source, PurpleInputCondition cond) -{ - MsnNexus *nexus = data; - int len; - char *da_login; - char *base, *c; - - if (nexus->input_handler == 0) - /* TODO: Use purple_ssl_input_add()? */ - nexus->input_handler = purple_input_add(nexus->gsc->fd, - PURPLE_INPUT_READ, nexus_connect_written_cb, nexus); - - /* Get the PassportURLs line. */ - len = msn_ssl_read(nexus); - - if (len < 0 && errno == EAGAIN) - return; - else if (len <= 0) { - purple_input_remove(nexus->input_handler); - nexus->input_handler = 0; - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - /* TODO: error handling */ - return; - } - - if (g_strstr_len(nexus->read_buf, nexus->read_len, - "\r\n\r\n") == NULL) - return; - - purple_input_remove(nexus->input_handler); - nexus->input_handler = 0; - - base = strstr(nexus->read_buf, "PassportURLs"); - - if (base == NULL) - { - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - return; - } - - if ((da_login = strstr(base, "DALogin=")) != NULL) - { - /* skip over "DALogin=" */ - da_login += 8; - - if ((c = strchr(da_login, ',')) != NULL) - *c = '\0'; - - if ((c = strchr(da_login, '/')) != NULL) - { - nexus->login_path = g_strdup(c); - *c = '\0'; - } - - nexus->login_host = g_strdup(da_login); - } - - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - - purple_ssl_close(nexus->gsc); - - /* Now begin the connection to the login server. */ - nexus->gsc = purple_ssl_connect(nexus->session->account, - nexus->login_host, PURPLE_SSL_DEFAULT_PORT, - login_connect_cb, login_error_cb, nexus); -} - - -/************************************************************************** - * Connect - **************************************************************************/ - -static void -nexus_connect_cb(gpointer data, PurpleSslConnection *gsc, - PurpleInputCondition cond) -{ - MsnNexus *nexus; - MsnSession *session; - - nexus = data; - g_return_if_fail(nexus != NULL); - - session = nexus->session; - g_return_if_fail(session != NULL); - - msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH); - - nexus->write_buf = g_strdup("GET /rdr/pprdr.asp\r\n\r\n"); - nexus->written_len = 0; - - nexus->read_len = 0; - - nexus->written_cb = nexus_connect_written_cb; - - nexus->input_handler = purple_input_add(gsc->fd, PURPLE_INPUT_WRITE, - nexus_write_cb, nexus); - - nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE); -} - -void -msn_nexus_connect(MsnNexus *nexus) -{ - nexus->gsc = purple_ssl_connect(nexus->session->account, - "nexus.passport.com", PURPLE_SSL_DEFAULT_PORT, - nexus_connect_cb, login_error_cb, nexus); -}
--- a/libpurple/protocols/msnp9/nexus.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/** - * @file nexus.h MSN Nexus functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_NEXUS_H_ -#define _MSN_NEXUS_H_ - -typedef struct _MsnNexus MsnNexus; - -struct _MsnNexus -{ - MsnSession *session; - - char *login_host; - char *login_path; - GHashTable *challenge_data; - PurpleSslConnection *gsc; - - guint input_handler; - - char *write_buf; - gsize written_len; - PurpleInputFunction written_cb; - - char *read_buf; - gsize read_len; -}; - -void msn_nexus_connect(MsnNexus *nexus); -MsnNexus *msn_nexus_new(MsnSession *session); -void msn_nexus_destroy(MsnNexus *nexus); - -#endif /* _MSN_NEXUS_H_ */
--- a/libpurple/protocols/msnp9/notification.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1510 +0,0 @@ -/** - * @file notification.c Notification server functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "notification.h" -#include "state.h" -#include "error.h" -#include "msn-utils.h" -#include "page.h" - -#include "userlist.h" -#include "sync.h" -#include "slplink.h" - -static MsnTable *cbs_table; - -/************************************************************************** - * Main - **************************************************************************/ - -static void -destroy_cb(MsnServConn *servconn) -{ - MsnNotification *notification; - - notification = servconn->cmdproc->data; - g_return_if_fail(notification != NULL); - - msn_notification_destroy(notification); -} - -MsnNotification * -msn_notification_new(MsnSession *session) -{ - MsnNotification *notification; - MsnServConn *servconn; - - g_return_val_if_fail(session != NULL, NULL); - - notification = g_new0(MsnNotification, 1); - - notification->session = session; - notification->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_NS); - msn_servconn_set_destroy_cb(servconn, destroy_cb); - - notification->cmdproc = servconn->cmdproc; - notification->cmdproc->data = notification; - notification->cmdproc->cbs_table = cbs_table; - - return notification; -} - -void -msn_notification_destroy(MsnNotification *notification) -{ - notification->cmdproc->data = NULL; - - msn_servconn_set_destroy_cb(notification->servconn, NULL); - - msn_servconn_destroy(notification->servconn); - - g_free(notification); -} - -/************************************************************************** - * Connect - **************************************************************************/ - -static void -connect_cb(MsnServConn *servconn) -{ - MsnCmdProc *cmdproc; - MsnSession *session; - PurpleAccount *account; - char **a, **c, *vers; - int i; - - g_return_if_fail(servconn != NULL); - - cmdproc = servconn->cmdproc; - session = servconn->session; - account = session->account; - - /* Allocate an array for CVR0, NULL, and all the versions */ - a = c = g_new0(char *, session->protocol_ver - 8 + 3); - - for (i = session->protocol_ver; i >= 8; i--) - *c++ = g_strdup_printf("MSNP%d", i); - - *c++ = g_strdup("CVR0"); - - vers = g_strjoinv(" ", a); - - if (session->login_step == MSN_LOGIN_STEP_START) - msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE); - else - msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE2); - - msn_cmdproc_send(cmdproc, "VER", "%s", vers); - - g_strfreev(a); - g_free(vers); -} - -gboolean -msn_notification_connect(MsnNotification *notification, const char *host, int port) -{ - MsnServConn *servconn; - - g_return_val_if_fail(notification != NULL, FALSE); - - servconn = notification->servconn; - - msn_servconn_set_connect_cb(servconn, connect_cb); - notification->in_use = msn_servconn_connect(servconn, host, port); - - return notification->in_use; -} - -void -msn_notification_disconnect(MsnNotification *notification) -{ - g_return_if_fail(notification != NULL); - g_return_if_fail(notification->in_use); - - msn_servconn_disconnect(notification->servconn); - - notification->in_use = FALSE; -} - -/************************************************************************** - * Util - **************************************************************************/ - -static void -group_error_helper(MsnSession *session, const char *msg, int group_id, int error) -{ - PurpleAccount *account; - PurpleConnection *gc; - char *reason = NULL; - char *title = NULL; - - account = session->account; - gc = purple_account_get_connection(account); - - if (error == 224) - { - if (group_id == 0) - { - return; - } - else - { - const char *group_name; - group_name = - msn_userlist_find_group_name(session->userlist, - group_id); - reason = g_strdup_printf(_("%s is not a valid group."), - group_name); - } - } - else - { - reason = g_strdup(_("Unknown error.")); - } - - title = g_strdup_printf(_("%s on %s (%s)"), msg, - purple_account_get_username(account), - purple_account_get_protocol_name(account)); - purple_notify_error(gc, NULL, title, reason); - g_free(title); - g_free(reason); -} - -/************************************************************************** - * Login - **************************************************************************/ - -void -msn_got_login_params(MsnSession *session, const char *login_params) -{ - MsnCmdProc *cmdproc; - - cmdproc = session->notification->cmdproc; - - msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END); - - msn_cmdproc_send(cmdproc, "USR", "TWN S %s", login_params); -} - -static void -cvr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - PurpleAccount *account; - - account = cmdproc->session->account; - - msn_cmdproc_send(cmdproc, "USR", "TWN I %s", - purple_account_get_username(account)); -} - -static void -usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - PurpleAccount *account; - PurpleConnection *gc; - - session = cmdproc->session; - account = session->account; - gc = purple_account_get_connection(account); - - if (!g_ascii_strcasecmp(cmd->params[1], "OK")) - { - /* OK */ - const char *friendly = purple_url_decode(cmd->params[3]); - - session->passport_info.verified = atoi(cmd->params[4]); - - purple_connection_set_display_name(gc, friendly); - - msn_session_set_login_step(session, MSN_LOGIN_STEP_SYN); - - msn_cmdproc_send(cmdproc, "SYN", "%s", "0"); - } - else if (!g_ascii_strcasecmp(cmd->params[1], "TWN")) - { - /* Passport authentication */ - char **elems, **cur, **tokens; - - session->nexus = msn_nexus_new(session); - - /* Parse the challenge data. */ - - elems = g_strsplit(cmd->params[3], ",", 0); - - for (cur = elems; *cur != NULL; cur++) - { - tokens = g_strsplit(*cur, "=", 2); - g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]); - /* Don't free each of the tokens, only the array. */ - g_free(tokens); - } - - g_strfreev(elems); - - msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_START); - - msn_nexus_connect(session->nexus); - } -} - -static void -usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) -{ - MsnErrorType msnerr = 0; - - switch (error) - { - case 500: - case 601: - case 910: - case 921: - msnerr = MSN_ERROR_SERV_UNAVAILABLE; - break; - case 911: - msnerr = MSN_ERROR_AUTH; - break; - default: - return; - break; - } - - msn_session_set_error(cmdproc->session, msnerr, NULL); -} - -static void -ver_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - PurpleAccount *account; - gboolean protocol_supported = FALSE; - char proto_str[8]; - size_t i; - - session = cmdproc->session; - account = session->account; - - g_snprintf(proto_str, sizeof(proto_str), "MSNP%d", session->protocol_ver); - - for (i = 1; i < cmd->param_count; i++) - { - if (!strcmp(cmd->params[i], proto_str)) - { - protocol_supported = TRUE; - break; - } - } - - if (!protocol_supported) - { - msn_session_set_error(session, MSN_ERROR_UNSUPPORTED_PROTOCOL, - NULL); - return; - } - - msn_cmdproc_send(cmdproc, "CVR", - "0x0409 winnt 5.1 i386 MSNMSGR 6.0.0602 MSMSGS %s", - purple_account_get_username(account)); -} - -/************************************************************************** - * Log out - **************************************************************************/ - -static void -out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - if (!g_ascii_strcasecmp(cmd->params[0], "OTH")) - msn_session_set_error(cmdproc->session, MSN_ERROR_SIGN_OTHER, - NULL); - else if (!g_ascii_strcasecmp(cmd->params[0], "SSD")) - msn_session_set_error(cmdproc->session, MSN_ERROR_SERV_DOWN, NULL); -} - -void -msn_notification_close(MsnNotification *notification) -{ - g_return_if_fail(notification != NULL); - - if (!notification->in_use) - return; - - msn_cmdproc_send_quick(notification->cmdproc, "OUT", NULL, NULL); - - msn_notification_disconnect(notification); -} - -/************************************************************************** - * Messages - **************************************************************************/ - -static void -msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, - size_t len) -{ - MsnMessage *msg; - - msg = msn_message_new_from_cmd(cmdproc->session, cmd); - - msn_message_parse_payload(msg, payload, len); -#ifdef MSN_DEBUG_NS - msn_message_show_readable(msg, "Notification", TRUE); -#endif - - msn_cmdproc_process_msg(cmdproc, msg); - - msn_message_destroy(msg); -} - -static void -msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - /* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued - * command and we are processing it */ - - if (cmd->payload == NULL) - { - cmdproc->last_cmd->payload_cb = msg_cmd_post; - cmdproc->servconn->payload_len = atoi(cmd->params[2]); - } - else - { - g_return_if_fail(cmd->payload_cb != NULL); - - cmd->payload_cb(cmdproc, cmd, cmd->payload, cmd->payload_len); - } -} - -/************************************************************************** - * Challenges - **************************************************************************/ - -static void -chl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnTransaction *trans; - char buf[33]; - const char *challenge_resp; - PurpleCipher *cipher; - PurpleCipherContext *context; - guchar digest[16]; - int i; - - cipher = purple_ciphers_find_cipher("md5"); - context = purple_cipher_context_new(cipher, NULL); - - purple_cipher_context_append(context, (const guchar *)cmd->params[1], - strlen(cmd->params[1])); - - challenge_resp = "VT6PX?UQTM4WM%YR"; - - purple_cipher_context_append(context, (const guchar *)challenge_resp, - strlen(challenge_resp)); - purple_cipher_context_digest(context, sizeof(digest), digest, NULL); - purple_cipher_context_destroy(context); - - for (i = 0; i < 16; i++) - g_snprintf(buf + (i*2), 3, "%02x", digest[i]); - - trans = msn_transaction_new(cmdproc, "QRY", "%s 32", "PROD0038W!61ZTF9"); - - msn_transaction_set_payload(trans, buf, 32); - - msn_cmdproc_send_trans(cmdproc, trans); -} - -/************************************************************************** - * Buddy Lists - **************************************************************************/ - -static void -add_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - MsnUser *user; - const char *list; - const char *passport; - const char *friendly; - MsnListId list_id; - int group_id; - - list = cmd->params[1]; - passport = cmd->params[3]; - friendly = purple_url_decode(cmd->params[4]); - - session = cmdproc->session; - - user = msn_userlist_find_user(session->userlist, passport); - - if (user == NULL) - { - user = msn_user_new(session->userlist, passport, friendly); - msn_userlist_add_user(session->userlist, user); - } - else - msn_user_set_friendly_name(user, friendly); - - list_id = msn_get_list_id(list); - - if (cmd->param_count >= 6) - group_id = atoi(cmd->params[5]); - else - group_id = -1; - - msn_got_add_user(session, user, list_id, group_id); - msn_user_update(user); -} - -static void -add_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) -{ - MsnSession *session; - PurpleAccount *account; - PurpleConnection *gc; - const char *list, *passport; - char *reason = NULL; - char *msg = NULL; - char **params; - - session = cmdproc->session; - account = session->account; - gc = purple_account_get_connection(account); - params = g_strsplit(trans->params, " ", 0); - - list = params[0]; - passport = params[1]; - - if (!strcmp(list, "FL")) - msg = g_strdup_printf(_("Unable to add user on %s (%s)"), - purple_account_get_username(account), - purple_account_get_protocol_name(account)); - else if (!strcmp(list, "BL")) - msg = g_strdup_printf(_("Unable to block user on %s (%s)"), - purple_account_get_username(account), - purple_account_get_protocol_name(account)); - else if (!strcmp(list, "AL")) - msg = g_strdup_printf(_("Unable to permit user on %s (%s)"), - purple_account_get_username(account), - purple_account_get_protocol_name(account)); - - if (!strcmp(list, "FL")) - { - if (error == 210) - { - reason = g_strdup_printf(_("%s could not be added because " - "your buddy list is full."), passport); - } - } - - if (reason == NULL) - { - if (error == 208) - { - reason = g_strdup_printf(_("%s is not a valid passport account."), - passport); - } - else if (error == 500) - { - reason = g_strdup(_("Service Temporarily Unavailable.")); - } - else - { - reason = g_strdup(_("Unknown error.")); - } - } - - if (msg != NULL) - { - purple_notify_error(gc, NULL, msg, reason); - g_free(msg); - } - - if (!strcmp(list, "FL")) - { - PurpleBuddy *buddy; - - buddy = purple_find_buddy(account, passport); - - if (buddy != NULL) - purple_blist_remove_buddy(buddy); - } - - g_free(reason); - - g_strfreev(params); -} - -static void -adg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - gint group_id; - const char *group_name; - - session = cmdproc->session; - - group_id = atoi(cmd->params[3]); - - group_name = purple_url_decode(cmd->params[2]); - - msn_group_new(session->userlist, group_id, group_name); - - /* There is a user that must me moved to this group */ - if (cmd->trans->data) - { - /* msn_userlist_move_buddy(); */ - MsnUserList *userlist = cmdproc->session->userlist; - MsnMoveBuddy *data = cmd->trans->data; - - if (data->old_group_name != NULL) - { - msn_userlist_rem_buddy(userlist, data->who, MSN_LIST_FL, data->old_group_name); - g_free(data->old_group_name); - } - - msn_userlist_add_buddy(userlist, data->who, MSN_LIST_FL, group_name); - g_free(data->who); - - } -} - -static void -qng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - static int count = 0; - const char *passport; - PurpleAccount *account; - - session = cmdproc->session; - account = session->account; - - if (session->passport_info.file == NULL) - return; - - passport = purple_normalize(account, purple_account_get_username(account)); - - if ((strstr(passport, "@hotmail.") == NULL) && - (strstr(passport, "@live.com") == NULL) && - (strstr(passport, "@msn.com") == NULL)) - return; - - if (count++ < 26) - return; - - count = 0; - msn_cmdproc_send(cmdproc, "URL", "%s", "INBOX"); -} - - -static void -fln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSlpLink *slplink; - MsnUser *user; - - user = msn_userlist_find_user(cmdproc->session->userlist, cmd->params[0]); - - user->status = "offline"; - msn_user_update(user); - - slplink = msn_session_find_slplink(cmdproc->session, cmd->params[0]); - - if (slplink != NULL) - msn_slplink_destroy(slplink); - -} - -static void -iln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - PurpleAccount *account; - PurpleConnection *gc; - MsnUser *user; - MsnObject *msnobj; - const char *state, *passport, *friendly; - - session = cmdproc->session; - account = session->account; - gc = purple_account_get_connection(account); - - state = cmd->params[1]; - passport = cmd->params[2]; - friendly = purple_url_decode(cmd->params[3]); - - user = msn_userlist_find_user(session->userlist, passport); - - serv_got_alias(gc, passport, friendly); - - msn_user_set_friendly_name(user, friendly); - - if (session->protocol_ver >= 9 && cmd->param_count == 6) - { - msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[5])); - msn_user_set_object(user, msnobj); - } - - msn_user_set_state(user, state); - msn_user_update(user); -} - -static void -ipg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len) -{ -#if 0 - purple_debug_misc("msn", "Incoming Page: {%s}\n", payload); -#endif -} - -static void -ipg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - cmdproc->servconn->payload_len = atoi(cmd->params[0]); - cmdproc->last_cmd->payload_cb = ipg_cmd_post; -} - -static void -nln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - PurpleAccount *account; - PurpleConnection *gc; - MsnUser *user; - MsnObject *msnobj; - int clientid; - const char *state, *passport, *friendly, *old_friendly; - - session = cmdproc->session; - account = session->account; - gc = purple_account_get_connection(account); - - state = cmd->params[0]; - passport = cmd->params[1]; - friendly = purple_url_decode(cmd->params[2]); - - user = msn_userlist_find_user(session->userlist, passport); - - old_friendly = msn_user_get_friendly_name(user); - if (!old_friendly || (old_friendly && (!friendly || strcmp(old_friendly, friendly)))) - { - serv_got_alias(gc, passport, friendly); - msn_user_set_friendly_name(user, friendly); - } - - if (session->protocol_ver >= 9) - { - if (cmd->param_count == 5) - { - msnobj = - msn_object_new_from_string(purple_url_decode(cmd->params[4])); - msn_user_set_object(user, msnobj); - } - else - { - msn_user_set_object(user, NULL); - } - } - - clientid = atoi(cmd->params[3]); - user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE); - - msn_user_set_state(user, state); - msn_user_update(user); -} - -#if 0 -static void -chg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - char *state = cmd->params[1]; - int state_id = 0; - - if (!strcmp(state, "NLN")) - state_id = MSN_ONLINE; - else if (!strcmp(state, "BSY")) - state_id = MSN_BUSY; - else if (!strcmp(state, "IDL")) - state_id = MSN_IDLE; - else if (!strcmp(state, "BRB")) - state_id = MSN_BRB; - else if (!strcmp(state, "AWY")) - state_id = MSN_AWAY; - else if (!strcmp(state, "PHN")) - state_id = MSN_PHONE; - else if (!strcmp(state, "LUN")) - state_id = MSN_LUNCH; - else if (!strcmp(state, "HDN")) - state_id = MSN_HIDDEN; - - cmdproc->session->state = state_id; -} -#endif - - -static void -not_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len) -{ -#if 0 - MSN_SET_PARAMS("NOT %d\r\n%s", cmdproc->servconn->payload, payload); - purple_debug_misc("msn", "Notification: {%s}\n", payload); -#endif -} - -static void -not_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - cmdproc->servconn->payload_len = atoi(cmd->params[0]); - cmdproc->last_cmd->payload_cb = not_cmd_post; -} - -static void -rea_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - PurpleAccount *account; - PurpleConnection *gc; - const char *friendly; - char *username; - - session = cmdproc->session; - account = session->account; - username = g_strdup(purple_normalize(account, - purple_account_get_username(account))); - - /* Only set display name if our *own* friendly name changed! */ - if (strcmp(username, purple_normalize(account, cmd->params[2]))) - { - g_free(username); - return; - } - - g_free(username); - - gc = account->gc; - friendly = purple_url_decode(cmd->params[3]); - - purple_connection_set_display_name(gc, friendly); -} - -static void -prp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session = cmdproc->session; - const char *type, *value; - - g_return_if_fail(cmd->param_count >= 3); - - type = cmd->params[2]; - - if (cmd->param_count == 4) - { - value = cmd->params[3]; - if (!strcmp(type, "PHH")) - msn_user_set_home_phone(session->user, purple_url_decode(value)); - else if (!strcmp(type, "PHW")) - msn_user_set_work_phone(session->user, purple_url_decode(value)); - else if (!strcmp(type, "PHM")) - msn_user_set_mobile_phone(session->user, purple_url_decode(value)); - } - else - { - if (!strcmp(type, "PHH")) - msn_user_set_home_phone(session->user, NULL); - else if (!strcmp(type, "PHW")) - msn_user_set_work_phone(session->user, NULL); - else if (!strcmp(type, "PHM")) - msn_user_set_mobile_phone(session->user, NULL); - } -} - -static void -bpr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - const char *type, *value, *passport; - MsnUser *user; - - passport = cmd->params[1]; - user = msn_userlist_find_user(cmdproc->session->userlist, passport); - - g_return_if_fail(user != NULL); - - type = cmd->params[2]; - value = cmd->params[3]; - - if (value) - { - if (!strcmp(type, "MOB")) - { - if (!strcmp(value, "Y")) - user->mobile = TRUE; - else if (!strcmp(value, "N")) - user->mobile = FALSE; - } - else if (!strcmp(type, "PHH")) - msn_user_set_home_phone(user, purple_url_decode(value)); - else if (!strcmp(type, "PHW")) - msn_user_set_work_phone(user, purple_url_decode(value)); - else if (!strcmp(type, "PHM")) - msn_user_set_mobile_phone(user, purple_url_decode(value)); - } -} - -static void -reg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - int group_id; - const char *group_name; - - session = cmdproc->session; - group_id = atoi(cmd->params[2]); - group_name = purple_url_decode(cmd->params[3]); - - msn_userlist_rename_group_id(session->userlist, group_id, group_name); -} - -static void -reg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) -{ - int group_id; - char **params; - - params = g_strsplit(trans->params, " ", 0); - - group_id = atoi(params[0]); - - group_error_helper(cmdproc->session, _("Unable to rename group"), group_id, error); - - g_strfreev(params); -} - -static void -rem_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - MsnUser *user; - const char *list; - const char *passport; - MsnListId list_id; - int group_id; - - session = cmdproc->session; - list = cmd->params[1]; - passport = cmd->params[3]; - user = msn_userlist_find_user(session->userlist, passport); - - g_return_if_fail(user != NULL); - - list_id = msn_get_list_id(list); - - if (cmd->param_count == 5) - group_id = atoi(cmd->params[4]); - else - group_id = -1; - - msn_got_rem_user(session, user, list_id, group_id); - msn_user_update(user); -} - -static void -rmg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - int group_id; - - session = cmdproc->session; - group_id = atoi(cmd->params[2]); - - msn_userlist_remove_group_id(session->userlist, group_id); -} - -static void -rmg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) -{ - int group_id; - char **params; - - params = g_strsplit(trans->params, " ", 0); - - group_id = atoi(params[0]); - - group_error_helper(cmdproc->session, _("Unable to delete group"), group_id, error); - - g_strfreev(params); -} - -static void -syn_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - MsnSync *sync; - int total_users; - - session = cmdproc->session; - - if (cmd->param_count == 2) - { - /* - * This can happen if we sent a SYN with an up-to-date - * buddy list revision, but we send 0 to get a full list. - * So, error out. - */ - - msn_session_set_error(cmdproc->session, MSN_ERROR_BAD_BLIST, NULL); - return; - } - - total_users = atoi(cmd->params[2]); - - sync = msn_sync_new(session); - sync->total_users = total_users; - sync->old_cbs_table = cmdproc->cbs_table; - - session->sync = sync; - cmdproc->cbs_table = sync->cbs_table; -} - -/************************************************************************** - * Misc commands - **************************************************************************/ - -static void -url_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - PurpleAccount *account; - const char *rru; - const char *url; - PurpleCipher *cipher; - PurpleCipherContext *context; - guchar digest[16]; - FILE *fd; - char *buf; - char buf2[3]; - char sendbuf[64]; - int i; - - session = cmdproc->session; - account = session->account; - - rru = cmd->params[1]; - url = cmd->params[2]; - - buf = g_strdup_printf("%s%lu%s", - session->passport_info.mspauth ? session->passport_info.mspauth : "BOGUS", - time(NULL) - session->passport_info.sl, - purple_connection_get_password(account->gc)); - - cipher = purple_ciphers_find_cipher("md5"); - context = purple_cipher_context_new(cipher, NULL); - - purple_cipher_context_append(context, (const guchar *)buf, strlen(buf)); - purple_cipher_context_digest(context, sizeof(digest), digest, NULL); - purple_cipher_context_destroy(context); - - g_free(buf); - - memset(sendbuf, 0, sizeof(sendbuf)); - - for (i = 0; i < 16; i++) - { - g_snprintf(buf2, sizeof(buf2), "%02x", digest[i]); - strcat(sendbuf, buf2); - } - - if (session->passport_info.file != NULL) - { - g_unlink(session->passport_info.file); - g_free(session->passport_info.file); - } - - if ((fd = purple_mkstemp(&session->passport_info.file, FALSE)) == NULL) - { - purple_debug_error("msn", - "Error opening temp passport file: %s\n", - g_strerror(errno)); - } - else - { -#ifdef _WIN32 - fputs("<!-- saved from url=(0013)about:internet -->\n", fd); -#endif - fputs("<html>\n" - "<head>\n" - "<noscript>\n" - "<meta http-equiv=\"Refresh\" content=\"0; " - "url=http://www.hotmail.com\">\n" - "</noscript>\n" - "</head>\n\n", - fd); - - fprintf(fd, "<body onload=\"document.pform.submit(); \">\n"); - fprintf(fd, "<form name=\"pform\" action=\"%s\" method=\"POST\">\n\n", - url); - fprintf(fd, "<input type=\"hidden\" name=\"mode\" value=\"ttl\">\n"); - fprintf(fd, "<input type=\"hidden\" name=\"login\" value=\"%s\">\n", - purple_account_get_username(account)); - fprintf(fd, "<input type=\"hidden\" name=\"username\" value=\"%s\">\n", - purple_account_get_username(account)); - if (session->passport_info.sid != NULL) - fprintf(fd, "<input type=\"hidden\" name=\"sid\" value=\"%s\">\n", - session->passport_info.sid); - if (session->passport_info.kv != NULL) - fprintf(fd, "<input type=\"hidden\" name=\"kv\" value=\"%s\">\n", - session->passport_info.kv); - fprintf(fd, "<input type=\"hidden\" name=\"id\" value=\"2\">\n"); - fprintf(fd, "<input type=\"hidden\" name=\"sl\" value=\"%ld\">\n", - time(NULL) - session->passport_info.sl); - fprintf(fd, "<input type=\"hidden\" name=\"rru\" value=\"%s\">\n", - rru); - if (session->passport_info.mspauth != NULL) - fprintf(fd, "<input type=\"hidden\" name=\"auth\" value=\"%s\">\n", - session->passport_info.mspauth); - fprintf(fd, "<input type=\"hidden\" name=\"creds\" value=\"%s\">\n", - sendbuf); /* TODO Digest me (huh? -- ChipX86) */ - fprintf(fd, "<input type=\"hidden\" name=\"svc\" value=\"mail\">\n"); - fprintf(fd, "<input type=\"hidden\" name=\"js\" value=\"yes\">\n"); - fprintf(fd, "</form></body>\n"); - fprintf(fd, "</html>\n"); - - if (fclose(fd)) - { - purple_debug_error("msn", - "Error closing temp passport file: %s\n", - g_strerror(errno)); - - g_unlink(session->passport_info.file); - g_free(session->passport_info.file); - session->passport_info.file = NULL; - } -#ifdef _WIN32 - else - { - /* - * Renaming file with .html extension, so that the - * win32 open_url will work. - */ - char *tmp; - - if ((tmp = - g_strdup_printf("%s.html", - session->passport_info.file)) != NULL) - { - if (g_rename(session->passport_info.file, - tmp) == 0) - { - g_free(session->passport_info.file); - session->passport_info.file = tmp; - } - else - g_free(tmp); - } - } -#endif - } -} -/************************************************************************** - * Switchboards - **************************************************************************/ - -static void -rng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - MsnSwitchBoard *swboard; - const char *session_id; - char *host; - int port; - - session = cmdproc->session; - session_id = cmd->params[0]; - - msn_parse_socket(cmd->params[1], &host, &port); - - if (session->http_method) - port = 80; - - swboard = msn_switchboard_new(session); - - msn_switchboard_set_invited(swboard, TRUE); - msn_switchboard_set_session_id(swboard, cmd->params[0]); - msn_switchboard_set_auth_key(swboard, cmd->params[3]); - swboard->im_user = g_strdup(cmd->params[4]); - /* msn_switchboard_add_user(swboard, cmd->params[4]); */ - - if (!msn_switchboard_connect(swboard, host, port)) - msn_switchboard_destroy(swboard); - - g_free(host); -} - -static void -xfr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - char *host; - int port; - - if (strcmp(cmd->params[1], "SB") && strcmp(cmd->params[1], "NS")) - { - /* Maybe we can have a generic bad command error. */ - purple_debug_error("msn", "Bad XFR command (%s)\n", cmd->params[1]); - return; - } - - msn_parse_socket(cmd->params[2], &host, &port); - - if (!strcmp(cmd->params[1], "SB")) - { - purple_debug_error("msn", "This shouldn't be handled here.\n"); - } - else if (!strcmp(cmd->params[1], "NS")) - { - MsnSession *session; - - session = cmdproc->session; - - msn_session_set_login_step(session, MSN_LOGIN_STEP_TRANSFER); - - msn_notification_connect(session->notification, host, port); - } - - g_free(host); -} - -/************************************************************************** - * Message Types - **************************************************************************/ - -static void -profile_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - MsnSession *session; - const char *value; - - session = cmdproc->session; - - if (strcmp(msg->remote_user, "Hotmail")) - /* This isn't an official message. */ - return; - - if ((value = msn_message_get_attr(msg, "kv")) != NULL) - { - g_free(session->passport_info.kv); - session->passport_info.kv = g_strdup(value); - } - - if ((value = msn_message_get_attr(msg, "sid")) != NULL) - { - g_free(session->passport_info.sid); - session->passport_info.sid = g_strdup(value); - } - - if ((value = msn_message_get_attr(msg, "MSPAuth")) != NULL) - { - g_free(session->passport_info.mspauth); - session->passport_info.mspauth = g_strdup(value); - } - - if ((value = msn_message_get_attr(msg, "ClientIP")) != NULL) - { - g_free(session->passport_info.client_ip); - session->passport_info.client_ip = g_strdup(value); - } - - if ((value = msn_message_get_attr(msg, "ClientPort")) != NULL) - session->passport_info.client_port = ntohs(atoi(value)); - - if ((value = msn_message_get_attr(msg, "LoginTime")) != NULL) - session->passport_info.sl = atol(value); -} - -static void -initial_email_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - MsnSession *session; - PurpleConnection *gc; - GHashTable *table; - const char *unread; - - session = cmdproc->session; - gc = session->account->gc; - - if (strcmp(msg->remote_user, "Hotmail")) - /* This isn't an official message. */ - return; - - if (session->passport_info.file == NULL) - { - MsnTransaction *trans; - trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX"); - msn_transaction_queue_cmd(trans, msg->cmd); - - msn_cmdproc_send_trans(cmdproc, trans); - - return; - } - - if (!purple_account_get_check_mail(session->account)) - return; - - table = msn_message_get_hashtable_from_body(msg); - - unread = g_hash_table_lookup(table, "Inbox-Unread"); - - if (unread != NULL) - { - int count = atoi(unread); - - if (count > 0) - { - const char *passports[2] = { msn_user_get_passport(session->user) }; - const char *urls[2] = { session->passport_info.file }; - - purple_notify_emails(gc, count, FALSE, NULL, NULL, - passports, urls, NULL, NULL); - } - } - - g_hash_table_destroy(table); -} - -static void -email_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - MsnSession *session; - PurpleConnection *gc; - GHashTable *table; - char *from, *subject, *tmp; - - session = cmdproc->session; - gc = session->account->gc; - - if (strcmp(msg->remote_user, "Hotmail")) - /* This isn't an official message. */ - return; - - if (session->passport_info.file == NULL) - { - MsnTransaction *trans; - trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX"); - msn_transaction_queue_cmd(trans, msg->cmd); - - msn_cmdproc_send_trans(cmdproc, trans); - - return; - } - - if (!purple_account_get_check_mail(session->account)) - return; - - table = msn_message_get_hashtable_from_body(msg); - - from = subject = NULL; - - tmp = g_hash_table_lookup(table, "From"); - if (tmp != NULL) - from = purple_mime_decode_field(tmp); - - tmp = g_hash_table_lookup(table, "Subject"); - if (tmp != NULL) - subject = purple_mime_decode_field(tmp); - - purple_notify_email(gc, - (subject != NULL ? subject : ""), - (from != NULL ? from : ""), - msn_user_get_passport(session->user), - session->passport_info.file, NULL, NULL); - - g_free(from); - g_free(subject); - - g_hash_table_destroy(table); -} - -static void -system_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - GHashTable *table; - const char *type_s; - - if (strcmp(msg->remote_user, "Hotmail")) - /* This isn't an official message. */ - return; - - table = msn_message_get_hashtable_from_body(msg); - - if ((type_s = g_hash_table_lookup(table, "Type")) != NULL) - { - int type = atoi(type_s); - char buf[MSN_BUF_LEN]; - int minutes; - - switch (type) - { - case 1: - minutes = atoi(g_hash_table_lookup(table, "Arg1")); - g_snprintf(buf, sizeof(buf), dngettext(PACKAGE, - "The MSN server will shut down for maintenance " - "in %d minute. You will automatically be " - "signed out at that time. Please finish any " - "conversations in progress.\n\nAfter the " - "maintenance has been completed, you will be " - "able to successfully sign in.", - "The MSN server will shut down for maintenance " - "in %d minutes. You will automatically be " - "signed out at that time. Please finish any " - "conversations in progress.\n\nAfter the " - "maintenance has been completed, you will be " - "able to successfully sign in.", minutes), - minutes); - default: - break; - } - - if (*buf != '\0') - purple_notify_info(cmdproc->session->account->gc, NULL, buf, NULL); - } - - g_hash_table_destroy(table); -} - -void -msn_notification_add_buddy(MsnNotification *notification, const char *list, - const char *who, const char *friendly_name, - int group_id) -{ - MsnCmdProc *cmdproc; - cmdproc = notification->servconn->cmdproc; - - if (group_id < 0 && !strcmp(list, "FL")) - group_id = 0; - - if (group_id >= 0) - { - msn_cmdproc_send(cmdproc, "ADD", "%s %s %s %d", - list, who, friendly_name, group_id); - } - else - { - msn_cmdproc_send(cmdproc, "ADD", "%s %s %s", list, who, friendly_name); - } -} - -void -msn_notification_rem_buddy(MsnNotification *notification, const char *list, - const char *who, int group_id) -{ - MsnCmdProc *cmdproc; - cmdproc = notification->servconn->cmdproc; - - if (group_id >= 0) - { - msn_cmdproc_send(cmdproc, "REM", "%s %s %d", list, who, group_id); - } - else - { - msn_cmdproc_send(cmdproc, "REM", "%s %s", list, who); - } -} - -/************************************************************************** - * Init - **************************************************************************/ - -void -msn_notification_init(void) -{ - /* TODO: check prp, blp */ - - cbs_table = msn_table_new(); - - /* Synchronous */ - msn_table_add_cmd(cbs_table, "CHG", "CHG", NULL); - msn_table_add_cmd(cbs_table, "CHG", "ILN", iln_cmd); - msn_table_add_cmd(cbs_table, "ADD", "ADD", add_cmd); - msn_table_add_cmd(cbs_table, "ADD", "ILN", iln_cmd); - msn_table_add_cmd(cbs_table, "REM", "REM", rem_cmd); - msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd); - msn_table_add_cmd(cbs_table, "USR", "XFR", xfr_cmd); - msn_table_add_cmd(cbs_table, "SYN", "SYN", syn_cmd); - msn_table_add_cmd(cbs_table, "CVR", "CVR", cvr_cmd); - msn_table_add_cmd(cbs_table, "VER", "VER", ver_cmd); - msn_table_add_cmd(cbs_table, "REA", "REA", rea_cmd); - msn_table_add_cmd(cbs_table, "PRP", "PRP", prp_cmd); - /* msn_table_add_cmd(cbs_table, "BLP", "BLP", blp_cmd); */ - msn_table_add_cmd(cbs_table, "BLP", "BLP", NULL); - msn_table_add_cmd(cbs_table, "REG", "REG", reg_cmd); - msn_table_add_cmd(cbs_table, "ADG", "ADG", adg_cmd); - msn_table_add_cmd(cbs_table, "RMG", "RMG", rmg_cmd); - msn_table_add_cmd(cbs_table, "XFR", "XFR", xfr_cmd); - - /* Asynchronous */ - msn_table_add_cmd(cbs_table, NULL, "IPG", ipg_cmd); - msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd); - msn_table_add_cmd(cbs_table, NULL, "NOT", not_cmd); - msn_table_add_cmd(cbs_table, NULL, "BPR", bpr_cmd); - - msn_table_add_cmd(cbs_table, NULL, "CHL", chl_cmd); - msn_table_add_cmd(cbs_table, NULL, "REM", rem_cmd); - msn_table_add_cmd(cbs_table, NULL, "ADD", add_cmd); - - msn_table_add_cmd(cbs_table, NULL, "QRY", NULL); - msn_table_add_cmd(cbs_table, NULL, "QNG", qng_cmd); - msn_table_add_cmd(cbs_table, NULL, "FLN", fln_cmd); - msn_table_add_cmd(cbs_table, NULL, "NLN", nln_cmd); - msn_table_add_cmd(cbs_table, NULL, "ILN", iln_cmd); - msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd); - msn_table_add_cmd(cbs_table, NULL, "RNG", rng_cmd); - - msn_table_add_cmd(cbs_table, NULL, "URL", url_cmd); - - msn_table_add_cmd(cbs_table, "fallback", "XFR", xfr_cmd); - - msn_table_add_error(cbs_table, "ADD", add_error); - msn_table_add_error(cbs_table, "REG", reg_error); - msn_table_add_error(cbs_table, "RMG", rmg_error); - /* msn_table_add_error(cbs_table, "REA", rea_error); */ - msn_table_add_error(cbs_table, "USR", usr_error); - - msn_table_add_msg_type(cbs_table, - "text/x-msmsgsprofile", - profile_msg); - msn_table_add_msg_type(cbs_table, - "text/x-msmsgsinitialemailnotification", - initial_email_msg); - msn_table_add_msg_type(cbs_table, - "text/x-msmsgsemailnotification", - email_msg); - msn_table_add_msg_type(cbs_table, - "application/x-msmsgssystemmessage", - system_msg); -} - -void -msn_notification_end(void) -{ - msn_table_destroy(cbs_table); -}
--- a/libpurple/protocols/msnp9/notification.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/** - * @file notification.h Notification server functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_NOTIFICATION_H_ -#define _MSN_NOTIFICATION_H_ - -typedef struct _MsnNotification MsnNotification; - -#include "session.h" -#include "servconn.h" -#include "cmdproc.h" - -struct _MsnNotification -{ - MsnSession *session; - MsnCmdProc *cmdproc; - MsnServConn *servconn; - - gboolean in_use; -}; - -#include "state.h" - -void msn_notification_end(void); -void msn_notification_init(void); - -void msn_notification_add_buddy(MsnNotification *notification, - const char *list, const char *who, - const char *friendly_name, int group_id); -void msn_notification_rem_buddy(MsnNotification *notification, - const char *list, const char *who, - int group_id); -MsnNotification *msn_notification_new(MsnSession *session); -void msn_notification_destroy(MsnNotification *notification); -gboolean msn_notification_connect(MsnNotification *notification, - const char *host, int port); -void msn_notification_disconnect(MsnNotification *notification); - -/** - * Closes a notification. - * - * It's first closed, and then disconnected. - * - * @param notification The notification object to close. - */ -void msn_notification_close(MsnNotification *notification); - -void msn_got_login_params(MsnSession *session, const char *login_params); - -#endif /* _MSN_NOTIFICATION_H_ */
--- a/libpurple/protocols/msnp9/object.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,417 +0,0 @@ -/** - * @file object.c MSNObject API - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "object.h" -#include "debug.h" -/* Sha1 stuff */ -#include "cipher.h" -/* Base64 stuff */ -#include "util.h" - -#define GET_STRING_TAG(field, id) \ - if ((tag = strstr(str, id "=\"")) != NULL) \ - { \ - tag += strlen(id "=\""); \ - c = strchr(tag, '"'); \ - if (c != NULL) \ - { \ - if (obj->field != NULL) \ - g_free(obj->field); \ - obj->field = g_strndup(tag, c - tag); \ - } \ - } - -#define GET_INT_TAG(field, id) \ - if ((tag = strstr(str, id "=\"")) != NULL) \ - { \ - char buf[16]; \ - size_t offset; \ - tag += strlen(id "=\""); \ - c = strchr(tag, '"'); \ - if (c != NULL) \ - { \ - memset(buf, 0, sizeof(buf)); \ - offset = c - tag; \ - if (offset >= sizeof(buf)) \ - offset = sizeof(buf) - 1; \ - strncpy(buf, tag, offset); \ - obj->field = atoi(buf); \ - } \ - } - -static GList *local_objs; - -MsnObject * -msn_object_new(void) -{ - MsnObject *obj; - - obj = g_new0(MsnObject, 1); - - msn_object_set_type(obj, MSN_OBJECT_UNKNOWN); - msn_object_set_friendly(obj, "AAA="); - - return obj; -} - -MsnObject * -msn_object_new_from_string(const char *str) -{ - MsnObject *obj; - char *tag, *c; - - g_return_val_if_fail(str != NULL, NULL); - - if (strncmp(str, "<msnobj ", 8)) - return NULL; - - obj = msn_object_new(); - - GET_STRING_TAG(creator, "Creator"); - GET_INT_TAG(size, "Size"); - GET_INT_TAG(type, "Type"); - GET_STRING_TAG(location, "Location"); - GET_STRING_TAG(friendly, "Friendly"); - GET_STRING_TAG(sha1d, "SHA1D"); - GET_STRING_TAG(sha1c, "SHA1C"); - - /* If we are missing any of the required elements then discard the object */ - /* SHA1C is not always sent anymore */ - if (obj->creator == NULL || obj->size == 0 || obj->type == 0 - || obj->location == NULL || obj->friendly == NULL - || obj->sha1d == NULL /*|| obj->sha1c == NULL*/) { - purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str); - msn_object_destroy(obj); - obj = NULL; - } - - return obj; -} - -MsnObject* -msn_object_new_from_image(PurpleStoredImage *img, const char *location, - const char *creator, MsnObjectType type) -{ - MsnObject *msnobj; - - PurpleCipherContext *ctx; - char *buf; - gconstpointer data; - size_t size; - char *base64; - unsigned char digest[20]; - - msnobj = NULL; - - if (img == NULL) - return msnobj; - - size = purple_imgstore_get_size(img); - data = purple_imgstore_get_data(img); - - /* New object */ - msnobj = msn_object_new(); - msn_object_set_local(msnobj); - msn_object_set_type(msnobj, type); - msn_object_set_location(msnobj, location); - msn_object_set_creator(msnobj, creator); - - msn_object_set_image(msnobj, img); - - /* Compute the SHA1D field. */ - memset(digest, 0, sizeof(digest)); - - ctx = purple_cipher_context_new_by_name("sha1", NULL); - purple_cipher_context_append(ctx, data, size); - purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL); - - base64 = purple_base64_encode(digest, sizeof(digest)); - msn_object_set_sha1d(msnobj, base64); - g_free(base64); - - msn_object_set_size(msnobj, size); - - /* Compute the SHA1C field. */ - buf = g_strdup_printf( - "Creator%sSize%dType%dLocation%sFriendly%sSHA1D%s", - msn_object_get_creator(msnobj), - msn_object_get_size(msnobj), - msn_object_get_type(msnobj), - msn_object_get_location(msnobj), - msn_object_get_friendly(msnobj), - msn_object_get_sha1d(msnobj)); - - memset(digest, 0, sizeof(digest)); - - purple_cipher_context_reset(ctx, NULL); - purple_cipher_context_append(ctx, (const guchar *)buf, strlen(buf)); - purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL); - purple_cipher_context_destroy(ctx); - g_free(buf); - - base64 = purple_base64_encode(digest, sizeof(digest)); - msn_object_set_sha1c(msnobj, base64); - g_free(base64); - - return msnobj; -} - -void -msn_object_destroy(MsnObject *obj) -{ - g_return_if_fail(obj != NULL); - - g_free(obj->creator); - g_free(obj->location); - g_free(obj->friendly); - g_free(obj->sha1d); - g_free(obj->sha1c); - - purple_imgstore_unref(obj->img); - - if (obj->local) - local_objs = g_list_remove(local_objs, obj); - - g_free(obj); -} - -char * -msn_object_to_string(const MsnObject *obj) -{ - char *str; - const char *sha1c; - - g_return_val_if_fail(obj != NULL, NULL); - - sha1c = msn_object_get_sha1c(obj); - - str = g_strdup_printf("<msnobj Creator=\"%s\" Size=\"%d\" Type=\"%d\" " - "Location=\"%s\" Friendly=\"%s\" SHA1D=\"%s\"" - "%s%s%s/>", - msn_object_get_creator(obj), - msn_object_get_size(obj), - msn_object_get_type(obj), - msn_object_get_location(obj), - msn_object_get_friendly(obj), - msn_object_get_sha1d(obj), - sha1c ? " SHA1C=\"" : "", - sha1c ? sha1c : "", - sha1c ? "\"" : ""); - - return str; -} - -void -msn_object_set_creator(MsnObject *obj, const char *creator) -{ - g_return_if_fail(obj != NULL); - - if (obj->creator != NULL) - g_free(obj->creator); - - obj->creator = (creator == NULL ? NULL : g_strdup(creator)); -} - -void -msn_object_set_size(MsnObject *obj, int size) -{ - g_return_if_fail(obj != NULL); - - obj->size = size; -} - -void -msn_object_set_type(MsnObject *obj, MsnObjectType type) -{ - g_return_if_fail(obj != NULL); - - obj->type = type; -} - -void -msn_object_set_location(MsnObject *obj, const char *location) -{ - g_return_if_fail(obj != NULL); - - if (obj->location != NULL) - g_free(obj->location); - - obj->location = (location == NULL ? NULL : g_strdup(location)); -} - -void -msn_object_set_friendly(MsnObject *obj, const char *friendly) -{ - g_return_if_fail(obj != NULL); - - if (obj->friendly != NULL) - g_free(obj->friendly); - - obj->friendly = (friendly == NULL ? NULL : g_strdup(friendly)); -} - -void -msn_object_set_sha1d(MsnObject *obj, const char *sha1d) -{ - g_return_if_fail(obj != NULL); - - if (obj->sha1d != NULL) - g_free(obj->sha1d); - - obj->sha1d = (sha1d == NULL ? NULL : g_strdup(sha1d)); -} - -void -msn_object_set_sha1c(MsnObject *obj, const char *sha1c) -{ - g_return_if_fail(obj != NULL); - - if (obj->sha1c != NULL) - g_free(obj->sha1c); - - obj->sha1c = (sha1c == NULL ? NULL : g_strdup(sha1c)); -} - -const char * -msn_object_get_creator(const MsnObject *obj) -{ - g_return_val_if_fail(obj != NULL, NULL); - - return obj->creator; -} - -int -msn_object_get_size(const MsnObject *obj) -{ - g_return_val_if_fail(obj != NULL, 0); - - return obj->size; -} - -MsnObjectType -msn_object_get_type(const MsnObject *obj) -{ - g_return_val_if_fail(obj != NULL, MSN_OBJECT_UNKNOWN); - - return obj->type; -} - -const char * -msn_object_get_location(const MsnObject *obj) -{ - g_return_val_if_fail(obj != NULL, NULL); - - return obj->location; -} - -const char * -msn_object_get_friendly(const MsnObject *obj) -{ - g_return_val_if_fail(obj != NULL, NULL); - - return obj->friendly; -} - -const char * -msn_object_get_sha1d(const MsnObject *obj) -{ - g_return_val_if_fail(obj != NULL, NULL); - - return obj->sha1d; -} - -const char * -msn_object_get_sha1c(const MsnObject *obj) -{ - g_return_val_if_fail(obj != NULL, NULL); - - return obj->sha1c; -} - -const char * -msn_object_get_sha1(const MsnObject *obj) -{ - g_return_val_if_fail(obj != NULL, NULL); - - if(obj->sha1c != NULL) { - return obj->sha1c; - } else { - return obj->sha1d; - } -} - -static MsnObject * -msn_object_find_local(const char *sha1) -{ - GList *l; - - g_return_val_if_fail(sha1 != NULL, NULL); - - for (l = local_objs; l != NULL; l = l->next) - { - MsnObject *local_obj = l->data; - - if (!strcmp(msn_object_get_sha1(local_obj), sha1)) - return local_obj; - } - - return NULL; - -} - -void -msn_object_set_local(MsnObject *obj) -{ - g_return_if_fail(obj != NULL); - - obj->local = TRUE; - - local_objs = g_list_append(local_objs, obj); -} - -void -msn_object_set_image(MsnObject *obj, PurpleStoredImage *img) -{ - g_return_if_fail(obj != NULL); - g_return_if_fail(img != NULL); - - /* obj->local = TRUE; */ - - purple_imgstore_unref(obj->img); - obj->img = purple_imgstore_ref(img); -} - -PurpleStoredImage * -msn_object_get_image(const MsnObject *obj) -{ - MsnObject *local_obj; - - g_return_val_if_fail(obj != NULL, NULL); - - local_obj = msn_object_find_local(msn_object_get_sha1(obj)); - - if (local_obj != NULL) - return local_obj->img; - - return NULL; -}
--- a/libpurple/protocols/msnp9/object.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,242 +0,0 @@ -/** - * @file object.h MSNObject API - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_OBJECT_H_ -#define _MSN_OBJECT_H_ - -#include "imgstore.h" - -#include "internal.h" - -typedef enum -{ - MSN_OBJECT_UNKNOWN = -1, /**< Unknown object */ - MSN_OBJECT_RESERVED1 = 1, /**< Reserved */ - MSN_OBJECT_EMOTICON = 2, /**< Custom Emoticon */ - MSN_OBJECT_USERTILE = 3, /**< UserTile (buddy icon) */ - MSN_OBJECT_RESERVED2 = 4, /**< Reserved */ - MSN_OBJECT_BACKGROUND = 5 /**< Background */ - -} MsnObjectType; - -typedef struct -{ - gboolean local; - - char *creator; - int size; - MsnObjectType type; - PurpleStoredImage *img; - char *location; - char *friendly; - char *sha1d; - char *sha1c; - -} MsnObject; - -/** - * Creates a MsnObject structure. - * - * @return A new MsnObject structure. - */ -MsnObject *msn_object_new(void); - -/** - * Creates a MsnObject structure from a string. - * - * @param str The string. - * - * @return The new MsnObject structure. - */ -MsnObject *msn_object_new_from_string(const char *str); - -/** - * Creates a MsnObject structure from a stored image - * - * @param img The image associated to object - * @param location The object location as stored in MsnObject - * @param creator The creator of the object - * @param type The type of the object - * - * @return A new MsnObject structure - */ -MsnObject *msn_object_new_from_image(PurpleStoredImage *img, - const char *location, const char *creator, MsnObjectType type); - -/** - * Destroys an MsnObject structure. - * - * @param obj The object structure. - */ -void msn_object_destroy(MsnObject *obj); - -/** - * Outputs a string representation of an MsnObject. - * - * @param obj The object. - * - * @return The string representation. This must be freed. - */ -char *msn_object_to_string(const MsnObject *obj); - -/** - * Sets the creator field in a MsnObject. - * - * @param creator The creator value. - */ -void msn_object_set_creator(MsnObject *obj, const char *creator); - -/** - * Sets the size field in a MsnObject. - * - * @param size The size value. - */ -void msn_object_set_size(MsnObject *obj, int size); - -/** - * Sets the type field in a MsnObject. - * - * @param type The type value. - */ -void msn_object_set_type(MsnObject *obj, MsnObjectType type); - -/** - * Sets the location field in a MsnObject. - * - * @param location The location value. - */ -void msn_object_set_location(MsnObject *obj, const char *location); - -/** - * Sets the friendly name field in a MsnObject. - * - * @param friendly The friendly name value. - */ -void msn_object_set_friendly(MsnObject *obj, const char *friendly); - -/** - * Sets the SHA1D field in a MsnObject. - * - * @param sha1d The sha1d value. - */ -void msn_object_set_sha1d(MsnObject *obj, const char *sha1d); - -/** - * Sets the SHA1C field in a MsnObject. - * - * @param sha1c The sha1c value. - */ -void msn_object_set_sha1c(MsnObject *obj, const char *sha1c); - -/** - * Associates an image with a MsnObject. - * - * @param obj The object. - * @param img The image to associate. - */ -void msn_object_set_image(MsnObject *obj, PurpleStoredImage *img); - -/** - * Returns a MsnObject's creator value. - * - * @param obj The object. - * - * @return The creator value. - */ -const char *msn_object_get_creator(const MsnObject *obj); - -/** - * Returns a MsnObject's size value. - * - * @param obj The object. - * - * @return The size value. - */ -int msn_object_get_size(const MsnObject *obj); - -/** - * Returns a MsnObject's type. - * - * @param obj The object. - * - * @return The object type. - */ -MsnObjectType msn_object_get_type(const MsnObject *obj); - -/** - * Returns a MsnObject's location value. - * - * @param obj The object. - * - * @return The location value. - */ -const char *msn_object_get_location(const MsnObject *obj); - -/** - * Returns a MsnObject's friendly name value. - * - * @param obj The object. - * - * @return The friendly name value. - */ -const char *msn_object_get_friendly(const MsnObject *obj); - -/** - * Returns a MsnObject's SHA1D value. - * - * @param obj The object. - * - * @return The SHA1D value. - */ -const char *msn_object_get_sha1d(const MsnObject *obj); - -/** - * Returns a MsnObject's SHA1C value. - * - * @param obj The object. - * - * @return The SHA1C value. - */ -const char *msn_object_get_sha1c(const MsnObject *obj); - -/** - * Returns a MsnObject's SHA1C value if it exists, otherwise SHA1D. - * - * @param obj The object. - * - * @return The SHA1C value. - */ -const char *msn_object_get_sha1(const MsnObject *obj); - -/** - * Returns the image associated with the MsnObject. - * - * @param obj The object. - * - * @return The associated image. - */ -PurpleStoredImage *msn_object_get_image(const MsnObject *obj); - -void msn_object_set_local(MsnObject *obj); - -#endif /* _MSN_OBJECT_H_ */
--- a/libpurple/protocols/msnp9/page.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/** - * @file page.c Paging functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "page.h" - -MsnPage * -msn_page_new(void) -{ - MsnPage *page; - - page = g_new0(MsnPage, 1); - - return page; -} - -void -msn_page_destroy(MsnPage *page) -{ - g_return_if_fail(page != NULL); - - if (page->body != NULL) - g_free(page->body); - - if (page->from_location != NULL) - g_free(page->from_location); - - if (page->from_phone != NULL) - g_free(page->from_phone); - - g_free(page); -} - -char * -msn_page_gen_payload(const MsnPage *page, size_t *ret_size) -{ - char *str; - - g_return_val_if_fail(page != NULL, NULL); - - str = - g_strdup_printf("<TEXT xml:space=\"preserve\" enc=\"utf-8\">%s</TEXT>", - msn_page_get_body(page)); - - if (ret_size != NULL) - *ret_size = strlen(str); - - return str; -} - -void -msn_page_set_body(MsnPage *page, const char *body) -{ - g_return_if_fail(page != NULL); - g_return_if_fail(body != NULL); - - if (page->body != NULL) - g_free(page->body); - - page->body = g_strdup(body); -} - -const char * -msn_page_get_body(const MsnPage *page) -{ - g_return_val_if_fail(page != NULL, NULL); - - return page->body; -}
--- a/libpurple/protocols/msnp9/page.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/** - * @file page.h Paging functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_PAGE_H_ -#define _MSN_PAGE_H_ - -typedef struct _MsnPage MsnPage; - -#include "session.h" - -/** - * A page. - */ -struct _MsnPage -{ - char *from_location; - char *from_phone; - - char *body; -}; - -/** - * Creates a new, empty page. - * - * @return A new page. - */ -MsnPage *msn_page_new(void); - -/** - * Destroys a page. - */ -void msn_page_destroy(MsnPage *page); - -/** - * Generates the payload data of a page. - * - * @param page The page. - * @param ret_size The returned size of the payload. - * - * @return The payload data of a page. - */ -char *msn_page_gen_payload(const MsnPage *page, size_t *ret_size); - -/** - * Sets the body of a page. - * - * @param page The page. - * @param body The body of the page. - */ -void msn_page_set_body(MsnPage *page, const char *body); - -/** - * Returns the body of the page. - * - * @param page The page. - * - * @return The body of the page. - */ -const char *msn_page_get_body(const MsnPage *page); - -#endif /* _MSN_PAGE_H_ */
--- a/libpurple/protocols/msnp9/servconn.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,556 +0,0 @@ -/** - * @file servconn.c Server connection functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "servconn.h" -#include "error.h" - -static void read_cb(gpointer data, gint source, PurpleInputCondition cond); - -/************************************************************************** - * Main - **************************************************************************/ - -MsnServConn * -msn_servconn_new(MsnSession *session, MsnServConnType type) -{ - MsnServConn *servconn; - - g_return_val_if_fail(session != NULL, NULL); - - servconn = g_new0(MsnServConn, 1); - - servconn->type = type; - - servconn->session = session; - servconn->cmdproc = msn_cmdproc_new(session); - servconn->cmdproc->servconn = servconn; - - servconn->httpconn = msn_httpconn_new(servconn); - - servconn->num = session->servconns_count++; - - servconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN); - servconn->tx_handler = 0; - - return servconn; -} - -void -msn_servconn_destroy(MsnServConn *servconn) -{ - g_return_if_fail(servconn != NULL); - - if (servconn->processing) - { - servconn->wasted = TRUE; - return; - } - - if (servconn->connected) - msn_servconn_disconnect(servconn); - - if (servconn->destroy_cb) - servconn->destroy_cb(servconn); - - if (servconn->httpconn != NULL) - msn_httpconn_destroy(servconn->httpconn); - - g_free(servconn->host); - - purple_circ_buffer_destroy(servconn->tx_buf); - if (servconn->tx_handler > 0) - purple_input_remove(servconn->tx_handler); - - msn_cmdproc_destroy(servconn->cmdproc); - g_free(servconn); -} - -void -msn_servconn_set_connect_cb(MsnServConn *servconn, - void (*connect_cb)(MsnServConn *)) -{ - g_return_if_fail(servconn != NULL); - servconn->connect_cb = connect_cb; -} - -void -msn_servconn_set_disconnect_cb(MsnServConn *servconn, - void (*disconnect_cb)(MsnServConn *)) -{ - g_return_if_fail(servconn != NULL); - - servconn->disconnect_cb = disconnect_cb; -} - -void -msn_servconn_set_destroy_cb(MsnServConn *servconn, - void (*destroy_cb)(MsnServConn *)) -{ - g_return_if_fail(servconn != NULL); - - servconn->destroy_cb = destroy_cb; -} - -/************************************************************************** - * Utility - **************************************************************************/ - -void -msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error) -{ - char *tmp; - const char *reason; - - const char *names[] = { "Notification", "Switchboard" }; - const char *name; - - name = names[servconn->type]; - - switch (error) - { - case MSN_SERVCONN_ERROR_CONNECT: - reason = _("Unable to connect"); break; - case MSN_SERVCONN_ERROR_WRITE: - reason = _("Writing error"); break; - case MSN_SERVCONN_ERROR_READ: - reason = _("Reading error"); break; - default: - reason = _("Unknown error"); break; - } - - purple_debug_error("msn", "Connection error from %s server (%s): %s\n", - name, servconn->host, reason); - tmp = g_strdup_printf(_("Connection error from %s server:\n%s"), - name, reason); - - if (servconn->type == MSN_SERVCONN_NS) - { - msn_session_set_error(servconn->session, MSN_ERROR_SERVCONN, tmp); - } - else if (servconn->type == MSN_SERVCONN_SB) - { - MsnSwitchBoard *swboard; - swboard = servconn->cmdproc->data; - if (swboard != NULL) - swboard->error = MSN_SB_ERROR_CONNECTION; - } - - msn_servconn_disconnect(servconn); - - g_free(tmp); -} - -/************************************************************************** - * Connect - **************************************************************************/ - -static void -connect_cb(gpointer data, gint source, const gchar *error_message) -{ - MsnServConn *servconn; - - servconn = data; - servconn->connect_data = NULL; - servconn->processing = FALSE; - - if (servconn->wasted) - { - if (source >= 0) - close(source); - msn_servconn_destroy(servconn); - return; - } - - servconn->fd = source; - - if (source >= 0) - { - servconn->connected = TRUE; - - /* Someone wants to know we connected. */ - servconn->connect_cb(servconn); - servconn->inpa = purple_input_add(servconn->fd, PURPLE_INPUT_READ, - read_cb, data); - } - else - { - purple_debug_error("msn", "Connection error: %s\n", error_message); - msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_CONNECT); - } -} - -gboolean -msn_servconn_connect(MsnServConn *servconn, const char *host, int port) -{ - MsnSession *session; - - g_return_val_if_fail(servconn != NULL, FALSE); - g_return_val_if_fail(host != NULL, FALSE); - g_return_val_if_fail(port > 0, FALSE); - - session = servconn->session; - - if (servconn->connected) - msn_servconn_disconnect(servconn); - - g_free(servconn->host); - servconn->host = g_strdup(host); - - if (session->http_method) - { - /* HTTP Connection. */ - - if (!servconn->httpconn->connected) - if (!msn_httpconn_connect(servconn->httpconn, host, port)) - return FALSE; - - servconn->connected = TRUE; - servconn->httpconn->virgin = TRUE; - - /* Someone wants to know we connected. */ - servconn->connect_cb(servconn); - - return TRUE; - } - - servconn->connect_data = purple_proxy_connect(NULL, session->account, - host, port, connect_cb, servconn); - - if (servconn->connect_data != NULL) - { - servconn->processing = TRUE; - return TRUE; - } - else - return FALSE; -} - -void -msn_servconn_disconnect(MsnServConn *servconn) -{ - g_return_if_fail(servconn != NULL); - - if (servconn->connect_data != NULL) - { - purple_proxy_connect_cancel(servconn->connect_data); - servconn->connect_data = NULL; - } - - if (!servconn->connected) - { - /* We could not connect. */ - if (servconn->disconnect_cb != NULL) - servconn->disconnect_cb(servconn); - - return; - } - - if (servconn->session->http_method) - { - /* Fake disconnection. */ - if (servconn->disconnect_cb != NULL) - servconn->disconnect_cb(servconn); - - return; - } - - if (servconn->inpa > 0) - { - purple_input_remove(servconn->inpa); - servconn->inpa = 0; - } - - close(servconn->fd); - - servconn->rx_buf = NULL; - servconn->rx_len = 0; - servconn->payload_len = 0; - - servconn->connected = FALSE; - - if (servconn->disconnect_cb != NULL) - servconn->disconnect_cb(servconn); -} - -static void -servconn_write_cb(gpointer data, gint source, PurpleInputCondition cond) -{ - MsnServConn *servconn = data; - int ret, writelen; - - writelen = purple_circ_buffer_get_max_read(servconn->tx_buf); - - if (writelen == 0) { - purple_input_remove(servconn->tx_handler); - servconn->tx_handler = 0; - return; - } - - ret = write(servconn->fd, servconn->tx_buf->outptr, writelen); - - if (ret < 0 && errno == EAGAIN) - return; - else if (ret <= 0) { - msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE); - return; - } - - purple_circ_buffer_mark_read(servconn->tx_buf, ret); -} - -ssize_t -msn_servconn_write(MsnServConn *servconn, const char *buf, size_t len) -{ - ssize_t ret = 0; - - g_return_val_if_fail(servconn != NULL, 0); - - if (!servconn->session->http_method) - { - if (servconn->tx_handler == 0) { - switch (servconn->type) - { - case MSN_SERVCONN_NS: - case MSN_SERVCONN_SB: - ret = write(servconn->fd, buf, len); - break; -#if 0 - case MSN_SERVCONN_DC: - ret = write(servconn->fd, &buf, sizeof(len)); - ret = write(servconn->fd, buf, len); - break; -#endif - default: - ret = write(servconn->fd, buf, len); - break; - } - } else { - ret = -1; - errno = EAGAIN; - } - - if (ret < 0 && errno == EAGAIN) - ret = 0; - if (ret >= 0 && ret < len) { - if (servconn->tx_handler == 0) - servconn->tx_handler = purple_input_add( - servconn->fd, PURPLE_INPUT_WRITE, - servconn_write_cb, servconn); - purple_circ_buffer_append(servconn->tx_buf, buf + ret, - len - ret); - } - } - else - { - ret = msn_httpconn_write(servconn->httpconn, buf, len); - } - - if (ret == -1) - { - msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE); - } - - return ret; -} - -static void -read_cb(gpointer data, gint source, PurpleInputCondition cond) -{ - MsnServConn *servconn; - MsnSession *session; - char buf[MSN_BUF_LEN]; - char *cur, *end, *old_rx_buf; - int len, cur_len; - - servconn = data; - session = servconn->session; - - len = read(servconn->fd, buf, sizeof(buf) - 1); - servconn->session->account->gc->last_received = time(NULL); - - if (len < 0 && errno == EAGAIN) - return; - else if (len <= 0) - { - purple_debug_error("msn", "servconn read error, len: %d error: %s\n", len, g_strerror(errno)); - msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ); - - return; - } - - buf[len] = '\0'; - - servconn->rx_buf = g_realloc(servconn->rx_buf, len + servconn->rx_len + 1); - memcpy(servconn->rx_buf + servconn->rx_len, buf, len + 1); - servconn->rx_len += len; - - end = old_rx_buf = servconn->rx_buf; - - servconn->processing = TRUE; - - do - { - cur = end; - - if (servconn->payload_len) - { - if (servconn->payload_len > servconn->rx_len) - /* The payload is still not complete. */ - break; - - cur_len = servconn->payload_len; - end += cur_len; - } - else - { - end = strstr(cur, "\r\n"); - - if (end == NULL) - /* The command is still not complete. */ - break; - - *end = '\0'; - end += 2; - cur_len = end - cur; - } - - servconn->rx_len -= cur_len; - - if (servconn->payload_len) - { - msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len); - servconn->payload_len = 0; - } - else - { - msn_cmdproc_process_cmd_text(servconn->cmdproc, cur); - } - } while (servconn->connected && !servconn->wasted && servconn->rx_len > 0); - - if (servconn->connected && !servconn->wasted) - { - if (servconn->rx_len > 0) - servconn->rx_buf = g_memdup(cur, servconn->rx_len); - else - servconn->rx_buf = NULL; - } - - servconn->processing = FALSE; - - if (servconn->wasted) - msn_servconn_destroy(servconn); - - g_free(old_rx_buf); -} - -#if 0 -static int -create_listener(int port) -{ - int fd; - int flags; - const int on = 1; - -#if 0 - struct addrinfo hints; - struct addrinfo *c, *res; - char port_str[5]; - - snprintf(port_str, sizeof(port_str), "%d", port); - - memset(&hints, 0, sizeof(hints)); - - hints.ai_flags = AI_PASSIVE; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - if (getaddrinfo(NULL, port_str, &hints, &res) != 0) - { - purple_debug_error("msn", "Could not get address info: %s.\n", - port_str); - return -1; - } - - for (c = res; c != NULL; c = c->ai_next) - { - fd = socket(c->ai_family, c->ai_socktype, c->ai_protocol); - - if (fd < 0) - continue; - - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - - if (bind(fd, c->ai_addr, c->ai_addrlen) == 0) - break; - - close(fd); - } - - if (c == NULL) - { - purple_debug_error("msn", "Could not find socket: %s.\n", port_str); - return -1; - } - - freeaddrinfo(res); -#else - struct sockaddr_in sockin; - - fd = socket(AF_INET, SOCK_STREAM, 0); - - if (fd < 0) - return -1; - - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) - { - close(fd); - return -1; - } - - memset(&sockin, 0, sizeof(struct sockaddr_in)); - sockin.sin_family = AF_INET; - sockin.sin_port = htons(port); - - if (bind(fd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) - { - close(fd); - return -1; - } -#endif - - if (listen (fd, 4) != 0) - { - close (fd); - return -1; - } - - flags = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); -#ifndef _WIN32 - fcntl(fd, F_SETFD, FD_CLOEXEC); -#endif - - return fd; -} -#endif
--- a/libpurple/protocols/msnp9/servconn.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/** - * @file servconn.h Server connection functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_SERVCONN_H_ -#define _MSN_SERVCONN_H_ - -typedef struct _MsnServConn MsnServConn; - -#include "session.h" -#include "cmdproc.h" - -#include "proxy.h" -#include "httpconn.h" - -/** - * Connection error types. - */ -typedef enum -{ - MSN_SERVCONN_ERROR_NONE, - MSN_SERVCONN_ERROR_CONNECT, - MSN_SERVCONN_ERROR_WRITE, - MSN_SERVCONN_ERROR_READ, - -} MsnServConnError; - -/** - * Connection types. - */ -typedef enum -{ - MSN_SERVCONN_NS, - MSN_SERVCONN_SB - -} MsnServConnType; - -/** - * A Connection. - */ -struct _MsnServConn -{ - MsnServConnType type; /**< The type of this connection. */ - MsnSession *session; /**< The MSN session of this connection. */ - MsnCmdProc *cmdproc; /**< The command processor of this connection. */ - - PurpleProxyConnectData *connect_data; - - gboolean connected; /**< A flag that states if it's connected. */ - gboolean processing; /**< A flag that states if something is working - with this connection. */ - gboolean wasted; /**< A flag that states if it should be destroyed. */ - - char *host; /**< The host this connection is connected or should be - connected to. */ - int num; /**< A number id of this connection. */ - - MsnHttpConn *httpconn; /**< The HTTP connection this connection should use. */ - - int fd; /**< The connection's file descriptor. */ - int inpa; /**< The connection's input handler. */ - - char *rx_buf; /**< The receive buffer. */ - int rx_len; /**< The receive buffer lenght. */ - - size_t payload_len; /**< The length of the payload. - It's only set when we've received a command that - has a payload. */ - - PurpleCircBuffer *tx_buf; - guint tx_handler; - - void (*connect_cb)(MsnServConn *); /**< The callback to call when connecting. */ - void (*disconnect_cb)(MsnServConn *); /**< The callback to call when disconnecting. */ - void (*destroy_cb)(MsnServConn *); /**< The callback to call when destroying. */ -}; - -/** - * Creates a new connection object. - * - * @param session The session. - * @param type The type of the connection. - */ -MsnServConn *msn_servconn_new(MsnSession *session, MsnServConnType type); - -/** - * Destroys a connection object. - * - * @param servconn The connection. - */ -void msn_servconn_destroy(MsnServConn *servconn); - -/** - * Connects to a host. - * - * @param servconn The connection. - * @param host The host. - * @param port The port. - */ -gboolean msn_servconn_connect(MsnServConn *servconn, const char *host, int port); - -/** - * Disconnects. - * - * @param servconn The connection. - */ -void msn_servconn_disconnect(MsnServConn *servconn); - -/** - * Sets the connect callback. - * - * @param servconn The servconn. - * @param connect_cb The connect callback. - */ -void msn_servconn_set_connect_cb(MsnServConn *servconn, - void (*connect_cb)(MsnServConn *)); -/** - * Sets the disconnect callback. - * - * @param servconn The servconn. - * @param disconnect_cb The disconnect callback. - */ -void msn_servconn_set_disconnect_cb(MsnServConn *servconn, - void (*disconnect_cb)(MsnServConn *)); -/** - * Sets the destroy callback. - * - * @param servconn The servconn that's being destroyed. - * @param destroy_cb The destroy callback. - */ -void msn_servconn_set_destroy_cb(MsnServConn *servconn, - void (*destroy_cb)(MsnServConn *)); - -/** - * Writes a chunck of data to the servconn. - * - * @param servconn The servconn. - * @param buf The data to write. - * @param size The size of the data. - */ -ssize_t msn_servconn_write(MsnServConn *servconn, const char *buf, - size_t size); - -/** - * Function to call whenever an error related to a switchboard occurs. - * - * @param servconn The servconn. - * @param error The error that happened. - */ -void msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error); - -#endif /* _MSN_SERVCONN_H_ */
--- a/libpurple/protocols/msnp9/session.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,432 +0,0 @@ -/** - * @file session.c MSN session functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "session.h" -#include "notification.h" - -#include "dialog.h" - -MsnSession * -msn_session_new(PurpleAccount *account) -{ - MsnSession *session; - - g_return_val_if_fail(account != NULL, NULL); - - session = g_new0(MsnSession, 1); - - session->account = account; - session->notification = msn_notification_new(session); - session->userlist = msn_userlist_new(session); - - session->user = msn_user_new(session->userlist, - purple_account_get_username(account), NULL); - - session->protocol_ver = 9; - - return session; -} - -void -msn_session_destroy(MsnSession *session) -{ - g_return_if_fail(session != NULL); - - session->destroying = TRUE; - - if (session->connected) - msn_session_disconnect(session); - - if (session->notification != NULL) - msn_notification_destroy(session->notification); - - while (session->switches != NULL) - msn_switchboard_destroy(session->switches->data); - - while (session->slplinks != NULL) - msn_slplink_destroy(session->slplinks->data); - - msn_userlist_destroy(session->userlist); - - g_free(session->passport_info.kv); - g_free(session->passport_info.sid); - g_free(session->passport_info.mspauth); - g_free(session->passport_info.client_ip); - - if (session->passport_info.file != NULL) - { - g_unlink(session->passport_info.file); - g_free(session->passport_info.file); - } - - if (session->sync != NULL) - msn_sync_destroy(session->sync); - - if (session->nexus != NULL) - msn_nexus_destroy(session->nexus); - - if (session->user != NULL) - msn_user_destroy(session->user); - - g_free(session); -} - -gboolean -msn_session_connect(MsnSession *session, const char *host, int port, - gboolean http_method) -{ - g_return_val_if_fail(session != NULL, FALSE); - g_return_val_if_fail(!session->connected, TRUE); - - session->connected = TRUE; - session->http_method = http_method; - - if (session->notification == NULL) - { - purple_debug_error("msn", "This shouldn't happen\n"); - g_return_val_if_reached(FALSE); - } - - if (msn_notification_connect(session->notification, host, port)) - { - return TRUE; - } - - return FALSE; -} - -void -msn_session_disconnect(MsnSession *session) -{ - g_return_if_fail(session != NULL); - g_return_if_fail(session->connected); - - session->connected = FALSE; - - while (session->switches != NULL) - msn_switchboard_close(session->switches->data); - - if (session->notification != NULL) - msn_notification_close(session->notification); -} - -/* TODO: This must go away when conversation is redesigned */ -MsnSwitchBoard * -msn_session_find_swboard(MsnSession *session, const char *username) -{ - GList *l; - - g_return_val_if_fail(session != NULL, NULL); - g_return_val_if_fail(username != NULL, NULL); - - for (l = session->switches; l != NULL; l = l->next) - { - MsnSwitchBoard *swboard; - - swboard = l->data; - - if ((swboard->im_user != NULL) && !strcmp(username, swboard->im_user)) - return swboard; - } - - return NULL; -} - -MsnSwitchBoard * -msn_session_find_swboard_with_conv(MsnSession *session, PurpleConversation *conv) -{ - GList *l; - - g_return_val_if_fail(session != NULL, NULL); - g_return_val_if_fail(conv != NULL, NULL); - - for (l = session->switches; l != NULL; l = l->next) - { - MsnSwitchBoard *swboard; - - swboard = l->data; - - if (swboard->conv == conv) - return swboard; - } - - return NULL; -} - -MsnSwitchBoard * -msn_session_find_swboard_with_id(const MsnSession *session, int chat_id) -{ - GList *l; - - g_return_val_if_fail(session != NULL, NULL); - g_return_val_if_fail(chat_id >= 0, NULL); - - for (l = session->switches; l != NULL; l = l->next) - { - MsnSwitchBoard *swboard; - - swboard = l->data; - - if (swboard->chat_id == chat_id) - return swboard; - } - - return NULL; -} - -MsnSwitchBoard * -msn_session_get_swboard(MsnSession *session, const char *username, - MsnSBFlag flag) -{ - MsnSwitchBoard *swboard; - - g_return_val_if_fail(session != NULL, NULL); - - swboard = msn_session_find_swboard(session, username); - - if (swboard == NULL) - { - swboard = msn_switchboard_new(session); - swboard->im_user = g_strdup(username); - msn_switchboard_request(swboard); - msn_switchboard_request_add_user(swboard, username); - } - - swboard->flag |= flag; - - return swboard; -} - -static void -msn_session_sync_users(MsnSession *session) -{ - PurpleConnection *gc = purple_account_get_connection(session->account); - GList *to_remove = NULL; - GSList *buddies; - - g_return_if_fail(gc != NULL); - - /* The core used to use msn_add_buddy to add all buddies before - * being logged in. This no longer happens, so we manually iterate - * over the whole buddy list to identify sync issues. */ - for (buddies = purple_find_buddies(session->account, NULL); buddies; - buddies = g_slist_delete_link(buddies, buddies)) { - PurpleBuddy *buddy = buddies->data; - const char *buddy_name = purple_buddy_get_name(buddy); - const char *group_name = purple_group_get_name(purple_buddy_get_group(buddy)); - MsnUser *remote_user; - gboolean found = FALSE; - - remote_user = msn_userlist_find_user(session->userlist, buddy_name); - - if (remote_user && remote_user->list_op & MSN_LIST_FL_OP) { - int group_id; - GList *l; - - group_id = msn_userlist_find_group_id(remote_user->userlist, - group_name); - - for (l = remote_user->group_ids; l; l = l->next) { - if (group_id == GPOINTER_TO_INT(l->data)) { - found = TRUE; - break; - } - } - - /* We don't care if they're in a different group, as long as they're on the - * list somewhere. If we check for the group, we cause pain, agony and - * suffering for people who decide to re-arrange their buddy list elsewhere. - */ - if (!found) - { - if ((remote_user == NULL) || !(remote_user->list_op & MSN_LIST_FL_OP)) { - /* The user is not on the server list */ - msn_show_sync_issue(session, buddy_name, group_name); - } else { - /* The user is not in that group on the server list */ - to_remove = g_list_prepend(to_remove, buddy); - } - } - } - } - - if (to_remove != NULL) { - g_list_foreach(to_remove, (GFunc)purple_blist_remove_buddy, NULL); - g_list_free(to_remove); - } -} - -void -msn_session_set_error(MsnSession *session, MsnErrorType error, - const char *info) -{ - PurpleConnection *gc; - PurpleConnectionError reason; - char *msg; - - gc = purple_account_get_connection(session->account); - - switch (error) - { - case MSN_ERROR_SERVCONN: - reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; - msg = g_strdup(info); - break; - case MSN_ERROR_UNSUPPORTED_PROTOCOL: - reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; - msg = g_strdup(_("Our protocol is not supported by the " - "server")); - break; - case MSN_ERROR_HTTP_MALFORMED: - reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; - msg = g_strdup(_("Error parsing HTTP")); - break; - case MSN_ERROR_SIGN_OTHER: - reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE; - msg = g_strdup(_("You have signed on from another location")); - if (!purple_account_get_remember_password(session->account)) - purple_account_set_password(session->account, NULL); - break; - case MSN_ERROR_SERV_UNAVAILABLE: - reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; - msg = g_strdup(_("The MSN servers are temporarily " - "unavailable. Please wait and try " - "again.")); - break; - case MSN_ERROR_SERV_DOWN: - reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; - msg = g_strdup(_("The MSN servers are going down " - "temporarily")); - break; - case MSN_ERROR_AUTH: - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - msg = g_strdup_printf(_("Unable to authenticate: %s"), - (info == NULL ) ? - _("Unknown error") : info); - break; - case MSN_ERROR_BAD_BLIST: - reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; - msg = g_strdup(_("Your MSN buddy list is temporarily " - "unavailable. Please wait and try " - "again.")); - break; - default: - reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; - msg = g_strdup(_("Unknown error")); - break; - } - - msn_session_disconnect(session); - - purple_connection_error_reason(gc, reason, msg); - - g_free(msg); -} - -static const char * -get_login_step_text(MsnSession *session) -{ - const char *steps_text[] = { - _("Connecting"), - _("Handshaking"), - _("Transferring"), - _("Handshaking"), - _("Starting authentication"), - _("Getting cookie"), - _("Authenticating"), - _("Sending cookie"), - _("Retrieving buddy list") - }; - - return steps_text[session->login_step]; -} - -void -msn_session_set_login_step(MsnSession *session, MsnLoginStep step) -{ - PurpleConnection *gc; - - /* Prevent the connection progress going backwards, eg. if we get - * transferred several times during login */ - if (session->login_step > step) - return; - - /* If we're already logged in, we're probably here because of a - * mid-session XFR from the notification server, so we don't want to - * popup the connection progress dialog */ - if (session->logged_in) - return; - - gc = session->account->gc; - - session->login_step = step; - - purple_connection_update_progress(gc, get_login_step_text(session), step, - MSN_LOGIN_STEPS); -} - -void -msn_session_finish_login(MsnSession *session) -{ - PurpleAccount *account; - PurpleConnection *gc; - PurpleStoredImage *img; - const char *passport; - - if (session->logged_in) { - /* We are probably here because of a mid-session notification server XFR - * We must send a CHG now, otherwise the servers default to invisible, - * and prevent things happening, like sending IMs */ - msn_change_status(session); - return; - } - - account = session->account; - gc = purple_account_get_connection(account); - - img = purple_buddy_icons_find_account_icon(session->account); - msn_user_set_buddy_icon(session->user, img); - purple_imgstore_unref(img); - - session->logged_in = TRUE; - - msn_change_status(session); - - purple_connection_set_state(gc, PURPLE_CONNECTED); - - /* Sync users */ - msn_session_sync_users(session); - /* It seems that some accounts that haven't accessed hotmail for a while - * and @msn.com accounts don't automatically get the initial email - * notification so we always request it on login - */ - - passport = purple_normalize(account, purple_account_get_username(account)); - - if ((strstr(passport, "@hotmail.") != NULL) || - (strstr(passport, "@msn.com") != NULL)) - { - msn_cmdproc_send(session->notification->cmdproc, "URL", "%s", "INBOX"); - } -}
--- a/libpurple/protocols/msnp9/session.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +0,0 @@ -/** - * @file session.h MSN session functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_SESSION_H_ -#define _MSN_SESSION_H_ - -typedef struct _MsnSession MsnSession; - -#include "sslconn.h" - -#include "user.h" -#include "slpcall.h" - -#include "notification.h" -#include "switchboard.h" -#include "group.h" - -#include "cmdproc.h" -#include "nexus.h" -#include "httpconn.h" - -#include "userlist.h" -#include "sync.h" - -/** - * Types of errors. - */ -typedef enum -{ - MSN_ERROR_SERVCONN, - MSN_ERROR_UNSUPPORTED_PROTOCOL, - MSN_ERROR_HTTP_MALFORMED, - MSN_ERROR_AUTH, - MSN_ERROR_BAD_BLIST, - MSN_ERROR_SIGN_OTHER, - MSN_ERROR_SERV_DOWN, - MSN_ERROR_SERV_UNAVAILABLE - -} MsnErrorType; - -/** - * Login steps. - */ -typedef enum -{ - MSN_LOGIN_STEP_START, - MSN_LOGIN_STEP_HANDSHAKE, - MSN_LOGIN_STEP_TRANSFER, - MSN_LOGIN_STEP_HANDSHAKE2, - MSN_LOGIN_STEP_AUTH_START, - MSN_LOGIN_STEP_AUTH, - MSN_LOGIN_STEP_GET_COOKIE, - MSN_LOGIN_STEP_AUTH_END, - MSN_LOGIN_STEP_SYN, - MSN_LOGIN_STEP_END - -} MsnLoginStep; - -#define MSN_LOGIN_STEPS MSN_LOGIN_STEP_END - -struct _MsnSession -{ - PurpleAccount *account; - MsnUser *user; - - guint protocol_ver; - - MsnLoginStep login_step; /**< The current step in the login process. */ - - gboolean connected; - gboolean logged_in; /**< A temporal flag to ignore local buddy list adds. */ - gboolean destroying; /**< A flag that states if the session is being destroyed. */ - gboolean http_method; - - MsnNotification *notification; - MsnNexus *nexus; - MsnSync *sync; - - MsnUserList *userlist; - - int servconns_count; /**< The count of server connections. */ - GList *switches; /**< The list of all the switchboards. */ - GList *directconns; /**< The list of all the directconnections. */ - GList *slplinks; /**< The list of all the slplinks. */ - - struct - { - char *kv; - char *sid; - char *mspauth; - unsigned long sl; - char *file; - char *client_ip; - int client_port; - int verified; - } passport_info; -}; - -/** - * Creates an MSN session. - * - * @param account The account. - * - * @return The new MSN session. - */ -MsnSession *msn_session_new(PurpleAccount *account); - -/** - * Destroys an MSN session. - * - * @param session The MSN session to destroy. - */ -void msn_session_destroy(MsnSession *session); - -/** - * Connects to and initiates an MSN session. - * - * @param session The MSN session. - * @param host The dispatch server host. - * @param port The dispatch server port. - * @param http_method Whether to use or not http_method. - * - * @return @c TRUE on success, @c FALSE on failure. - */ -gboolean msn_session_connect(MsnSession *session, - const char *host, int port, - gboolean http_method); - -/** - * Disconnects from an MSN session. - * - * @param session The MSN session. - */ -void msn_session_disconnect(MsnSession *session); - - /** - * Finds a switchboard with the given username. - * - * @param session The MSN session. - * @param username The username to search for. - * - * @return The switchboard, if found. - */ -MsnSwitchBoard *msn_session_find_swboard(MsnSession *session, - const char *username); - - /** - * Finds a switchboard with the given conversation. - * - * @param session The MSN session. - * @param conv The conversation to search for. - * - * @return The switchboard, if found. - */ -MsnSwitchBoard *msn_session_find_swboard_with_conv(MsnSession *session, - PurpleConversation *conv); -/** - * Finds a switchboard with the given chat ID. - * - * @param session The MSN session. - * @param chat_id The chat ID to search for. - * - * @return The switchboard, if found. - */ -MsnSwitchBoard *msn_session_find_swboard_with_id(const MsnSession *session, - int chat_id); - -/** - * Returns a switchboard to communicate with certain username. - * - * @param session The MSN session. - * @param username The username to search for. - * @param flag The flag of the switchboard - * - * @return The switchboard. - */ -MsnSwitchBoard *msn_session_get_swboard(MsnSession *session, - const char *username, MsnSBFlag flag); - -/** - * Sets an error for the MSN session. - * - * @param session The MSN session. - * @param error The error. - * @param info Extra information. - */ -void msn_session_set_error(MsnSession *session, MsnErrorType error, - const char *info); - -/** - * Sets the current step in the login proccess. - * - * @param session The MSN session. - * @param step The current step. - */ -void msn_session_set_login_step(MsnSession *session, MsnLoginStep step); - -/** - * Finish the login proccess. - * - * @param session The MSN session. - */ -void msn_session_finish_login(MsnSession *session); - -#endif /* _MSN_SESSION_H_ */
--- a/libpurple/protocols/msnp9/slp.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1122 +0,0 @@ -/** - * @file msnslp.c MSNSLP support - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "slp.h" -#include "slpcall.h" -#include "slpmsg.h" -#include "slpsession.h" - -#include "object.h" -#include "user.h" -#include "switchboard.h" - -#include "smiley.h" - -/* Seconds to delay between sending buddy icon requests to the server. */ -#define BUDDY_ICON_DELAY 20 - -static void send_ok(MsnSlpCall *slpcall, const char *branch, - const char *type, const char *content); - -static void send_decline(MsnSlpCall *slpcall, const char *branch, - const char *type, const char *content); - -void msn_request_user_display(MsnUser *user); - -/************************************************************************** - * Util - **************************************************************************/ - -static char * -get_token(const char *str, const char *start, const char *end) -{ - const char *c, *c2; - - if ((c = strstr(str, start)) == NULL) - return NULL; - - c += strlen(start); - - if (end != NULL) - { - if ((c2 = strstr(c, end)) == NULL) - return NULL; - - return g_strndup(c, c2 - c); - } - else - { - /* This has to be changed */ - return g_strdup(c); - } - -} - -/************************************************************************** - * Xfer - **************************************************************************/ - -static void -msn_xfer_init(PurpleXfer *xfer) -{ - MsnSlpCall *slpcall; - /* MsnSlpLink *slplink; */ - char *content; - - purple_debug_info("msn", "xfer_init\n"); - - slpcall = xfer->data; - - /* Send Ok */ - content = g_strdup_printf("SessionID: %lu\r\n\r\n", - slpcall->session_id); - - send_ok(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody", - content); - - g_free(content); - msn_slplink_unleash(slpcall->slplink); -} - -void -msn_xfer_cancel(PurpleXfer *xfer) -{ - MsnSlpCall *slpcall; - char *content; - - g_return_if_fail(xfer != NULL); - g_return_if_fail(xfer->data != NULL); - - slpcall = xfer->data; - - if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) - { - if (slpcall->started) - { - msn_slp_call_close(slpcall); - } - else - { - content = g_strdup_printf("SessionID: %lu\r\n\r\n", - slpcall->session_id); - - send_decline(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody", - content); - - g_free(content); - msn_slplink_unleash(slpcall->slplink); - - msn_slp_call_destroy(slpcall); - } - } -} - -void -msn_xfer_progress_cb(MsnSlpCall *slpcall, gsize total_length, gsize len, gsize offset) -{ - PurpleXfer *xfer; - - xfer = slpcall->xfer; - - xfer->bytes_sent = (offset + len); - xfer->bytes_remaining = total_length - (offset + len); - - purple_xfer_update_progress(xfer); -} - -void -msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session) -{ - if ((purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_DONE) && - (purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_CANCEL_REMOTE) && - (purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_CANCEL_LOCAL)) - { - purple_xfer_cancel_remote(slpcall->xfer); - } -} - -void -msn_xfer_completed_cb(MsnSlpCall *slpcall, const guchar *body, - gsize size) -{ - PurpleXfer *xfer = slpcall->xfer; - purple_xfer_set_completed(xfer, TRUE); - purple_xfer_end(xfer); -} - -/************************************************************************** - * SLP Control - **************************************************************************/ - -#if 0 -static void -got_transresp(MsnSlpCall *slpcall, const char *nonce, - const char *ips_str, int port) -{ - MsnDirectConn *directconn; - char **ip_addrs, **c; - - directconn = msn_directconn_new(slpcall->slplink); - - directconn->initial_call = slpcall; - - /* msn_directconn_parse_nonce(directconn, nonce); */ - directconn->nonce = g_strdup(nonce); - - ip_addrs = g_strsplit(ips_str, " ", -1); - - for (c = ip_addrs; *c != NULL; c++) - { - purple_debug_info("msn", "ip_addr = %s\n", *c); - if (msn_directconn_connect(directconn, *c, port)) - break; - } - - g_strfreev(ip_addrs); -} -#endif - -static void -send_ok(MsnSlpCall *slpcall, const char *branch, - const char *type, const char *content) -{ - MsnSlpLink *slplink; - MsnSlpMessage *slpmsg; - - slplink = slpcall->slplink; - - /* 200 OK */ - slpmsg = msn_slpmsg_sip_new(slpcall, 1, - "MSNSLP/1.0 200 OK", - branch, type, content); - -#ifdef MSN_DEBUG_SLP - slpmsg->info = "SLP 200 OK"; - slpmsg->text_body = TRUE; -#endif - - msn_slplink_queue_slpmsg(slplink, slpmsg); - - msn_slp_call_session_init(slpcall); -} - -static void -send_decline(MsnSlpCall *slpcall, const char *branch, - const char *type, const char *content) -{ - MsnSlpLink *slplink; - MsnSlpMessage *slpmsg; - - slplink = slpcall->slplink; - - /* 603 Decline */ - slpmsg = msn_slpmsg_sip_new(slpcall, 1, - "MSNSLP/1.0 603 Decline", - branch, type, content); - -#ifdef MSN_DEBUG_SLP - slpmsg->info = "SLP 603 Decline"; - slpmsg->text_body = TRUE; -#endif - - msn_slplink_queue_slpmsg(slplink, slpmsg); -} - -#define MAX_FILE_NAME_LEN 0x226 - -static void -got_sessionreq(MsnSlpCall *slpcall, const char *branch, - const char *euf_guid, const char *context) -{ - if (!strcmp(euf_guid, "A4268EEC-FEC5-49E5-95C3-F126696BDBF6")) - { - /* Emoticon or UserDisplay */ - char *content; - gsize len; - MsnSlpSession *slpsession; - MsnSlpLink *slplink; - MsnSlpMessage *slpmsg; - MsnObject *obj; - char *msnobj_data; - PurpleStoredImage *img; - int type; - - /* Send Ok */ - content = g_strdup_printf("SessionID: %lu\r\n\r\n", - slpcall->session_id); - - send_ok(slpcall, branch, "application/x-msnmsgr-sessionreqbody", - content); - - g_free(content); - - slplink = slpcall->slplink; - - msnobj_data = (char *)purple_base64_decode(context, &len); - obj = msn_object_new_from_string(msnobj_data); - type = msn_object_get_type(obj); - g_free(msnobj_data); - - if ((type != MSN_OBJECT_USERTILE) && (type != MSN_OBJECT_EMOTICON)) - { - purple_debug_error("msn", "Wrong object?\n"); - msn_object_destroy(obj); - g_return_if_reached(); - } - - if (type == MSN_OBJECT_EMOTICON) { - char *path; - path = g_build_filename(purple_smileys_get_storing_dir(), - obj->location, NULL); - img = purple_imgstore_new_from_file(path); - g_free(path); - } else { - img = msn_object_get_image(obj); - if (img) - purple_imgstore_ref(img); - } - msn_object_destroy(obj); - - if (img == NULL) - { - purple_debug_error("msn", "Wrong object.\n"); - g_return_if_reached(); - } - - slpsession = msn_slplink_find_slp_session(slplink, - slpcall->session_id); - - /* DATA PREP */ - slpmsg = msn_slpmsg_new(slplink); - slpmsg->slpcall = slpcall; - slpmsg->slpsession = slpsession; - slpmsg->session_id = slpsession->id; - msn_slpmsg_set_body(slpmsg, NULL, 4); -#ifdef MSN_DEBUG_SLP - slpmsg->info = "SLP DATA PREP"; -#endif - msn_slplink_queue_slpmsg(slplink, slpmsg); - - /* DATA */ - slpmsg = msn_slpmsg_new(slplink); - slpmsg->slpcall = slpcall; - slpmsg->slpsession = slpsession; - slpmsg->flags = 0x20; -#ifdef MSN_DEBUG_SLP - slpmsg->info = "SLP DATA"; -#endif - msn_slpmsg_set_image(slpmsg, img); - msn_slplink_queue_slpmsg(slplink, slpmsg); - purple_imgstore_unref(img); - } - else if (!strcmp(euf_guid, "5D3E02AB-6190-11D3-BBBB-00C04F795683")) - { - /* File Transfer */ - PurpleAccount *account; - PurpleXfer *xfer; - char *bin; - gsize bin_len; - guint32 file_size; - gchar *file_name; - gunichar2 *uni_name; - - account = slpcall->slplink->session->account; - - slpcall->cb = msn_xfer_completed_cb; - slpcall->end_cb = msn_xfer_end_cb; - slpcall->progress_cb = msn_xfer_progress_cb; - slpcall->branch = g_strdup(branch); - - slpcall->pending = TRUE; - - xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE, - slpcall->slplink->remote_user); - if (xfer) - { - bin = (char *)purple_base64_decode(context, &bin_len); - file_size = GUINT32_FROM_LE(*(gsize *)(bin + 8)); - - uni_name = (gunichar2 *)(bin + 20); - while(*uni_name != 0 && ((char *)uni_name - (bin + 20)) < MAX_FILE_NAME_LEN) { - *uni_name = GUINT16_FROM_LE(*uni_name); - uni_name++; - } - - file_name = g_utf16_to_utf8((const gunichar2 *)(bin + 20), -1, - NULL, NULL, NULL); - - g_free(bin); - - purple_xfer_set_filename(xfer, file_name ? file_name : ""); - g_free(file_name); - purple_xfer_set_size(xfer, file_size); - purple_xfer_set_init_fnc(xfer, msn_xfer_init); - purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel); - purple_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel); - - slpcall->xfer = xfer; - purple_xfer_ref(slpcall->xfer); - - xfer->data = slpcall; - - purple_xfer_request(xfer); - } - } -} - -void -send_bye(MsnSlpCall *slpcall, const char *type) -{ - MsnSlpLink *slplink; - MsnSlpMessage *slpmsg; - char *header; - - slplink = slpcall->slplink; - - g_return_if_fail(slplink != NULL); - - header = g_strdup_printf("BYE MSNMSGR:%s MSNSLP/1.0", - slplink->local_user); - - slpmsg = msn_slpmsg_sip_new(slpcall, 0, header, - "A0D624A6-6C0C-4283-A9E0-BC97B4B46D32", - type, - "\r\n"); - g_free(header); - -#ifdef MSN_DEBUG_SLP - slpmsg->info = "SLP BYE"; - slpmsg->text_body = TRUE; -#endif - - msn_slplink_queue_slpmsg(slplink, slpmsg); -} - -static void -got_invite(MsnSlpCall *slpcall, - const char *branch, const char *type, const char *content) -{ - MsnSlpLink *slplink; - - slplink = slpcall->slplink; - - if (!strcmp(type, "application/x-msnmsgr-sessionreqbody")) - { - char *euf_guid, *context; - char *temp; - - euf_guid = get_token(content, "EUF-GUID: {", "}\r\n"); - - temp = get_token(content, "SessionID: ", "\r\n"); - if (temp != NULL) - slpcall->session_id = atoi(temp); - g_free(temp); - - temp = get_token(content, "AppID: ", "\r\n"); - if (temp != NULL) - slpcall->app_id = atoi(temp); - g_free(temp); - - context = get_token(content, "Context: ", "\r\n"); - - if (context != NULL) - got_sessionreq(slpcall, branch, euf_guid, context); - - g_free(context); - g_free(euf_guid); - } - else if (!strcmp(type, "application/x-msnmsgr-transreqbody")) - { - /* A direct connection? */ - - char *listening, *nonce; - char *content; - - if (FALSE) - { -#if 0 - MsnDirectConn *directconn; - /* const char *ip_addr; */ - char *ip_port; - int port; - - /* ip_addr = purple_prefs_get_string("/purple/ft/public_ip"); */ - ip_port = "5190"; - listening = "true"; - nonce = rand_guid(); - - directconn = msn_directconn_new(slplink); - - /* msn_directconn_parse_nonce(directconn, nonce); */ - directconn->nonce = g_strdup(nonce); - - msn_directconn_listen(directconn); - - port = directconn->port; - - content = g_strdup_printf( - "Bridge: TCPv1\r\n" - "Listening: %s\r\n" - "Nonce: {%s}\r\n" - "Ipv4Internal-Addrs: 192.168.0.82\r\n" - "Ipv4Internal-Port: %d\r\n" - "\r\n", - listening, - nonce, - port); -#endif - } - else - { - listening = "false"; - nonce = g_strdup("00000000-0000-0000-0000-000000000000"); - - content = g_strdup_printf( - "Bridge: TCPv1\r\n" - "Listening: %s\r\n" - "Nonce: {%s}\r\n" - "\r\n", - listening, - nonce); - } - - send_ok(slpcall, branch, - "application/x-msnmsgr-transrespbody", content); - - g_free(content); - g_free(nonce); - } - else if (!strcmp(type, "application/x-msnmsgr-transrespbody")) - { -#if 0 - char *ip_addrs; - char *temp; - char *nonce; - int port; - - nonce = get_token(content, "Nonce: {", "}\r\n"); - ip_addrs = get_token(content, "IPv4Internal-Addrs: ", "\r\n"); - - temp = get_token(content, "IPv4Internal-Port: ", "\r\n"); - if (temp != NULL) - port = atoi(temp); - else - port = -1; - g_free(temp); - - if (ip_addrs == NULL) - return; - - if (port > 0) - got_transresp(slpcall, nonce, ip_addrs, port); - - g_free(nonce); - g_free(ip_addrs); -#endif - } -} - -static void -got_ok(MsnSlpCall *slpcall, - const char *type, const char *content) -{ - g_return_if_fail(slpcall != NULL); - g_return_if_fail(type != NULL); - - if (!strcmp(type, "application/x-msnmsgr-sessionreqbody")) - { -#if 0 - if (slpcall->type == MSN_SLPCALL_DC) - { - /* First let's try a DirectConnection. */ - - MsnSlpLink *slplink; - MsnSlpMessage *slpmsg; - char *header; - char *content; - char *branch; - - slplink = slpcall->slplink; - - branch = rand_guid(); - - content = g_strdup_printf( - "Bridges: TRUDPv1 TCPv1\r\n" - "NetID: 0\r\n" - "Conn-Type: Direct-Connect\r\n" - "UPnPNat: false\r\n" - "ICF: false\r\n" - ); - - header = g_strdup_printf("INVITE MSNMSGR:%s MSNSLP/1.0", - slplink->remote_user); - - slpmsg = msn_slp_sipmsg_new(slpcall, 0, header, branch, - "application/x-msnmsgr-transreqbody", - content); - -#ifdef MSN_DEBUG_SLP - slpmsg->info = "SLP INVITE"; - slpmsg->text_body = TRUE; -#endif - msn_slplink_send_slpmsg(slplink, slpmsg); - - g_free(header); - g_free(content); - - g_free(branch); - } - else - { - msn_slp_call_session_init(slpcall); - } -#else - msn_slp_call_session_init(slpcall); -#endif - } - else if (!strcmp(type, "application/x-msnmsgr-transreqbody")) - { - /* Do we get this? */ - purple_debug_info("msn", "OK with transreqbody\n"); - } - else if (!strcmp(type, "application/x-msnmsgr-transrespbody")) - { -#if 0 - char *ip_addrs; - char *temp; - char *nonce; - int port; - - nonce = get_token(content, "Nonce: {", "}\r\n"); - ip_addrs = get_token(content, "IPv4Internal-Addrs: ", "\r\n"); - - temp = get_token(content, "IPv4Internal-Port: ", "\r\n"); - if (temp != NULL) - port = atoi(temp); - else - port = -1; - g_free(temp); - - if (ip_addrs == NULL) - return; - - if (port > 0) - got_transresp(slpcall, nonce, ip_addrs, port); - - g_free(nonce); - g_free(ip_addrs); -#endif - } -} - -MsnSlpCall * -msn_slp_sip_recv(MsnSlpLink *slplink, const char *body) -{ - MsnSlpCall *slpcall; - - if (body == NULL) - { - purple_debug_warning("msn", "received bogus message\n"); - return NULL; - } - - if (!strncmp(body, "INVITE", strlen("INVITE"))) - { - char *branch; - char *content; - char *content_type; - - slpcall = msn_slp_call_new(slplink); - - /* From: <msnmsgr:buddy@hotmail.com> */ -#if 0 - slpcall->remote_user = get_token(body, "From: <msnmsgr:", ">\r\n"); -#endif - - branch = get_token(body, ";branch={", "}"); - - slpcall->id = get_token(body, "Call-ID: {", "}"); - -#if 0 - long content_len = -1; - - temp = get_token(body, "Content-Length: ", "\r\n"); - if (temp != NULL) - content_len = atoi(temp); - g_free(temp); -#endif - content_type = get_token(body, "Content-Type: ", "\r\n"); - - content = get_token(body, "\r\n\r\n", NULL); - - got_invite(slpcall, branch, content_type, content); - - g_free(branch); - g_free(content_type); - g_free(content); - } - else if (!strncmp(body, "MSNSLP/1.0 ", strlen("MSNSLP/1.0 "))) - { - char *content; - char *content_type; - /* Make sure this is "OK" */ - const char *status = body + strlen("MSNSLP/1.0 "); - char *call_id; - - call_id = get_token(body, "Call-ID: {", "}"); - slpcall = msn_slplink_find_slp_call(slplink, call_id); - g_free(call_id); - - g_return_val_if_fail(slpcall != NULL, NULL); - - if (strncmp(status, "200 OK", 6)) - { - /* It's not valid. Kill this off. */ - char temp[32]; - const char *c; - - /* Eww */ - if ((c = strchr(status, '\r')) || (c = strchr(status, '\n')) || - (c = strchr(status, '\0'))) - { - size_t offset = c - status; - if (offset >= sizeof(temp)) - offset = sizeof(temp) - 1; - - strncpy(temp, status, offset); - temp[offset] = '\0'; - } - - purple_debug_error("msn", "Received non-OK result: %s\n", temp); - - slpcall->wasted = TRUE; - - /* msn_slp_call_destroy(slpcall); */ - return slpcall; - } - - content_type = get_token(body, "Content-Type: ", "\r\n"); - - content = get_token(body, "\r\n\r\n", NULL); - - got_ok(slpcall, content_type, content); - - g_free(content_type); - g_free(content); - } - else if (!strncmp(body, "BYE", strlen("BYE"))) - { - char *call_id; - - call_id = get_token(body, "Call-ID: {", "}"); - slpcall = msn_slplink_find_slp_call(slplink, call_id); - g_free(call_id); - - if (slpcall != NULL) - slpcall->wasted = TRUE; - - /* msn_slp_call_destroy(slpcall); */ - } - else - slpcall = NULL; - - return slpcall; -} - -/************************************************************************** - * Msg Callbacks - **************************************************************************/ - -void -msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - MsnSession *session; - MsnSlpLink *slplink; - - session = cmdproc->servconn->session; - slplink = msn_session_get_slplink(session, msg->remote_user); - - if (slplink->swboard == NULL) - { - /* We will need this in order to change its flags. */ - slplink->swboard = (MsnSwitchBoard *)cmdproc->data; - /* If swboard is NULL, something has probably gone wrong earlier on - * I didn't want to do this, but MSN 7 is somehow causing us to crash - * here, I couldn't reproduce it to debug more, and people are - * reporting bugs. Hopefully this doesn't cause more crashes. Stu. - */ - if (slplink->swboard != NULL) - slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink); - else - purple_debug_error("msn", "msn_p2p_msg, swboard is NULL, ouch!\n"); - } - - msn_slplink_process_msg(slplink, msg); -} - -static void -got_emoticon(MsnSlpCall *slpcall, - const guchar *data, gsize size) -{ - - PurpleConversation *conv; - PurpleConnection *gc; - const char *who; - - gc = slpcall->slplink->session->account->gc; - who = slpcall->slplink->remote_user; - - if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, gc->account))) { - - /* FIXME: it would be better if we wrote the data as we received it - instead of all at once, calling write multiple times and - close once at the very end - */ - purple_conv_custom_smiley_write(conv, slpcall->data_info, data, size); - purple_conv_custom_smiley_close(conv, slpcall->data_info); - } -#ifdef MSN_DEBUG_UD - purple_debug_info("msn", "Got smiley: %s\n", slpcall->data_info); -#endif -} - -void -msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - MsnSession *session; - MsnSlpLink *slplink; - MsnObject *obj; - char **tokens; - char *smile, *body_str; - const char *body, *who, *sha1; - guint tok; - size_t body_len; - - PurpleConversation *conv; - - session = cmdproc->servconn->session; - - if (!purple_account_get_bool(session->account, "custom_smileys", TRUE)) - return; - - body = msn_message_get_bin_data(msg, &body_len); - body_str = g_strndup(body, body_len); - - /* MSN Messenger 7 may send more than one MSNObject in a single message... - * Maybe 10 tokens is a reasonable max value. */ - tokens = g_strsplit(body_str, "\t", 10); - - g_free(body_str); - - for (tok = 0; tok < 9; tok += 2) { - if (tokens[tok] == NULL || tokens[tok + 1] == NULL) { - break; - } - - smile = tokens[tok]; - obj = msn_object_new_from_string(purple_url_decode(tokens[tok + 1])); - - if (obj == NULL) - break; - - who = msn_object_get_creator(obj); - sha1 = msn_object_get_sha1(obj); - - slplink = msn_session_get_slplink(session, who); - - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, - session->account); - - /* If the conversation doesn't exist then this is a custom smiley - * used in the first message in a MSN conversation: we need to create - * the conversation now, otherwise the custom smiley won't be shown. - * This happens because every GtkIMHtml has its own smiley tree: if - * the conversation doesn't exist then we cannot associate the new - * smiley with its GtkIMHtml widget. */ - if (!conv) { - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, who); - } - - if (purple_conv_custom_smiley_add(conv, smile, "sha1", sha1, TRUE)) { - msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj); - } - - msn_object_destroy(obj); - obj = NULL; - who = NULL; - sha1 = NULL; - } - g_strfreev(tokens); -} - -static gboolean -buddy_icon_cached(PurpleConnection *gc, MsnObject *obj) -{ - PurpleAccount *account; - PurpleBuddy *buddy; - const char *old; - const char *new; - - g_return_val_if_fail(obj != NULL, FALSE); - - account = purple_connection_get_account(gc); - - buddy = purple_find_buddy(account, msn_object_get_creator(obj)); - if (buddy == NULL) - return FALSE; - - old = purple_buddy_icons_get_checksum_for_user(buddy); - new = msn_object_get_sha1(obj); - - if (new == NULL) - return FALSE; - - /* If the old and new checksums are the same, and the file actually exists, - * then return TRUE */ - if (old != NULL && !strcmp(old, new)) - return TRUE; - - return FALSE; -} - -static void -msn_release_buddy_icon_request(MsnUserList *userlist) -{ - MsnUser *user; - - g_return_if_fail(userlist != NULL); - -#ifdef MSN_DEBUG_UD - purple_debug_info("msn", "Releasing buddy icon request\n"); -#endif - - if (userlist->buddy_icon_window > 0) - { - GQueue *queue; - PurpleAccount *account; - const char *username; - - queue = userlist->buddy_icon_requests; - - if (g_queue_is_empty(userlist->buddy_icon_requests)) - return; - - user = g_queue_pop_head(queue); - - account = userlist->session->account; - username = user->passport; - - userlist->buddy_icon_window--; - msn_request_user_display(user); - -#ifdef MSN_DEBUG_UD - purple_debug_info("msn", "msn_release_buddy_icon_request(): buddy_icon_window-- yields =%d\n", - userlist->buddy_icon_window); -#endif - } -} - -/* - * Called on a timeout from end_user_display(). Frees a buddy icon window slow and dequeues the next - * buddy icon request if there is one. - */ -static gboolean -msn_release_buddy_icon_request_timeout(gpointer data) -{ - MsnUserList *userlist = (MsnUserList *)data; - - /* Free one window slot */ - userlist->buddy_icon_window++; - - /* Clear the tag for our former request timer */ - userlist->buddy_icon_request_timer = 0; - - msn_release_buddy_icon_request(userlist); - - return FALSE; -} - -void -msn_queue_buddy_icon_request(MsnUser *user) -{ - PurpleAccount *account; - MsnObject *obj; - GQueue *queue; - - g_return_if_fail(user != NULL); - - account = user->userlist->session->account; - - obj = msn_user_get_object(user); - - if (obj == NULL) - { - purple_buddy_icons_set_for_user(account, user->passport, NULL, 0, NULL); - return; - } - - if (!buddy_icon_cached(account->gc, obj)) - { - MsnUserList *userlist; - - userlist = user->userlist; - queue = userlist->buddy_icon_requests; - -#ifdef MSN_DEBUG_UD - purple_debug_info("msn", "Queueing buddy icon request for %s (buddy_icon_window = %i)\n", - user->passport, userlist->buddy_icon_window); -#endif - - g_queue_push_tail(queue, user); - - if (userlist->buddy_icon_window > 0) - msn_release_buddy_icon_request(userlist); - } -} - -static void -got_user_display(MsnSlpCall *slpcall, - const guchar *data, gsize size) -{ - MsnUserList *userlist; - const char *info; - PurpleAccount *account; - - g_return_if_fail(slpcall != NULL); - - info = slpcall->data_info; -#ifdef MSN_DEBUG_UD - purple_debug_info("msn", "Got User Display: %s\n", slpcall->slplink->remote_user); -#endif - - userlist = slpcall->slplink->session->userlist; - account = slpcall->slplink->session->account; - - purple_buddy_icons_set_for_user(account, slpcall->slplink->remote_user, - g_memdup(data, size), size, info); - -#if 0 - /* Free one window slot */ - userlist->buddy_icon_window++; - - purple_debug_info("msn", "got_user_display(): buddy_icon_window++ yields =%d\n", - userlist->buddy_icon_window); - - msn_release_buddy_icon_request(userlist); -#endif -} - -static void -end_user_display(MsnSlpCall *slpcall, MsnSession *session) -{ - MsnUserList *userlist; - - g_return_if_fail(session != NULL); - -#ifdef MSN_DEBUG_UD - purple_debug_info("msn", "End User Display\n"); -#endif - - userlist = session->userlist; - - /* If the session is being destroyed we better stop doing anything. */ - if (session->destroying) - return; - - /* Delay before freeing a buddy icon window slot and requesting the next icon, if appropriate. - * If we don't delay, we'll rapidly hit the MSN equivalent of AIM's rate limiting; the server will - * send us an error 800 like so: - * - * C: NS 000: XFR 21 SB - * S: NS 000: 800 21 - */ - if (userlist->buddy_icon_request_timer) { - /* Free the window slot used by this previous request */ - userlist->buddy_icon_window++; - - /* Clear our pending timeout */ - purple_timeout_remove(userlist->buddy_icon_request_timer); - } - - /* Wait BUDDY_ICON_DELAY_S seconds before freeing our window slot and requesting the next icon. */ - userlist->buddy_icon_request_timer = purple_timeout_add_seconds(BUDDY_ICON_DELAY, - msn_release_buddy_icon_request_timeout, userlist); -} - -void -msn_request_user_display(MsnUser *user) -{ - PurpleAccount *account; - MsnSession *session; - MsnSlpLink *slplink; - MsnObject *obj; - const char *info; - - session = user->userlist->session; - account = session->account; - - slplink = msn_session_get_slplink(session, user->passport); - - obj = msn_user_get_object(user); - - info = msn_object_get_sha1(obj); - - if (g_ascii_strcasecmp(user->passport, - purple_account_get_username(account))) - { - msn_slplink_request_object(slplink, info, got_user_display, - end_user_display, obj); - } - else - { - MsnObject *my_obj = NULL; - gconstpointer data = NULL; - size_t len = 0; - -#ifdef MSN_DEBUG_UD - purple_debug_info("msn", "Requesting our own user display\n"); -#endif - - my_obj = msn_user_get_object(session->user); - - if (my_obj != NULL) - { - PurpleStoredImage *img = msn_object_get_image(my_obj); - data = purple_imgstore_get_data(img); - len = purple_imgstore_get_size(img); - } - - purple_buddy_icons_set_for_user(account, user->passport, g_memdup(data, len), len, info); - - /* Free one window slot */ - session->userlist->buddy_icon_window++; - -#ifdef MSN_DEBUG_UD - purple_debug_info("msn", "msn_request_user_display(): buddy_icon_window++ yields =%d\n", - session->userlist->buddy_icon_window); -#endif - - msn_release_buddy_icon_request(session->userlist); - } -}
--- a/libpurple/protocols/msnp9/slp.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/** - * @file slp.h MSNSLP support - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_SLP_H_ -#define _MSN_SLP_H_ - -#include "slpcall.h" -#include "session.h" -#include "internal.h" -#include "ft.h" - -void msn_xfer_progress_cb(MsnSlpCall *slpcall, gsize total_length, gsize - len, gsize offset); - -MsnSlpCall * msn_slp_sip_recv(MsnSlpLink *slplink, - const char *body); - -void send_bye(MsnSlpCall *slpcall, const char *type); - -void msn_xfer_completed_cb(MsnSlpCall *slpcall, - const guchar *body, gsize size); - -void msn_xfer_cancel(PurpleXfer *xfer); -void msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session); - -void msn_queue_buddy_icon_request(MsnUser *user); - -#endif /* _MSN_SLP_H_ */
--- a/libpurple/protocols/msnp9/slpcall.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,272 +0,0 @@ -/** - * @file slpcall.c SLP Call Functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "slpcall.h" -#include "slpsession.h" - -#include "slp.h" - -/* #define MSN_DEBUG_SLPCALL */ - -/************************************************************************** - * Util - **************************************************************************/ - -static char * -rand_guid(void) -{ - return g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X", - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111, - rand() % 0xAAFF + 0x1111); -} - -/************************************************************************** - * Main - **************************************************************************/ - -MsnSlpCall * -msn_slp_call_new(MsnSlpLink *slplink) -{ - MsnSlpCall *slpcall; - - g_return_val_if_fail(slplink != NULL, NULL); - - slpcall = g_new0(MsnSlpCall, 1); - -#ifdef MSN_DEBUG_SLPCALL - purple_debug_info("msn", "slpcall_new: slpcall(%p)\n", slpcall); -#endif - - slpcall->slplink = slplink; - - msn_slplink_add_slpcall(slplink, slpcall); - - slpcall->timer = purple_timeout_add_seconds(MSN_SLPCALL_TIMEOUT, msn_slp_call_timeout, slpcall); - - return slpcall; -} - -void -msn_slp_call_destroy(MsnSlpCall *slpcall) -{ - GList *e; - MsnSession *session; - -#ifdef MSN_DEBUG_SLPCALL - purple_debug_info("msn", "slpcall_destroy: slpcall(%p)\n", slpcall); -#endif - - g_return_if_fail(slpcall != NULL); - - if (slpcall->timer) - purple_timeout_remove(slpcall->timer); - - if (slpcall->id != NULL) - g_free(slpcall->id); - - if (slpcall->branch != NULL) - g_free(slpcall->branch); - - if (slpcall->data_info != NULL) - g_free(slpcall->data_info); - - for (e = slpcall->slplink->slp_msgs; e != NULL; ) - { - MsnSlpMessage *slpmsg = e->data; - e = e->next; - -#ifdef MSN_DEBUG_SLPCALL_VERBOSE - purple_debug_info("msn", "slpcall_destroy: trying slpmsg(%p)\n", - slpmsg); -#endif - - if (slpmsg->slpcall == slpcall) - { - msn_slpmsg_destroy(slpmsg); - } - } - - session = slpcall->slplink->session; - - msn_slplink_remove_slpcall(slpcall->slplink, slpcall); - - if (slpcall->end_cb != NULL) - slpcall->end_cb(slpcall, session); - - if (slpcall->xfer != NULL) { - slpcall->xfer->data = NULL; - purple_xfer_unref(slpcall->xfer); - } - - g_free(slpcall); -} - -void -msn_slp_call_init(MsnSlpCall *slpcall, MsnSlpCallType type) -{ - slpcall->session_id = rand() % 0xFFFFFF00 + 4; - slpcall->id = rand_guid(); - slpcall->type = type; -} - -void -msn_slp_call_session_init(MsnSlpCall *slpcall) -{ - MsnSlpSession *slpsession; - - slpsession = msn_slp_session_new(slpcall); - - if (slpcall->session_init_cb) - slpcall->session_init_cb(slpsession); - - slpcall->started = TRUE; -} - -void -msn_slp_call_invite(MsnSlpCall *slpcall, const char *euf_guid, - int app_id, const char *context) -{ - MsnSlpLink *slplink; - MsnSlpMessage *slpmsg; - char *header; - char *content; - - g_return_if_fail(slpcall != NULL); - g_return_if_fail(context != NULL); - - slplink = slpcall->slplink; - - slpcall->branch = rand_guid(); - - content = g_strdup_printf( - "EUF-GUID: {%s}\r\n" - "SessionID: %lu\r\n" - "AppID: %d\r\n" - "Context: %s\r\n\r\n", - euf_guid, - slpcall->session_id, - app_id, - context); - - header = g_strdup_printf("INVITE MSNMSGR:%s MSNSLP/1.0", - slplink->remote_user); - - slpmsg = msn_slpmsg_sip_new(slpcall, 0, header, slpcall->branch, - "application/x-msnmsgr-sessionreqbody", content); - -#ifdef MSN_DEBUG_SLP - slpmsg->info = "SLP INVITE"; - slpmsg->text_body = TRUE; -#endif - - msn_slplink_send_slpmsg(slplink, slpmsg); - - g_free(header); - g_free(content); -} - -void -msn_slp_call_close(MsnSlpCall *slpcall) -{ - g_return_if_fail(slpcall != NULL); - g_return_if_fail(slpcall->slplink != NULL); - - send_bye(slpcall, "application/x-msnmsgr-sessionclosebody"); - msn_slplink_unleash(slpcall->slplink); - msn_slp_call_destroy(slpcall); -} - -gboolean -msn_slp_call_timeout(gpointer data) -{ - MsnSlpCall *slpcall; - - slpcall = data; - -#ifdef MSN_DEBUG_SLPCALL - purple_debug_info("msn", "slpcall_timeout: slpcall(%p)\n", slpcall); -#endif - - if (!slpcall->pending && !slpcall->progress) - { - msn_slp_call_destroy(slpcall); - return FALSE; - } - - slpcall->progress = FALSE; - - return TRUE; -} - -MsnSlpCall * -msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) -{ - MsnSlpCall *slpcall; - const guchar *body; - gsize body_len; - - slpcall = NULL; - body = slpmsg->buffer; - body_len = slpmsg->size; - - if (slpmsg->flags == 0x0) - { - char *body_str; - - body_str = g_strndup((const char *)body, body_len); - slpcall = msn_slp_sip_recv(slplink, body_str); - g_free(body_str); - } - else if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) - { - slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id); - - if (slpcall != NULL) - { - if (slpcall->timer) - purple_timeout_remove(slpcall->timer); - - slpcall->cb(slpcall, body, body_len); - - slpcall->wasted = TRUE; - } - } -#if 0 - else if (slpmsg->flags == 0x100) - { - slpcall = slplink->directconn->initial_call; - - if (slpcall != NULL) - msn_slp_call_session_init(slpcall); - } -#endif - - return slpcall; -}
--- a/libpurple/protocols/msnp9/slpcall.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/** - * @file slpcall.h SLP Call functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_SLPCALL_H_ -#define _MSN_SLPCALL_H_ - -#include "internal.h" -#include "ft.h" - -typedef struct _MsnSlpCall MsnSlpCall; - -#include "slplink.h" -#include "slpsession.h" - -/* The official client seems to timeout slp calls after 5 minutes */ -#define MSN_SLPCALL_TIMEOUT 300 - -typedef enum -{ - MSN_SLPCALL_ANY, - MSN_SLPCALL_DC, - -} MsnSlpCallType; - -struct _MsnSlpCall -{ - /* MsnSession *session; */ - MsnSlpLink *slplink; - - MsnSlpCallType type; - - /* Call-ID */ - char *id; - char *branch; - - long session_id; - long app_id; - - gboolean pending; /**< A flag that states if we should wait for this - slpcall to start and do not time out. */ - gboolean progress; /**< A flag that states if there has been progress since - the last time out. */ - gboolean wasted; /**< A flag that states if this slpcall is going to be - destroyed. */ - gboolean started; /**< A flag that states if this slpcall's session has - been initiated. */ - - void (*progress_cb)(MsnSlpCall *slpcall, - gsize total_length, gsize len, gsize offset); - void (*session_init_cb)(MsnSlpSession *slpsession); - - /* Can be checksum, or smile */ - char *data_info; - - PurpleXfer *xfer; - - MsnSlpCb cb; - void (*end_cb)(MsnSlpCall *slpcall, MsnSession *session); - - int timer; -}; - -MsnSlpCall *msn_slp_call_new(MsnSlpLink *slplink); -void msn_slp_call_init(MsnSlpCall *slpcall, MsnSlpCallType type); -void msn_slp_call_session_init(MsnSlpCall *slpcall); -void msn_slp_call_destroy(MsnSlpCall *slpcall); -void msn_slp_call_invite(MsnSlpCall *slpcall, const char *euf_guid, - int app_id, const char *context); -void msn_slp_call_close(MsnSlpCall *slpcall); -gboolean msn_slp_call_timeout(gpointer data); - -#endif /* _MSN_SLPCALL_H_ */
--- a/libpurple/protocols/msnp9/slplink.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,822 +0,0 @@ -/** - * @file slplink.c MSNSLP Link support - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "slplink.h" - -#include "switchboard.h" -#include "slp.h" - -void msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg); - -#ifdef MSN_DEBUG_SLP_FILES -static int m_sc = 0; -static int m_rc = 0; - -static void -debug_msg_to_file(MsnMessage *msg, gboolean send) -{ - char *tmp; - char *dir; - char *pload; - FILE *tf; - int c; - gsize pload_size; - - dir = send ? "send" : "recv"; - c = send ? m_sc++ : m_rc++; - tmp = g_strdup_printf("%s/msntest/%s/%03d", g_get_home_dir(), dir, c); - tf = g_fopen(tmp, "wb"); - if (tf == NULL) - { - purple_debug_error("msn", "could not open debug file\n"); - return; - } - pload = msn_message_gen_payload(msg, &pload_size); - fwrite(pload, 1, pload_size, tf); - fclose(tf); - g_free(tmp); -} -#endif - -/************************************************************************** - * Main - **************************************************************************/ - -MsnSlpLink * -msn_slplink_new(MsnSession *session, const char *username) -{ - MsnSlpLink *slplink; - - g_return_val_if_fail(session != NULL, NULL); - - slplink = g_new0(MsnSlpLink, 1); - -#ifdef MSN_DEBUG_SLPLINK - purple_debug_info("msn", "slplink_new: slplink(%p)\n", slplink); -#endif - - slplink->session = session; - slplink->slp_seq_id = rand() % 0xFFFFFF00 + 4; - - slplink->local_user = g_strdup(msn_user_get_passport(session->user)); - slplink->remote_user = g_strdup(username); - - slplink->slp_msg_queue = g_queue_new(); - - session->slplinks = - g_list_append(session->slplinks, slplink); - - return slplink; -} - -void -msn_slplink_destroy(MsnSlpLink *slplink) -{ - MsnSession *session; - -#ifdef MSN_DEBUG_SLPLINK - purple_debug_info("msn", "slplink_destroy: slplink(%p)\n", slplink); -#endif - - g_return_if_fail(slplink != NULL); - - if (slplink->swboard != NULL) - slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink); - - session = slplink->session; - - if (slplink->local_user != NULL) - g_free(slplink->local_user); - - if (slplink->remote_user != NULL) - g_free(slplink->remote_user); - - if (slplink->directconn != NULL) - msn_directconn_destroy(slplink->directconn); - - while (slplink->slp_calls != NULL) - msn_slp_call_destroy(slplink->slp_calls->data); - - g_queue_free(slplink->slp_msg_queue); - - session->slplinks = - g_list_remove(session->slplinks, slplink); - - g_free(slplink); -} - -MsnSlpLink * -msn_session_find_slplink(MsnSession *session, const char *who) -{ - GList *l; - - for (l = session->slplinks; l != NULL; l = l->next) - { - MsnSlpLink *slplink; - - slplink = l->data; - - if (!strcmp(slplink->remote_user, who)) - return slplink; - } - - return NULL; -} - -MsnSlpLink * -msn_session_get_slplink(MsnSession *session, const char *username) -{ - MsnSlpLink *slplink; - - g_return_val_if_fail(session != NULL, NULL); - g_return_val_if_fail(username != NULL, NULL); - - slplink = msn_session_find_slplink(session, username); - - if (slplink == NULL) - slplink = msn_slplink_new(session, username); - - return slplink; -} - -MsnSlpSession * -msn_slplink_find_slp_session(MsnSlpLink *slplink, long session_id) -{ - GList *l; - MsnSlpSession *slpsession; - - for (l = slplink->slp_sessions; l != NULL; l = l->next) - { - slpsession = l->data; - - if (slpsession->id == session_id) - return slpsession; - } - - return NULL; -} - -void -msn_slplink_add_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall) -{ - if (slplink->swboard != NULL) - slplink->swboard->flag |= MSN_SB_FLAG_FT; - - slplink->slp_calls = g_list_append(slplink->slp_calls, slpcall); -} - -void -msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall) -{ - slplink->slp_calls = g_list_remove(slplink->slp_calls, slpcall); - - /* The slplink has no slpcalls in it. If no one is using it, we might - * destroy the switchboard, but we should be careful not to use the slplink - * again. */ - if (slplink->slp_calls == NULL) - { - if (slplink->swboard != NULL) - { - if (msn_switchboard_release(slplink->swboard, MSN_SB_FLAG_FT)) - /* I'm not sure this is the best thing to do, but it's better - * than nothing. */ - slpcall->slplink = NULL; - } - } -} - -MsnSlpCall * -msn_slplink_find_slp_call(MsnSlpLink *slplink, const char *id) -{ - GList *l; - MsnSlpCall *slpcall; - - if (!id) - return NULL; - - for (l = slplink->slp_calls; l != NULL; l = l->next) - { - slpcall = l->data; - - if (slpcall->id && !strcmp(slpcall->id, id)) - return slpcall; - } - - return NULL; -} - -MsnSlpCall * -msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id) -{ - GList *l; - MsnSlpCall *slpcall; - - for (l = slplink->slp_calls; l != NULL; l = l->next) - { - slpcall = l->data; - - if (slpcall->session_id == id) - return slpcall; - } - - return NULL; -} - -void -msn_slplink_send_msg(MsnSlpLink *slplink, MsnMessage *msg) -{ - if (slplink->directconn != NULL) - { - msn_directconn_send_msg(slplink->directconn, msg); - } - else - { - if (slplink->swboard == NULL) - { - slplink->swboard = msn_session_get_swboard(slplink->session, - slplink->remote_user, MSN_SB_FLAG_FT); - - if (slplink->swboard == NULL) - return; - - /* If swboard is destroyed we will be too */ - slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink); - } - - msn_switchboard_send_msg(slplink->swboard, msg, TRUE); - } -} - -/* We have received the message ack */ -static void -msg_ack(MsnMessage *msg, void *data) -{ - MsnSlpMessage *slpmsg; - long long real_size; - - slpmsg = data; - - real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size; - - slpmsg->offset += msg->msnslp_header.length; - - if (slpmsg->offset < real_size) - { - msn_slplink_send_msgpart(slpmsg->slplink, slpmsg); - } - else - { - /* The whole message has been sent */ - if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) - { - if (slpmsg->slpcall != NULL) - { - if (slpmsg->slpcall->cb) - slpmsg->slpcall->cb(slpmsg->slpcall, - NULL, 0); - } - } - } - - slpmsg->msgs = g_list_remove(slpmsg->msgs, msg); -} - -/* We have received the message nak. */ -static void -msg_nak(MsnMessage *msg, void *data) -{ - MsnSlpMessage *slpmsg; - - slpmsg = data; - - msn_slplink_send_msgpart(slpmsg->slplink, slpmsg); - - slpmsg->msgs = g_list_remove(slpmsg->msgs, msg); -} - -void -msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) -{ - MsnMessage *msg; - long long real_size; - size_t len = 0; - - /* Maybe we will want to create a new msg for this slpmsg instead of - * reusing the same one all the time. */ - msg = slpmsg->msg; - - real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size; - - if (slpmsg->offset < real_size) - { - if (slpmsg->fp) - { - char data[1202]; - len = fread(data, 1, sizeof(data), slpmsg->fp); - msn_message_set_bin_data(msg, data, len); - } - else - { - len = slpmsg->size - slpmsg->offset; - - if (len > 1202) - len = 1202; - - msn_message_set_bin_data(msg, slpmsg->buffer + slpmsg->offset, len); - } - - msg->msnslp_header.offset = slpmsg->offset; - msg->msnslp_header.length = len; - } - -#ifdef MSN_DEBUG_SLP - msn_message_show_readable(msg, slpmsg->info, slpmsg->text_body); -#endif - -#ifdef MSN_DEBUG_SLP_FILES - debug_msg_to_file(msg, TRUE); -#endif - - slpmsg->msgs = - g_list_append(slpmsg->msgs, msg); - msn_slplink_send_msg(slplink, msg); - - if ((slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) && - (slpmsg->slpcall != NULL)) - { - slpmsg->slpcall->progress = TRUE; - - if (slpmsg->slpcall->progress_cb != NULL) - { - slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size, - len, slpmsg->offset); - } - } - - /* slpmsg->offset += len; */ -} - -void -msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) -{ - MsnMessage *msg; - - slpmsg->msg = msg = msn_message_new_msnslp(); - - if (slpmsg->flags == 0x0) - { - msg->msnslp_header.session_id = slpmsg->session_id; - msg->msnslp_header.ack_id = rand() % 0xFFFFFF00; - } - else if (slpmsg->flags == 0x2) - { - msg->msnslp_header.session_id = slpmsg->session_id; - msg->msnslp_header.ack_id = slpmsg->ack_id; - msg->msnslp_header.ack_size = slpmsg->ack_size; - msg->msnslp_header.ack_sub_id = slpmsg->ack_sub_id; - } - else if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) - { - MsnSlpSession *slpsession; - slpsession = slpmsg->slpsession; - - g_return_if_fail(slpsession != NULL); - msg->msnslp_header.session_id = slpsession->id; - msg->msnslp_footer.value = slpsession->app_id; - msg->msnslp_header.ack_id = rand() % 0xFFFFFF00; - } - else if (slpmsg->flags == 0x100) - { - msg->msnslp_header.ack_id = slpmsg->ack_id; - msg->msnslp_header.ack_sub_id = slpmsg->ack_sub_id; - msg->msnslp_header.ack_size = slpmsg->ack_size; - } - - msg->msnslp_header.id = slpmsg->id; - msg->msnslp_header.flags = slpmsg->flags; - - msg->msnslp_header.total_size = slpmsg->size; - - msn_message_set_attr(msg, "P2P-Dest", slplink->remote_user); - - msg->ack_cb = msg_ack; - msg->nak_cb = msg_nak; - msg->ack_data = slpmsg; - - msn_slplink_send_msgpart(slplink, slpmsg); - - msn_message_destroy(msg); -} - -void -msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) -{ - slpmsg->id = slplink->slp_seq_id++; - - g_queue_push_head(slplink->slp_msg_queue, slpmsg); -} - -void -msn_slplink_send_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg) -{ - slpmsg->id = slplink->slp_seq_id++; - - msn_slplink_release_slpmsg(slplink, slpmsg); -} - -void -msn_slplink_unleash(MsnSlpLink *slplink) -{ - MsnSlpMessage *slpmsg; - - /* Send the queued msgs in the order they came. */ - - while ((slpmsg = g_queue_pop_tail(slplink->slp_msg_queue)) != NULL) - { - msn_slplink_release_slpmsg(slplink, slpmsg); - } -} - -void -msn_slplink_send_ack(MsnSlpLink *slplink, MsnMessage *msg) -{ - MsnSlpMessage *slpmsg; - - slpmsg = msn_slpmsg_new(slplink); - - slpmsg->session_id = msg->msnslp_header.session_id; - slpmsg->size = msg->msnslp_header.total_size; - slpmsg->flags = 0x02; - slpmsg->ack_id = msg->msnslp_header.id; - slpmsg->ack_sub_id = msg->msnslp_header.ack_id; - slpmsg->ack_size = msg->msnslp_header.total_size; - -#ifdef MSN_DEBUG_SLP - slpmsg->info = "SLP ACK"; -#endif - - msn_slplink_send_slpmsg(slplink, slpmsg); - msn_slpmsg_destroy(slpmsg); -} - -static void -send_file_cb(MsnSlpSession *slpsession) -{ - MsnSlpCall *slpcall; - MsnSlpMessage *slpmsg; - struct stat st; - PurpleXfer *xfer; - - slpcall = slpsession->slpcall; - slpmsg = msn_slpmsg_new(slpcall->slplink); - slpmsg->slpcall = slpcall; - slpmsg->flags = 0x1000030; - slpmsg->slpsession = slpsession; -#ifdef MSN_DEBUG_SLP - slpmsg->info = "SLP FILE"; -#endif - xfer = (PurpleXfer *)slpcall->xfer; - purple_xfer_start(slpcall->xfer, -1, NULL, 0); - slpmsg->fp = xfer->dest_fp; - if (g_stat(purple_xfer_get_local_filename(xfer), &st) == 0) - slpmsg->size = st.st_size; - xfer->dest_fp = NULL; /* Disable double fclose() */ - - msn_slplink_send_slpmsg(slpcall->slplink, slpmsg); -} - -void -msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg) -{ - MsnSlpMessage *slpmsg; - const char *data; - guint64 offset; - gsize len; - -#ifdef MSN_DEBUG_SLP - msn_slpmsg_show(msg); -#endif - -#ifdef MSN_DEBUG_SLP_FILES - debug_msg_to_file(msg, FALSE); -#endif - - if (msg->msnslp_header.total_size < msg->msnslp_header.length) - { - purple_debug_error("msn", "This can't be good\n"); - g_return_if_reached(); - } - - slpmsg = NULL; - data = msn_message_get_bin_data(msg, &len); - - /* - OVERHEAD! - if (msg->msnslp_header.length < msg->msnslp_header.total_size) - */ - - offset = msg->msnslp_header.offset; - - if (offset == 0) - { - slpmsg = msn_slpmsg_new(slplink); - slpmsg->id = msg->msnslp_header.id; - slpmsg->session_id = msg->msnslp_header.session_id; - slpmsg->size = msg->msnslp_header.total_size; - slpmsg->flags = msg->msnslp_header.flags; - - if (slpmsg->session_id) - { - if (slpmsg->slpcall == NULL) - slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id); - - if (slpmsg->slpcall != NULL) - { - if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) - { - PurpleXfer *xfer; - - xfer = slpmsg->slpcall->xfer; - - if (xfer != NULL) - { - purple_xfer_ref(xfer); - purple_xfer_start(xfer, -1, NULL, 0); - - if (xfer->data == NULL) { - purple_xfer_unref(xfer); - return; - } else { - purple_xfer_unref(xfer); - slpmsg->fp = xfer->dest_fp; - xfer->dest_fp = NULL; /* Disable double fclose() */ - } - } - } - } - } - if (!slpmsg->fp && slpmsg->size) - { - slpmsg->buffer = g_try_malloc(slpmsg->size); - if (slpmsg->buffer == NULL) - { - purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n"); - msn_slpmsg_destroy(slpmsg); - return; - } - } - } - else - { - slpmsg = msn_slplink_message_find(slplink, msg->msnslp_header.session_id, msg->msnslp_header.id); - } - - if (slpmsg == NULL) - { - /* Probably the transfer was canceled */ - purple_debug_error("msn", "Couldn't find slpmsg\n"); - return; - } - - if (slpmsg->fp) - { - /* fseek(slpmsg->fp, offset, SEEK_SET); */ - len = fwrite(data, 1, len, slpmsg->fp); - } - else if (slpmsg->size && slpmsg->buffer) - { - if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size) - { - purple_debug_error("msn", "Oversized slpmsg\n"); - g_return_if_reached(); - } - else - memcpy(slpmsg->buffer + offset, data, len); - } - - if ((slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) && - (slpmsg->slpcall != NULL)) - { - slpmsg->slpcall->progress = TRUE; - - if (slpmsg->slpcall->progress_cb != NULL) - { - slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size, - len, offset); - } - } - -#if 0 - if (slpmsg->buffer == NULL) - return; -#endif - - if (msg->msnslp_header.offset + msg->msnslp_header.length - >= msg->msnslp_header.total_size) - { - /* All the pieces of the slpmsg have been received */ - MsnSlpCall *slpcall; - - slpcall = msn_slp_process_msg(slplink, slpmsg); - - if (slpmsg->flags == 0x100) - { - MsnDirectConn *directconn; - - directconn = slplink->directconn; - - if (!directconn->acked) - msn_directconn_send_handshake(directconn); - } - else if (slpmsg->flags == 0x0 || slpmsg->flags == 0x20 || - slpmsg->flags == 0x1000030) - { - /* Release all the messages and send the ACK */ - - msn_slplink_send_ack(slplink, msg); - msn_slplink_unleash(slplink); - } - - msn_slpmsg_destroy(slpmsg); - - if (slpcall != NULL && slpcall->wasted) - msn_slp_call_destroy(slpcall); - } -} - -MsnSlpMessage * -msn_slplink_message_find(MsnSlpLink *slplink, long session_id, long id) -{ - GList *e; - - for (e = slplink->slp_msgs; e != NULL; e = e->next) - { - MsnSlpMessage *slpmsg = e->data; - - if ((slpmsg->session_id == session_id) && (slpmsg->id == id)) - return slpmsg; - } - - return NULL; -} - -typedef struct -{ - guint32 length; - guint32 unk1; - guint32 file_size; - guint32 unk2; - guint32 unk3; -} MsnContextHeader; - -#define MAX_FILE_NAME_LEN 0x226 - -static gchar * -gen_context(const char *file_name, const char *file_path) -{ - struct stat st; - gsize size = 0; - MsnContextHeader header; - gchar *u8 = NULL; - guchar *base; - guchar *n; - gchar *ret; - gunichar2 *uni = NULL; - glong currentChar = 0; - glong uni_len = 0; - gsize len; - - if (g_stat(file_path, &st) == 0) - size = st.st_size; - - if(!file_name) { - u8 = purple_utf8_try_convert(g_basename(file_path)); - file_name = u8; - } - - uni = g_utf8_to_utf16(file_name, -1, NULL, &uni_len, NULL); - - if(u8) { - g_free(u8); - file_name = NULL; - u8 = NULL; - } - - len = sizeof(MsnContextHeader) + MAX_FILE_NAME_LEN + 4; - - header.length = GUINT32_TO_LE(len); - header.unk1 = GUINT32_TO_LE(2); - header.file_size = GUINT32_TO_LE(size); - header.unk2 = GUINT32_TO_LE(0); - header.unk3 = GUINT32_TO_LE(0); - - base = g_malloc(len + 1); - n = base; - - memcpy(n, &header, sizeof(MsnContextHeader)); - n += sizeof(MsnContextHeader); - - memset(n, 0x00, MAX_FILE_NAME_LEN); - for(currentChar = 0; currentChar < uni_len; currentChar++) { - *((gunichar2 *)n + currentChar) = GUINT16_TO_LE(uni[currentChar]); - } - n += MAX_FILE_NAME_LEN; - - memset(n, 0xFF, 4); - n += 4; - - g_free(uni); - ret = purple_base64_encode(base, len); - g_free(base); - return ret; -} - -void -msn_slplink_request_ft(MsnSlpLink *slplink, PurpleXfer *xfer) -{ - MsnSlpCall *slpcall; - char *context; - const char *fn; - const char *fp; - - fn = purple_xfer_get_filename(xfer); - fp = purple_xfer_get_local_filename(xfer); - - g_return_if_fail(slplink != NULL); - g_return_if_fail(fp != NULL); - - slpcall = msn_slp_call_new(slplink); - msn_slp_call_init(slpcall, MSN_SLPCALL_DC); - - slpcall->session_init_cb = send_file_cb; - slpcall->end_cb = msn_xfer_end_cb; - slpcall->progress_cb = msn_xfer_progress_cb; - slpcall->cb = msn_xfer_completed_cb; - slpcall->xfer = xfer; - purple_xfer_ref(slpcall->xfer); - - slpcall->pending = TRUE; - - purple_xfer_set_cancel_send_fnc(xfer, msn_xfer_cancel); - - xfer->data = slpcall; - - context = gen_context(fn, fp); - - msn_slp_call_invite(slpcall, "5D3E02AB-6190-11D3-BBBB-00C04F795683", 2, - context); - - g_free(context); -} - -void -msn_slplink_request_object(MsnSlpLink *slplink, - const char *info, - MsnSlpCb cb, - MsnSlpEndCb end_cb, - const MsnObject *obj) -{ - MsnSlpCall *slpcall; - char *msnobj_data; - char *msnobj_base64; - - g_return_if_fail(slplink != NULL); - g_return_if_fail(obj != NULL); - - msnobj_data = msn_object_to_string(obj); - msnobj_base64 = purple_base64_encode((const guchar *)msnobj_data, strlen(msnobj_data)); - g_free(msnobj_data); - - slpcall = msn_slp_call_new(slplink); - msn_slp_call_init(slpcall, MSN_SLPCALL_ANY); - - slpcall->data_info = g_strdup(info); - slpcall->cb = cb; - slpcall->end_cb = end_cb; - - msn_slp_call_invite(slpcall, "A4268EEC-FEC5-49E5-95C3-F126696BDBF6", 1, - msnobj_base64); - - g_free(msnobj_base64); -}
--- a/libpurple/protocols/msnp9/slplink.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/** - * @file slplink.h MSNSLP Link support - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_SLPLINK_H_ -#define _MSN_SLPLINK_H_ - -typedef struct _MsnSlpLink MsnSlpLink; - -#include "directconn.h" -#include "slpcall.h" -#include "slpmsg.h" - -#include "switchboard.h" - -#include "ft.h" - -#include "session.h" - -typedef void (*MsnSlpCb)(MsnSlpCall *slpcall, - const guchar *data, gsize size); -typedef void (*MsnSlpEndCb)(MsnSlpCall *slpcall, MsnSession *session); - -struct _MsnSlpLink -{ - MsnSession *session; - MsnSwitchBoard *swboard; - - char *local_user; - char *remote_user; - - int slp_seq_id; - - MsnDirectConn *directconn; - - GList *slp_calls; - GList *slp_sessions; - GList *slp_msgs; - - GQueue *slp_msg_queue; -}; - -MsnSlpLink *msn_slplink_new(MsnSession *session, const char *username); -void msn_slplink_destroy(MsnSlpLink *slplink); -MsnSlpLink *msn_session_find_slplink(MsnSession *session, - const char *who); -MsnSlpLink *msn_session_get_slplink(MsnSession *session, const char *username); -MsnSlpSession *msn_slplink_find_slp_session(MsnSlpLink *slplink, - long session_id); -void msn_slplink_add_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall); -void msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall); -MsnSlpCall *msn_slplink_find_slp_call(MsnSlpLink *slplink, - const char *id); -MsnSlpCall *msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id); -void msn_slplink_send_msg(MsnSlpLink *slplink, MsnMessage *msg); -void msn_slplink_release_slpmsg(MsnSlpLink *slplink, - MsnSlpMessage *slpmsg); -void msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg); -void msn_slplink_send_slpmsg(MsnSlpLink *slplink, - MsnSlpMessage *slpmsg); -void msn_slplink_unleash(MsnSlpLink *slplink); -void msn_slplink_send_ack(MsnSlpLink *slplink, MsnMessage *msg); -void msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg); -MsnSlpMessage *msn_slplink_message_find(MsnSlpLink *slplink, long session_id, long id); -void msn_slplink_append_slp_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg); -void msn_slplink_remove_slp_msg(MsnSlpLink *slplink, - MsnSlpMessage *slpmsg); -void msn_slplink_request_ft(MsnSlpLink *slplink, PurpleXfer *xfer); - -void msn_slplink_request_object(MsnSlpLink *slplink, - const char *info, - MsnSlpCb cb, - MsnSlpEndCb end_cb, - const MsnObject *obj); - -MsnSlpCall *msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg); - -#endif /* _MSN_SLPLINK_H_ */
--- a/libpurple/protocols/msnp9/slpmsg.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,239 +0,0 @@ -/** - * @file slpmsg.h SLP Message functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "slpmsg.h" -#include "slplink.h" - -/************************************************************************** - * SLP Message - **************************************************************************/ - -MsnSlpMessage * -msn_slpmsg_new(MsnSlpLink *slplink) -{ - MsnSlpMessage *slpmsg; - - slpmsg = g_new0(MsnSlpMessage, 1); - -#ifdef MSN_DEBUG_SLPMSG - purple_debug_info("msn", "slpmsg new (%p)\n", slpmsg); -#endif - - slpmsg->slplink = slplink; - - slplink->slp_msgs = - g_list_append(slplink->slp_msgs, slpmsg); - - return slpmsg; -} - -void -msn_slpmsg_destroy(MsnSlpMessage *slpmsg) -{ - MsnSlpLink *slplink; - GList *cur; - - g_return_if_fail(slpmsg != NULL); - -#ifdef MSN_DEBUG_SLPMSG - purple_debug_info("msn", "slpmsg destroy (%p)\n", slpmsg); -#endif - - slplink = slpmsg->slplink; - - if (slpmsg->fp != NULL) - fclose(slpmsg->fp); - - purple_imgstore_unref(slpmsg->img); - - /* We don't want to free the data of the PurpleStoredImage, - * but to avoid code duplication, it's sharing buffer. */ - if (slpmsg->img == NULL) - g_free(slpmsg->buffer); - -#ifdef MSN_DEBUG_SLP - /* - if (slpmsg->info != NULL) - g_free(slpmsg->info); - */ -#endif - - for (cur = slpmsg->msgs; cur != NULL; cur = cur->next) - { - /* Something is pointing to this slpmsg, so we should remove that - * pointer to prevent a crash. */ - /* Ex: a user goes offline and after that we receive an ACK */ - - MsnMessage *msg = cur->data; - -#ifdef MSN_DEBUG_SLPMSG - purple_debug_info("msn", "Unlink slpmsg callbacks.\n"); -#endif - - msg->ack_cb = NULL; - msg->nak_cb = NULL; - msg->ack_data = NULL; - } - - slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg); - - g_free(slpmsg); -} - -void -msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body, - long long size) -{ - /* We can only have one data source at a time. */ - g_return_if_fail(slpmsg->buffer == NULL); - g_return_if_fail(slpmsg->img == NULL); - g_return_if_fail(slpmsg->fp == NULL); - - if (body != NULL) - slpmsg->buffer = g_memdup(body, size); - else - slpmsg->buffer = g_new0(guchar, size); - - slpmsg->size = size; -} - -void -msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img) -{ - /* We can only have one data source at a time. */ - g_return_if_fail(slpmsg->buffer == NULL); - g_return_if_fail(slpmsg->img == NULL); - g_return_if_fail(slpmsg->fp == NULL); - - slpmsg->img = purple_imgstore_ref(img); - slpmsg->buffer = (guchar *)purple_imgstore_get_data(img); - slpmsg->size = purple_imgstore_get_size(img); -} - -void -msn_slpmsg_open_file(MsnSlpMessage *slpmsg, const char *file_name) -{ - struct stat st; - - /* We can only have one data source at a time. */ - g_return_if_fail(slpmsg->buffer == NULL); - g_return_if_fail(slpmsg->img == NULL); - g_return_if_fail(slpmsg->fp == NULL); - - slpmsg->fp = g_fopen(file_name, "rb"); - - if (g_stat(file_name, &st) == 0) - slpmsg->size = st.st_size; -} - -#ifdef MSN_DEBUG_SLP -void -msn_slpmsg_show(MsnMessage *msg) -{ - const char *info; - gboolean text; - guint32 flags; - - text = FALSE; - - flags = GUINT32_TO_LE(msg->msnslp_header.flags); - - switch (flags) - { - case 0x0: - info = "SLP CONTROL"; - text = TRUE; - break; - case 0x2: - info = "SLP ACK"; break; - case 0x20: - case 0x1000030: - info = "SLP DATA"; break; - default: - info = "SLP UNKNOWN"; break; - } - - msn_message_show_readable(msg, info, text); -} -#endif - -MsnSlpMessage * -msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq, - const char *header, const char *branch, - const char *content_type, const char *content) -{ - MsnSlpLink *slplink; - MsnSlpMessage *slpmsg; - char *body; - gsize body_len; - gsize content_len; - - g_return_val_if_fail(slpcall != NULL, NULL); - g_return_val_if_fail(header != NULL, NULL); - - slplink = slpcall->slplink; - - /* Let's remember that "content" should end with a 0x00 */ - - content_len = (content != NULL) ? strlen(content) + 1 : 0; - - body = g_strdup_printf( - "%s\r\n" - "To: <msnmsgr:%s>\r\n" - "From: <msnmsgr:%s>\r\n" - "Via: MSNSLP/1.0/TLP ;branch={%s}\r\n" - "CSeq: %d\r\n" - "Call-ID: {%s}\r\n" - "Max-Forwards: 0\r\n" - "Content-Type: %s\r\n" - "Content-Length: %" G_GSIZE_FORMAT "\r\n" - "\r\n", - header, - slplink->remote_user, - slplink->local_user, - branch, - cseq, - slpcall->id, - content_type, - content_len); - - body_len = strlen(body); - - if (content_len > 0) - { - body_len += content_len; - body = g_realloc(body, body_len); - g_strlcat(body, content, body_len); - } - - slpmsg = msn_slpmsg_new(slplink); - msn_slpmsg_set_body(slpmsg, body, body_len); - - slpmsg->sip = TRUE; - slpmsg->slpcall = slpcall; - - g_free(body); - - return slpmsg; -}
--- a/libpurple/protocols/msnp9/slpmsg.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -/** - * @file slpmsg.h SLP Message functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_SLPMSG_H_ -#define _MSN_SLPMSG_H_ - -typedef struct _MsnSlpMessage MsnSlpMessage; - -#include "imgstore.h" - -#include "slpsession.h" -#include "slpcall.h" -#include "slplink.h" -#include "session.h" -#include "msg.h" - -#include "slp.h" - -/** - * A SLP Message This contains everything that we will need to send a SLP - * Message even if has to be sent in several parts. - */ -struct _MsnSlpMessage -{ - MsnSlpSession *slpsession; - MsnSlpCall *slpcall; /**< The slpcall to which this slp message belongs (if applicable). */ - MsnSlpLink *slplink; /**< The slplink through which this slp message is being sent. */ - MsnSession *session; - - long session_id; - long id; - long ack_id; - long ack_sub_id; - long long ack_size; - long app_id; - - gboolean sip; /**< A flag that states if this is a SIP slp message. */ - int ref_count; /**< The reference count. */ - long flags; - - FILE *fp; - PurpleStoredImage *img; - guchar *buffer; - long long offset; - long long size; - - GList *msgs; /**< The real messages. */ - -#if 1 - MsnMessage *msg; /**< The temporary real message that will be sent. */ -#endif - -#ifdef MSN_DEBUG_SLP - char *info; - gboolean text_body; -#endif -}; - -/** - * Creates a new slp message - * - * @param slplink The slplink through which this slp message will be sent. - * @return The created slp message. - */ -MsnSlpMessage *msn_slpmsg_new(MsnSlpLink *slplink); - -/** - * Destroys a slp message - * - * @param slpmsg The slp message to destory. - */ -void msn_slpmsg_destroy(MsnSlpMessage *slpmsg); - -void msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body, - long long size); -void msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img); -void msn_slpmsg_open_file(MsnSlpMessage *slpmsg, - const char *file_name); -MsnSlpMessage * msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq, - const char *header, - const char *branch, - const char *content_type, - const char *content); - -#ifdef MSN_DEBUG_SLP -void msn_slpmsg_show(MsnMessage *msg); -#endif - -#endif /* _MSN_SLPMSG_H_ */
--- a/libpurple/protocols/msnp9/slpsession.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/** - * @file slpsession.h SLP Session functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "slpsession.h" - -/************************************************************************** - * SLP Session - **************************************************************************/ - -MsnSlpSession * -msn_slp_session_new(MsnSlpCall *slpcall) -{ - MsnSlpSession *slpsession; - - g_return_val_if_fail(slpcall != NULL, NULL); - - slpsession = g_new0(MsnSlpSession, 1); - - slpsession->slpcall = slpcall; - slpsession->id = slpcall->session_id; - slpsession->call_id = slpcall->id; - slpsession->app_id = slpcall->app_id; - - slpcall->slplink->slp_sessions = - g_list_append(slpcall->slplink->slp_sessions, slpsession); - - return slpsession; -} - -void -msn_slp_session_destroy(MsnSlpSession *slpsession) -{ - g_return_if_fail(slpsession != NULL); - - if (slpsession->call_id != NULL) - g_free(slpsession->call_id); - - slpsession->slpcall->slplink->slp_sessions = - g_list_remove(slpsession->slpcall->slplink->slp_sessions, slpsession); - - g_free(slpsession); -} - -#if 0 -static void -msn_slp_session_send_slpmsg(MsnSlpSession *slpsession, MsnSlpMessage *slpmsg) -{ - slpmsg->slpsession = slpsession; - -#if 0 - slpmsg->session_id = slpsession->id; - slpmsg->app_id = slpsession->app_id; -#endif - - msn_slplink_send_slpmsg(slpsession->slpcall->slplink, slpmsg); -} -#endif
--- a/libpurple/protocols/msnp9/slpsession.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/** - * @file slpsession.h SLP Session functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_SLPSESSION_H_ -#define _MSN_SLPSESSION_H_ - -typedef struct _MsnSlpSession MsnSlpSession; - -#include "slpcall.h" -#include "slpsession.h" -#include "slpmsg.h" - -struct _MsnSlpSession -{ - /* MsnSlpLink *slplink; */ - MsnSlpCall *slpcall; - - long id; - - long app_id; - char *call_id; -}; - -MsnSlpSession *msn_slp_session_new(MsnSlpCall *slpcall); -void msn_slp_session_destroy(MsnSlpSession *slpsession); -void msn_slpsession_send_slpmsg(MsnSlpSession *slpsession, - MsnSlpMessage *slpmsg); -#endif /* _MSN_SLPSESSION_H_ */
--- a/libpurple/protocols/msnp9/state.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/** - * @file state.c State functions and definitions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "state.h" - -static const char *away_text[] = -{ - N_("Available"), - N_("Available"), - N_("Busy"), - N_("Idle"), - N_("Be Right Back"), - N_("Away From Computer"), - N_("On The Phone"), - N_("Out To Lunch"), - N_("Available"), - N_("Available") -}; - -void -msn_change_status(MsnSession *session) -{ - PurpleAccount *account; - MsnCmdProc *cmdproc; - MsnUser *user; - MsnObject *msnobj; - const char *state_text; - - g_return_if_fail(session != NULL); - g_return_if_fail(session->notification != NULL); - - account = session->account; - cmdproc = session->notification->cmdproc; - user = session->user; - state_text = msn_state_get_text(msn_state_from_account(account)); - - /* If we're not logged in yet, don't send the status to the server, - * it will be sent when login completes - */ - if (!session->logged_in) - return; - - msnobj = msn_user_get_object(user); - - if (msnobj == NULL) - { - msn_cmdproc_send(cmdproc, "CHG", "%s %d", state_text, - MSN_CLIENT_ID); - } - else - { - char *msnobj_str; - - msnobj_str = msn_object_to_string(msnobj); - - msn_cmdproc_send(cmdproc, "CHG", "%s %d %s", state_text, - MSN_CLIENT_ID, purple_url_encode(msnobj_str)); - - g_free(msnobj_str); - } -} - -const char * -msn_away_get_text(MsnAwayType type) -{ - g_return_val_if_fail(type <= MSN_HIDDEN, NULL); - - return _(away_text[type]); -} - -const char * -msn_state_get_text(MsnAwayType state) -{ - static char *status_text[] = - { "NLN", "NLN", "BSY", "IDL", "BRB", "AWY", "PHN", "LUN", "HDN", "HDN" }; - - return status_text[state]; -} - -MsnAwayType -msn_state_from_account(PurpleAccount *account) -{ - MsnAwayType msnstatus; - PurplePresence *presence; - PurpleStatus *status; - const char *status_id; - - presence = purple_account_get_presence(account); - status = purple_presence_get_active_status(presence); - status_id = purple_status_get_id(status); - - if (!strcmp(status_id, "away")) - msnstatus = MSN_AWAY; - else if (!strcmp(status_id, "brb")) - msnstatus = MSN_BRB; - else if (!strcmp(status_id, "busy")) - msnstatus = MSN_BUSY; - else if (!strcmp(status_id, "phone")) - msnstatus = MSN_PHONE; - else if (!strcmp(status_id, "lunch")) - msnstatus = MSN_LUNCH; - else if (!strcmp(status_id, "invisible")) - msnstatus = MSN_HIDDEN; - else - msnstatus = MSN_ONLINE; - - if ((msnstatus == MSN_ONLINE) && purple_presence_is_idle(presence)) - msnstatus = MSN_IDLE; - - return msnstatus; -}
--- a/libpurple/protocols/msnp9/state.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/** - * @file state.h State functions and definitions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_STATE_H_ -#define _MSN_STATE_H_ - -/** - * Away types. - */ -typedef enum -{ - MSN_ONLINE = 1, - MSN_BUSY = 2, - MSN_IDLE = 3, - MSN_BRB = 4, - MSN_AWAY = 5, - MSN_PHONE = 6, - MSN_LUNCH = 7, - MSN_OFFLINE = 8, - MSN_HIDDEN = 9 - -} MsnAwayType; - -/** - * Changes the status of the user. - * - * @param session The MSN session. - */ -void msn_change_status(MsnSession *session); - -/** - * Returns the string representation of an away type. - * - * @param type The away type. - * - * @return The string representation of the away type. - */ -const char *msn_away_get_text(MsnAwayType type); - -const char *msn_state_get_text(MsnAwayType state); - -MsnAwayType msn_state_from_account(PurpleAccount *account); - -#endif /* _MSN_STATE_H_ */
--- a/libpurple/protocols/msnp9/switchboard.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1305 +0,0 @@ -/** - * @file switchboard.c MSN switchboard functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "prefs.h" -#include "switchboard.h" -#include "notification.h" -#include "msn-utils.h" - -#include "error.h" - -static MsnTable *cbs_table; - -static void msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, - MsnMsgErrorType error); - -/************************************************************************** - * Main - **************************************************************************/ - -MsnSwitchBoard * -msn_switchboard_new(MsnSession *session) -{ - MsnSwitchBoard *swboard; - MsnServConn *servconn; - - g_return_val_if_fail(session != NULL, NULL); - - swboard = g_new0(MsnSwitchBoard, 1); - - swboard->session = session; - swboard->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_SB); - swboard->cmdproc = servconn->cmdproc; - - swboard->msg_queue = g_queue_new(); - swboard->empty = TRUE; - - swboard->cmdproc->data = swboard; - swboard->cmdproc->cbs_table = cbs_table; - - session->switches = g_list_append(session->switches, swboard); - - return swboard; -} - -void -msn_switchboard_destroy(MsnSwitchBoard *swboard) -{ - MsnSession *session; - MsnMessage *msg; - GList *l; - -#ifdef MSN_DEBUG_SB - purple_debug_info("msn", "switchboard_destroy: swboard(%p)\n", swboard); -#endif - - g_return_if_fail(swboard != NULL); - - if (swboard->destroying) - return; - - swboard->destroying = TRUE; - - /* If it linked us is because its looking for trouble */ - while (swboard->slplinks != NULL) - msn_slplink_destroy(swboard->slplinks->data); - - /* Destroy the message queue */ - while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL) - { - if (swboard->error != MSN_SB_ERROR_NONE) - { - /* The messages could not be sent due to a switchboard error */ - msg_error_helper(swboard->cmdproc, msg, - MSN_MSG_ERROR_SB); - } - msn_message_unref(msg); - } - - g_queue_free(swboard->msg_queue); - - /* msg_error_helper will both remove the msg from ack_list and - unref it, so we don't need to do either here */ - while ((l = swboard->ack_list) != NULL) - msg_error_helper(swboard->cmdproc, l->data, MSN_MSG_ERROR_SB); - - g_free(swboard->im_user); - g_free(swboard->auth_key); - g_free(swboard->session_id); - - for (l = swboard->users; l != NULL; l = l->next) - g_free(l->data); - - if (swboard->users != NULL) - g_list_free(swboard->users); - - session = swboard->session; - session->switches = g_list_remove(session->switches, swboard); - -#if 0 - /* This should never happen or we are in trouble. */ - if (swboard->servconn != NULL) - msn_servconn_destroy(swboard->servconn); -#endif - - swboard->cmdproc->data = NULL; - - msn_servconn_set_disconnect_cb(swboard->servconn, NULL); - - msn_servconn_destroy(swboard->servconn); - - g_free(swboard); -} - -void -msn_switchboard_set_auth_key(MsnSwitchBoard *swboard, const char *key) -{ - g_return_if_fail(swboard != NULL); - g_return_if_fail(key != NULL); - - swboard->auth_key = g_strdup(key); -} - -const char * -msn_switchboard_get_auth_key(MsnSwitchBoard *swboard) -{ - g_return_val_if_fail(swboard != NULL, NULL); - - return swboard->auth_key; -} - -void -msn_switchboard_set_session_id(MsnSwitchBoard *swboard, const char *id) -{ - g_return_if_fail(swboard != NULL); - g_return_if_fail(id != NULL); - - if (swboard->session_id != NULL) - g_free(swboard->session_id); - - swboard->session_id = g_strdup(id); -} - -const char * -msn_switchboard_get_session_id(MsnSwitchBoard *swboard) -{ - g_return_val_if_fail(swboard != NULL, NULL); - - return swboard->session_id; -} - -int -msn_switchboard_get_chat_id(void) -{ - static int chat_id = 1; - - return chat_id++; -} - -void -msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited) -{ - g_return_if_fail(swboard != NULL); - - swboard->invited = invited; -} - -gboolean -msn_switchboard_is_invited(MsnSwitchBoard *swboard) -{ - g_return_val_if_fail(swboard != NULL, FALSE); - - return swboard->invited; -} - -/************************************************************************** - * Utility - **************************************************************************/ - -static void -send_clientcaps(MsnSwitchBoard *swboard) -{ - MsnMessage *msg; - - msg = msn_message_new(MSN_MSG_CAPS); - msn_message_set_content_type(msg, "text/x-clientcaps"); - msn_message_set_flag(msg, 'U'); - msn_message_set_bin_data(msg, MSN_CLIENTINFO, strlen(MSN_CLIENTINFO)); - - msn_switchboard_send_msg(swboard, msg, TRUE); - - msn_message_destroy(msg); -} - -static void -msn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user) -{ - MsnCmdProc *cmdproc; - PurpleAccount *account; - - g_return_if_fail(swboard != NULL); - - cmdproc = swboard->cmdproc; - account = cmdproc->session->account; - - swboard->users = g_list_prepend(swboard->users, g_strdup(user)); - swboard->current_users++; - swboard->empty = FALSE; - -#ifdef MSN_DEBUG_CHAT - purple_debug_info("msn", "user=[%s], total=%d\n", user, - swboard->current_users); -#endif - - if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL)) - { - /* This is a helper switchboard. */ - purple_debug_error("msn", "switchboard_add_user: conv != NULL\n"); - return; - } - - if ((swboard->conv != NULL) && - (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) - { - purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), user, NULL, - PURPLE_CBFLAGS_NONE, TRUE); - } - else if (swboard->current_users > 1 || swboard->total_users > 1) - { - if (swboard->conv == NULL || - purple_conversation_get_type(swboard->conv) != PURPLE_CONV_TYPE_CHAT) - { - GList *l; - -#ifdef MSN_DEBUG_CHAT - purple_debug_info("msn", "[chat] Switching to chat.\n"); -#endif - -#if 0 - /* this is bad - it causes msn_switchboard_close to be called on the - * switchboard we're in the middle of using :( */ - if (swboard->conv != NULL) - purple_conversation_destroy(swboard->conv); -#endif - - swboard->chat_id = msn_switchboard_get_chat_id(); - swboard->flag |= MSN_SB_FLAG_IM; - swboard->conv = serv_got_joined_chat(account->gc, - swboard->chat_id, - "MSN Chat"); - - for (l = swboard->users; l != NULL; l = l->next) - { - const char *tmp_user; - - tmp_user = l->data; - -#ifdef MSN_DEBUG_CHAT - purple_debug_info("msn", "[chat] Adding [%s].\n", tmp_user); -#endif - - purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), - tmp_user, NULL, PURPLE_CBFLAGS_NONE, TRUE); - } - -#ifdef MSN_DEBUG_CHAT - purple_debug_info("msn", "[chat] We add ourselves.\n"); -#endif - - purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), - purple_account_get_username(account), - NULL, PURPLE_CBFLAGS_NONE, TRUE); - - g_free(swboard->im_user); - swboard->im_user = NULL; - } - } - else if (swboard->conv == NULL) - { - swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - user, account); - } - else - { - purple_debug_warning("msn", "switchboard_add_user: This should not happen!\n"); - } -} - -static PurpleConversation * -msn_switchboard_get_conv(MsnSwitchBoard *swboard) -{ - PurpleAccount *account; - - g_return_val_if_fail(swboard != NULL, NULL); - - if (swboard->conv != NULL) - return swboard->conv; - - purple_debug_error("msn", "Switchboard with unassigned conversation\n"); - - account = swboard->session->account; - - return (swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, - account, swboard->im_user)); -} - -static void -msn_switchboard_report_user(MsnSwitchBoard *swboard, PurpleMessageFlags flags, const char *msg) -{ - PurpleConversation *conv; - - g_return_if_fail(swboard != NULL); - g_return_if_fail(msg != NULL); - - if ((conv = msn_switchboard_get_conv(swboard)) != NULL) - { - purple_conversation_write(conv, NULL, msg, flags, time(NULL)); - } -} - -static void -swboard_error_helper(MsnSwitchBoard *swboard, int reason, const char *passport) -{ - g_return_if_fail(swboard != NULL); - - purple_debug_warning("msg", "Error: Unable to call the user %s for reason %i\n", - passport ? passport : "(null)", reason); - - /* TODO: if current_users > 0, this is probably a chat and an invite failed, - * we should report that in the chat or something */ - if (swboard->current_users == 0) - { - swboard->error = reason; - msn_switchboard_close(swboard); - } -} - -static void -cal_error_helper(MsnTransaction *trans, int reason) -{ - MsnSwitchBoard *swboard; - const char *passport; - char **params; - - params = g_strsplit(trans->params, " ", 0); - - passport = params[0]; - - swboard = trans->data; - - purple_debug_warning("msn", "cal_error_helper: command %s failed for reason %i\n",trans->command,reason); - - swboard_error_helper(swboard, reason, passport); - - g_strfreev(params); -} - -static void -msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error) -{ - MsnSwitchBoard *swboard; - - g_return_if_fail(cmdproc != NULL); - g_return_if_fail(msg != NULL); - - if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL)) - msg->nak_cb(msg, msg->ack_data); - - swboard = cmdproc->data; - - /* This is not good, and should be fixed somewhere else. */ - g_return_if_fail(swboard != NULL); - - if (msg->type == MSN_MSG_TEXT) - { - const char *format, *str_reason; - char *body_str, *body_enc, *pre, *post; - -#if 0 - if (swboard->conv == NULL) - { - if (msg->ack_ref) - msn_message_unref(msg); - - return; - } -#endif - - if (error == MSN_MSG_ERROR_TIMEOUT) - { - str_reason = _("Message may have not been sent " - "because a timeout occurred:"); - } - else if (error == MSN_MSG_ERROR_SB) - { - switch (swboard->error) - { - case MSN_SB_ERROR_OFFLINE: - str_reason = _("Message could not be sent, " - "not allowed while invisible:"); - break; - case MSN_SB_ERROR_USER_OFFLINE: - str_reason = _("Message could not be sent " - "because the user is offline:"); - break; - case MSN_SB_ERROR_CONNECTION: - str_reason = _("Message could not be sent " - "because a connection error occurred:"); - break; - case MSN_SB_ERROR_TOO_FAST: - str_reason = _("Message could not be sent " - "because we are sending too quickly:"); - break; - case MSN_SB_ERROR_AUTHFAILED: - str_reason = _("Message could not be sent " - "because we were unable to establish a " - "session with the server. This is " - "likely a server problem, try again in " - "a few minutes:"); - break; - default: - str_reason = _("Message could not be sent " - "because an error with " - "the switchboard occurred:"); - break; - } - } - else - { - str_reason = _("Message may have not been sent " - "because an unknown error occurred:"); - } - - body_str = msn_message_to_string(msg); - body_enc = g_markup_escape_text(body_str, -1); - g_free(body_str); - - format = msn_message_get_attr(msg, "X-MMS-IM-Format"); - msn_parse_format(format, &pre, &post); - body_str = g_strdup_printf("%s%s%s", pre ? pre : "", - body_enc ? body_enc : "", post ? post : ""); - g_free(body_enc); - g_free(pre); - g_free(post); - - msn_switchboard_report_user(swboard, PURPLE_MESSAGE_ERROR, - str_reason); - msn_switchboard_report_user(swboard, PURPLE_MESSAGE_RAW, - body_str); - - g_free(body_str); - } - - /* If a timeout occures we will want the msg around just in case we - * receive the ACK after the timeout. */ - if (msg->ack_ref && error != MSN_MSG_ERROR_TIMEOUT) - { - swboard->ack_list = g_list_remove(swboard->ack_list, msg); - msn_message_unref(msg); - } -} - -/************************************************************************** - * Message Stuff - **************************************************************************/ - -/** Called when a message times out. */ -static void -msg_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans) -{ - MsnMessage *msg; - - msg = trans->data; - - msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_TIMEOUT); -} - -/** Called when we receive an error of a message. */ -static void -msg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) -{ - msg_error_helper(cmdproc, trans->data, MSN_MSG_ERROR_UNKNOWN); -} - -#if 0 -/** Called when we receive an ack of a special message. */ -static void -msg_ack(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnMessage *msg; - - msg = cmd->trans->data; - - if (msg->ack_cb != NULL) - msg->ack_cb(msg->ack_data); - - msn_message_unref(msg); -} - -/** Called when we receive a nak of a special message. */ -static void -msg_nak(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnMessage *msg; - - msg = cmd->trans->data; - - msn_message_unref(msg); -} -#endif - -static void -release_msg(MsnSwitchBoard *swboard, MsnMessage *msg) -{ - MsnCmdProc *cmdproc; - MsnTransaction *trans; - char *payload; - gsize payload_len; - - g_return_if_fail(swboard != NULL); - g_return_if_fail(msg != NULL); - - cmdproc = swboard->cmdproc; - - payload = msn_message_gen_payload(msg, &payload_len); - -#ifdef MSN_DEBUG_SB - msn_message_show_readable(msg, "SB SEND", FALSE); -#endif - - trans = msn_transaction_new(cmdproc, "MSG", "%c %d", - msn_message_get_flag(msg), payload_len); - - /* Data for callbacks */ - msn_transaction_set_data(trans, msg); - - if (msg->type == MSN_MSG_TEXT) - { - msg->ack_ref = TRUE; - msn_message_ref(msg); - swboard->ack_list = g_list_append(swboard->ack_list, msg); - msn_transaction_set_timeout_cb(trans, msg_timeout); - } - else if (msg->type == MSN_MSG_SLP) - { - msg->ack_ref = TRUE; - msn_message_ref(msg); - swboard->ack_list = g_list_append(swboard->ack_list, msg); - msn_transaction_set_timeout_cb(trans, msg_timeout); -#if 0 - if (msg->ack_cb != NULL) - { - msn_transaction_add_cb(trans, "ACK", msg_ack); - msn_transaction_add_cb(trans, "NAK", msg_nak); - } -#endif - } - - trans->payload = payload; - trans->payload_len = payload_len; - - msg->trans = trans; - - msn_cmdproc_send_trans(cmdproc, trans); -} - -static void -queue_msg(MsnSwitchBoard *swboard, MsnMessage *msg) -{ - g_return_if_fail(swboard != NULL); - g_return_if_fail(msg != NULL); - - purple_debug_info("msn", "Appending message to queue.\n"); - - g_queue_push_tail(swboard->msg_queue, msg); - - msn_message_ref(msg); -} - -static void -process_queue(MsnSwitchBoard *swboard) -{ - MsnMessage *msg; - - g_return_if_fail(swboard != NULL); - - purple_debug_info("msn", "Processing queue\n"); - - while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL) - { - purple_debug_info("msn", "Sending message\n"); - release_msg(swboard, msg); - msn_message_unref(msg); - } -} - -gboolean -msn_switchboard_can_send(MsnSwitchBoard *swboard) -{ - g_return_val_if_fail(swboard != NULL, FALSE); - - if (swboard->empty || !g_queue_is_empty(swboard->msg_queue)) - return FALSE; - - return TRUE; -} - -void -msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg, - gboolean queue) -{ - g_return_if_fail(swboard != NULL); - g_return_if_fail(msg != NULL); - - if (msn_switchboard_can_send(swboard)) - release_msg(swboard, msg); - else if (queue) - queue_msg(swboard, msg); -} - -/************************************************************************** - * Switchboard Commands - **************************************************************************/ - -static void -ans_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSwitchBoard *swboard; - - swboard = cmdproc->data; - swboard->ready = TRUE; -} - -static void -bye_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSwitchBoard *swboard; - const char *user; - - swboard = cmdproc->data; - user = cmd->params[0]; - - /* cmdproc->data is set to NULL when the switchboard is destroyed; - * we may get a bye shortly thereafter. */ - g_return_if_fail(swboard != NULL); - - if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL)) - purple_debug_error("msn_switchboard", "bye_cmd: helper bug\n"); - - if (swboard->conv == NULL) - { - /* This is a helper switchboard */ - msn_switchboard_destroy(swboard); - } - else if ((swboard->current_users > 1) || - (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) - { - /* This is a switchboard used for a chat */ - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(swboard->conv), user, NULL); - swboard->current_users--; - if (swboard->current_users == 0) - msn_switchboard_destroy(swboard); - } - else - { - /* This is a switchboard used for a im session */ - msn_switchboard_destroy(swboard); - } -} - -static void -iro_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - PurpleAccount *account; - PurpleConnection *gc; - MsnSwitchBoard *swboard; - - account = cmdproc->session->account; - gc = account->gc; - swboard = cmdproc->data; - - swboard->total_users = atoi(cmd->params[2]); - - msn_switchboard_add_user(swboard, cmd->params[3]); -} - -static void -joi_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session; - PurpleAccount *account; - PurpleConnection *gc; - MsnSwitchBoard *swboard; - const char *passport; - - passport = cmd->params[0]; - - session = cmdproc->session; - account = session->account; - gc = account->gc; - swboard = cmdproc->data; - - msn_switchboard_add_user(swboard, passport); - - process_queue(swboard); - - if (!session->http_method) - send_clientcaps(swboard); - - if (swboard->closed) - msn_switchboard_close(swboard); -} - -static void -msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len) -{ - MsnMessage *msg; - - msg = msn_message_new_from_cmd(cmdproc->session, cmd); - - msn_message_parse_payload(msg, payload, len); -#ifdef MSN_DEBUG_SB - msn_message_show_readable(msg, "SB RECV", FALSE); -#endif - - if (msg->remote_user != NULL) - g_free (msg->remote_user); - - msg->remote_user = g_strdup(cmd->params[0]); - msn_cmdproc_process_msg(cmdproc, msg); - - msn_message_destroy(msg); -} - -static void -msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - cmdproc->servconn->payload_len = atoi(cmd->params[2]); - cmdproc->last_cmd->payload_cb = msg_cmd_post; -} - -static void -nak_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnMessage *msg; - - msg = cmd->trans->data; - g_return_if_fail(msg != NULL); - - msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_NAK); -} - -static void -ack_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSwitchBoard *swboard; - MsnMessage *msg; - - msg = cmd->trans->data; - - if (msg->ack_cb != NULL) - msg->ack_cb(msg, msg->ack_data); - - swboard = cmdproc->data; - if (swboard) - swboard->ack_list = g_list_remove(swboard->ack_list, msg); - msn_message_unref(msg); -} - -static void -out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - PurpleConnection *gc; - MsnSwitchBoard *swboard; - - gc = cmdproc->session->account->gc; - swboard = cmdproc->data; - - if (swboard->current_users > 1) - serv_got_chat_left(gc, swboard->chat_id); - - msn_switchboard_disconnect(swboard); -} - -static void -usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSwitchBoard *swboard; - - swboard = cmdproc->data; - -#if 0 - GList *l; - - for (l = swboard->users; l != NULL; l = l->next) - { - const char *user; - user = l->data; - - msn_cmdproc_send(cmdproc, "CAL", "%s", user); - } -#endif - - swboard->ready = TRUE; - msn_cmdproc_process_queue(cmdproc); -} - -/************************************************************************** - * Message Handlers - **************************************************************************/ -static void -plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - PurpleConnection *gc; - MsnSwitchBoard *swboard; - const char *body; - char *body_str; - char *body_enc; - char *body_final; - size_t body_len; - const char *passport; - const char *value; - - gc = cmdproc->session->account->gc; - swboard = cmdproc->data; - - body = msn_message_get_bin_data(msg, &body_len); - body_str = g_strndup(body, body_len); - body_enc = g_markup_escape_text(body_str, -1); - g_free(body_str); - - passport = msg->remote_user; - - if (!strcmp(passport, "messenger@microsoft.com") && - strstr(body, "immediate security update")) - { - return; - } - -#if 0 - if ((value = msn_message_get_attr(msg, "User-Agent")) != NULL) - { - purple_debug_misc("msn", "User-Agent = '%s'\n", value); - } -#endif - - if ((value = msn_message_get_attr(msg, "X-MMS-IM-Format")) != NULL) - { - char *pre, *post; - - msn_parse_format(value, &pre, &post); - - body_final = g_strdup_printf("%s%s%s", pre ? pre : "", - body_enc ? body_enc : "", post ? post : ""); - - g_free(pre); - g_free(post); - g_free(body_enc); - } - else - { - body_final = body_enc; - } - - swboard->flag |= MSN_SB_FLAG_IM; - - if (swboard->current_users > 1 || - ((swboard->conv != NULL) && - purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) - { - /* If current_users is always ok as it should then there is no need to - * check if this is a chat. */ - if (swboard->current_users <= 1) - purple_debug_misc("msn", "plain_msg: current_users(%d)\n", - swboard->current_users); - - serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final, - time(NULL)); - if (swboard->conv == NULL) - { - swboard->conv = purple_find_chat(gc, swboard->chat_id); - swboard->flag |= MSN_SB_FLAG_IM; - } - } - else - { - serv_got_im(gc, passport, body_final, 0, time(NULL)); - if (swboard->conv == NULL) - { - swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - passport, purple_connection_get_account(gc)); - swboard->flag |= MSN_SB_FLAG_IM; - } - } - - g_free(body_final); -} - -static void -control_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - PurpleConnection *gc; - MsnSwitchBoard *swboard; - char *passport; - - gc = cmdproc->session->account->gc; - swboard = cmdproc->data; - passport = msg->remote_user; - - if (swboard->current_users == 1 && - msn_message_get_attr(msg, "TypingUser") != NULL) - { - serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT, - PURPLE_TYPING); - } -} - -static void -clientcaps_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ -#if 0 - MsnSession *session; - MsnSwitchBoard *swboard; - MsnUser *user; - GHashTable *clientcaps; - const char *value; - - char *passport = msg->sender; - - session = cmdproc->session; - swboard = cmdproc->servconn->swboard; - - clientcaps = msn_message_get_hashtable_from_body(msg); -#endif -} - -static void -nudge_msg(MsnCmdProc *cmdproc, MsnMessage *msg) -{ - MsnSwitchBoard *swboard; - PurpleAccount *account; - const char *user; - - swboard = cmdproc->data; - account = cmdproc->session->account; - user = msg->remote_user; - - serv_got_attention(account->gc, user, MSN_NUDGE); -} - -/************************************************************************** - * Connect stuff - **************************************************************************/ -static void -ans_usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error); - -static void -connect_cb(MsnServConn *servconn) -{ - MsnSwitchBoard *swboard; - MsnTransaction *trans; - MsnCmdProc *cmdproc; - PurpleAccount *account; - - cmdproc = servconn->cmdproc; - g_return_if_fail(cmdproc != NULL); - - account = cmdproc->session->account; - swboard = cmdproc->data; - g_return_if_fail(swboard != NULL); - - if (msn_switchboard_is_invited(swboard)) - { - swboard->empty = FALSE; - - trans = msn_transaction_new(cmdproc, "ANS", "%s %s %s", - purple_account_get_username(account), - swboard->auth_key, swboard->session_id); - } - else - { - trans = msn_transaction_new(cmdproc, "USR", "%s %s", - purple_account_get_username(account), - swboard->auth_key); - } - - msn_transaction_set_error_cb(trans, ans_usr_error); - msn_transaction_set_data(trans, swboard); - msn_cmdproc_send_trans(cmdproc, trans); -} - -static void -ans_usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) -{ - MsnSwitchBoard *swboard; - char **params; - char *passport; - int reason = MSN_SB_ERROR_UNKNOWN; - - if (error == 911) - { - reason = MSN_SB_ERROR_AUTHFAILED; - } - - purple_debug_warning("msn", "ans_usr_error: command %s gave error %i\n", trans->command, error); - - params = g_strsplit(trans->params, " ", 0); - passport = params[0]; - swboard = trans->data; - - swboard_error_helper(swboard, reason, passport); - - g_strfreev(params); -} - -static void -disconnect_cb(MsnServConn *servconn) -{ - MsnSwitchBoard *swboard; - - swboard = servconn->cmdproc->data; - g_return_if_fail(swboard != NULL); - - msn_servconn_set_disconnect_cb(swboard->servconn, NULL); - - msn_switchboard_destroy(swboard); -} - -gboolean -msn_switchboard_connect(MsnSwitchBoard *swboard, const char *host, int port) -{ - g_return_val_if_fail(swboard != NULL, FALSE); - - msn_servconn_set_connect_cb(swboard->servconn, connect_cb); - msn_servconn_set_disconnect_cb(swboard->servconn, disconnect_cb); - - return msn_servconn_connect(swboard->servconn, host, port); -} - -void -msn_switchboard_disconnect(MsnSwitchBoard *swboard) -{ - g_return_if_fail(swboard != NULL); - - msn_servconn_disconnect(swboard->servconn); -} - -/************************************************************************** - * Call stuff - **************************************************************************/ -static void -got_cal(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ -#if 0 - MsnSwitchBoard *swboard; - const char *user; - - swboard = cmdproc->data; - - user = cmd->params[0]; - - msn_switchboard_add_user(swboard, user); -#endif -} - -static void -cal_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans) -{ - purple_debug_warning("msn", "cal_timeout: command %s timed out\n", trans->command); - - cal_error_helper(trans, MSN_SB_ERROR_UNKNOWN); -} - -static void -cal_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) -{ - int reason = MSN_SB_ERROR_UNKNOWN; - - if (error == 215) - { - purple_debug_info("msn", "Invited user already in switchboard\n"); - return; - } - else if (error == 217) - { - reason = MSN_SB_ERROR_USER_OFFLINE; - } - - purple_debug_warning("msn", "cal_error: command %s gave error %i\n", trans->command, error); - - cal_error_helper(trans, reason); -} - -void -msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user) -{ - MsnTransaction *trans; - MsnCmdProc *cmdproc; - - g_return_if_fail(swboard != NULL); - - cmdproc = swboard->cmdproc; - - trans = msn_transaction_new(cmdproc, "CAL", "%s", user); - /* this doesn't do anything, but users seem to think that - * 'Unhandled command' is some kind of error, so we don't report it */ - msn_transaction_add_cb(trans, "CAL", got_cal); - - msn_transaction_set_data(trans, swboard); - msn_transaction_set_timeout_cb(trans, cal_timeout); - - if (swboard->ready) - msn_cmdproc_send_trans(cmdproc, trans); - else - msn_cmdproc_queue_trans(cmdproc, trans); -} - -/************************************************************************** - * Create & Transfer stuff - **************************************************************************/ - -static void -got_swboard(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSwitchBoard *swboard; - char *host; - int port; - swboard = cmd->trans->data; - - if (g_list_find(cmdproc->session->switches, swboard) == NULL) - /* The conversation window was closed. */ - return; - - msn_switchboard_set_auth_key(swboard, cmd->params[4]); - - msn_parse_socket(cmd->params[2], &host, &port); - - if (!msn_switchboard_connect(swboard, host, port)) - msn_switchboard_destroy(swboard); - - g_free(host); -} - -static void -xfr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) -{ - MsnSwitchBoard *swboard; - int reason = MSN_SB_ERROR_UNKNOWN; - - if (error == 913) - reason = MSN_SB_ERROR_OFFLINE; - else if (error == 800) - reason = MSN_SB_ERROR_TOO_FAST; - - swboard = trans->data; - - purple_debug_info("msn", "xfr_error %i for %s: trans %p, command %s, reason %i\n", - error, (swboard->im_user ? swboard->im_user : "(null)"), trans, - (trans->command ? trans->command : "(null)"), reason); - - swboard_error_helper(swboard, reason, swboard->im_user); -} - -void -msn_switchboard_request(MsnSwitchBoard *swboard) -{ - MsnCmdProc *cmdproc; - MsnTransaction *trans; - - g_return_if_fail(swboard != NULL); - - cmdproc = swboard->session->notification->cmdproc; - - trans = msn_transaction_new(cmdproc, "XFR", "%s", "SB"); - msn_transaction_add_cb(trans, "XFR", got_swboard); - - msn_transaction_set_data(trans, swboard); - msn_transaction_set_error_cb(trans, xfr_error); - - msn_cmdproc_send_trans(cmdproc, trans); -} - -void -msn_switchboard_close(MsnSwitchBoard *swboard) -{ - g_return_if_fail(swboard != NULL); - - if (swboard->error != MSN_SB_ERROR_NONE) - { - msn_switchboard_destroy(swboard); - } - else if (g_queue_is_empty(swboard->msg_queue) || - !swboard->session->connected) - { - MsnCmdProc *cmdproc; - cmdproc = swboard->cmdproc; - msn_cmdproc_send_quick(cmdproc, "OUT", NULL, NULL); - - msn_switchboard_destroy(swboard); - } - else - { - swboard->closed = TRUE; - } -} - -gboolean -msn_switchboard_release(MsnSwitchBoard *swboard, MsnSBFlag flag) -{ - g_return_val_if_fail(swboard != NULL, FALSE); - - swboard->flag &= ~flag; - - if (flag == MSN_SB_FLAG_IM) - /* Forget any conversation that used to be associated with this - * swboard. */ - swboard->conv = NULL; - - if (swboard->flag == 0) - { - msn_switchboard_close(swboard); - return TRUE; - } - - return FALSE; -} - -/************************************************************************** - * Init stuff - **************************************************************************/ - -void -msn_switchboard_init(void) -{ - cbs_table = msn_table_new(); - - msn_table_add_cmd(cbs_table, "ANS", "ANS", ans_cmd); - msn_table_add_cmd(cbs_table, "ANS", "IRO", iro_cmd); - - msn_table_add_cmd(cbs_table, "MSG", "ACK", ack_cmd); - msn_table_add_cmd(cbs_table, "MSG", "NAK", nak_cmd); - - msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd); - - msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd); - msn_table_add_cmd(cbs_table, NULL, "JOI", joi_cmd); - msn_table_add_cmd(cbs_table, NULL, "BYE", bye_cmd); - msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd); - -#if 0 - /* They might skip the history */ - msn_table_add_cmd(cbs_table, NULL, "ACK", NULL); -#endif - - msn_table_add_error(cbs_table, "MSG", msg_error); - msn_table_add_error(cbs_table, "CAL", cal_error); - - /* Register the message type callbacks. */ - msn_table_add_msg_type(cbs_table, "text/plain", - plain_msg); - msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol", - control_msg); - msn_table_add_msg_type(cbs_table, "text/x-clientcaps", - clientcaps_msg); - msn_table_add_msg_type(cbs_table, "text/x-clientinfo", - clientcaps_msg); - msn_table_add_msg_type(cbs_table, "application/x-msnmsgrp2p", - msn_p2p_msg); - msn_table_add_msg_type(cbs_table, "text/x-mms-emoticon", - msn_emoticon_msg); - msn_table_add_msg_type(cbs_table, "text/x-mms-animemoticon", - msn_emoticon_msg); - msn_table_add_msg_type(cbs_table, "text/x-msnmsgr-datacast", - nudge_msg); -#if 0 - msn_table_add_msg_type(cbs_table, "text/x-msmmsginvite", - msn_invite_msg); -#endif -} - -void -msn_switchboard_end(void) -{ - msn_table_destroy(cbs_table); -}
--- a/libpurple/protocols/msnp9/switchboard.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,284 +0,0 @@ -/** - * @file switchboard.h MSN switchboard functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_SWITCHBOARD_H_ -#define _MSN_SWITCHBOARD_H_ - -typedef struct _MsnSwitchBoard MsnSwitchBoard; - -#include "conversation.h" - -#include "msg.h" -#include "user.h" - -#include "servconn.h" - -#include "slplink.h" - -/** - * A switchboard error. - */ -typedef enum -{ - MSN_SB_ERROR_NONE, /**< No error. */ - MSN_SB_ERROR_CAL, /**< The user could not join (answer the call). */ - MSN_SB_ERROR_OFFLINE, /**< The account is offline. */ - MSN_SB_ERROR_USER_OFFLINE, /**< The user to call is offline. */ - MSN_SB_ERROR_CONNECTION, /**< There was a connection error. */ - MSN_SB_ERROR_TOO_FAST, /**< We are sending too fast */ - MSN_SB_ERROR_AUTHFAILED, /**< Authentication failed joining the switchboard session */ - MSN_SB_ERROR_UNKNOWN /**< An unknown error occurred. */ - -} MsnSBErrorType; - -/** - * A switchboard flag. - */ -typedef enum -{ - MSN_SB_FLAG_IM = 0x01, /**< This switchboard is being used for a conversation. */ - MSN_SB_FLAG_FT = 0x02, /**< This switchboard is being used for file transfer. */ - -} MsnSBFlag; - -/** - * A switchboard. - * - * A place where a bunch of users send messages to the rest of the users. - */ -struct _MsnSwitchBoard -{ - MsnSession *session; - MsnServConn *servconn; - MsnCmdProc *cmdproc; - char *im_user; - - MsnSBFlag flag; - char *auth_key; - char *session_id; - - PurpleConversation *conv; /**< The conversation that displays the - messages of this switchboard, or @c NULL if - this is a helper switchboard. */ - - gboolean empty; /**< A flag that states if the swithcboard has no - users in it. */ - gboolean invited; /**< A flag that states if we were invited to the - switchboard. */ - gboolean ready; /**< A flag that states if this switchboard is - ready to be used. */ - gboolean closed; /**< A flag that states if the switchboard has - been closed by the user. */ - gboolean destroying; /**< A flag that states if the switchboard is - alredy on the process of destruction. */ - - int current_users; - int total_users; - GList *users; - - int chat_id; - - GQueue *msg_queue; /**< Queue of messages to send. */ - GList *ack_list; /**< List of messages waiting for an ack. */ - - MsnSBErrorType error; /**< The error that occurred in this switchboard - (if applicable). */ - GList *slplinks; /**< The list of slplinks that are using this switchboard. */ -}; - -/** - * Initialize the variables for switchboard creation. - */ -void msn_switchboard_init(void); - -/** - * Destroy the variables for switchboard creation. - */ -void msn_switchboard_end(void); - -/** - * Creates a new switchboard. - * - * @param session The MSN session. - * - * @return The new switchboard. - */ -MsnSwitchBoard *msn_switchboard_new(MsnSession *session); - -/** - * Destroys a switchboard. - * - * @param swboard The switchboard to destroy. - */ -void msn_switchboard_destroy(MsnSwitchBoard *swboard); - -/** - * Sets the auth key the switchboard must use when connecting. - * - * @param swboard The switchboard. - * @param key The auth key. - */ -void msn_switchboard_set_auth_key(MsnSwitchBoard *swboard, const char *key); - -/** - * Returns the auth key the switchboard must use when connecting. - * - * @param swboard The switchboard. - * - * @return The auth key. - */ -const char *msn_switchboard_get_auth_key(MsnSwitchBoard *swboard); - -/** - * Sets the session ID the switchboard must use when connecting. - * - * @param swboard The switchboard. - * @param id The session ID. - */ -void msn_switchboard_set_session_id(MsnSwitchBoard *swboard, const char *id); - -/** - * Returns the session ID the switchboard must use when connecting. - * - * @param swboard The switchboard. - * - * @return The session ID. - */ -const char *msn_switchboard_get_session_id(MsnSwitchBoard *swboard); - -/** - * Returns the next chat ID for use by a switchboard. - * - * @return The chat ID. - */ -int msn_switchboard_get_chat_id(void); - -/** - * Sets whether or not we were invited to this switchboard. - * - * @param swboard The switchboard. - * @param invite @c TRUE if invited, @c FALSE otherwise. - */ -void msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited); - -/** - * Returns whether or not we were invited to this switchboard. - * - * @param swboard The switchboard. - * - * @return @c TRUE if invited, @c FALSE otherwise. - */ -gboolean msn_switchboard_is_invited(MsnSwitchBoard *swboard); - -/** - * Connects to a switchboard. - * - * @param swboard The switchboard. - * @param host The switchboard server host. - * @param port The switcbharod server port. - * - * @return @c TRUE if able to connect, or @c FALSE otherwise. - */ -gboolean msn_switchboard_connect(MsnSwitchBoard *swboard, - const char *host, int port); - -/** - * Disconnects from a switchboard. - * - * @param swboard The switchboard to disconnect from. - */ -void msn_switchboard_disconnect(MsnSwitchBoard *swboard); - -/** - * Closes the switchboard. - * - * Called when a conversation is closed. - * - * @param swboard The switchboard to close. - */ -void msn_switchboard_close(MsnSwitchBoard *swboard); - -/** - * Release a switchboard from a certain function. - * - * @param swboard The switchboard to release. - * @param flag The flag that states the function. - * - * @return @c TRUE if the switchboard was closed, @c FALSE otherwise. - */ -gboolean msn_switchboard_release(MsnSwitchBoard *swboard, MsnSBFlag flag); - -/** - * Returns whether or not we currently can send a message through this - * switchboard. - * - * @param swboard The switchboard. - * - * @return @c TRUE if a message can be sent, @c FALSE otherwise. - */ -gboolean msn_switchboard_can_send(MsnSwitchBoard *swboard); - -/** - * Sends a message through this switchboard. - * - * @param swboard The switchboard. - * @param msg The message. - * @param queue A flag that states if we want this message to be queued (in - * the case it cannot currently be sent). - * - * @return @c TRUE if a message can be sent, @c FALSE otherwise. - */ -void msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg, - gboolean queue); - -gboolean msn_switchboard_chat_leave(MsnSwitchBoard *swboard); -gboolean msn_switchboard_chat_invite(MsnSwitchBoard *swboard, const char *who); - -void msn_switchboard_request(MsnSwitchBoard *swboard); -void msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user); - -/** - * Processes peer to peer messages. - * - * @param cmdproc The command processor. - * @param msg The message. - */ -void msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg); - -/** - * Processes emoticon messages. - * - * @param cmdproc The command processor. - * @param msg The message. - */ -void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg); - -/** - * Processes INVITE messages. - * - * @param cmdproc The command processor. - * @param msg The message. - */ -void msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg); - -#endif /* _MSN_SWITCHBOARD_H_ */
--- a/libpurple/protocols/msnp9/sync.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,260 +0,0 @@ -/** - * @file sync.c MSN list synchronization functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "sync.h" -#include "state.h" - -static MsnTable *cbs_table; - -static void -blp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - PurpleConnection *gc = cmdproc->session->account->gc; - const char *list_name; - - list_name = cmd->params[0]; - - if (!g_ascii_strcasecmp(list_name, "AL")) - { - /* - * If the current setting is AL, messages from users who - * are not in BL will be delivered. - * - * In other words, deny some. - */ - gc->account->perm_deny = PURPLE_PRIVACY_DENY_USERS; - } - else - { - /* If the current setting is BL, only messages from people - * who are in the AL will be delivered. - * - * In other words, permit some. - */ - gc->account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS; - } -} - -static void -prp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session = cmdproc->session; - const char *type, *value; - - type = cmd->params[0]; - value = cmd->params[1]; - - if (cmd->param_count == 2) - { - if (!strcmp(type, "PHH")) - msn_user_set_home_phone(session->user, purple_url_decode(value)); - else if (!strcmp(type, "PHW")) - msn_user_set_work_phone(session->user, purple_url_decode(value)); - else if (!strcmp(type, "PHM")) - msn_user_set_mobile_phone(session->user, purple_url_decode(value)); - } - else - { - if (!strcmp(type, "PHH")) - msn_user_set_home_phone(session->user, NULL); - else if (!strcmp(type, "PHW")) - msn_user_set_work_phone(session->user, NULL); - else if (!strcmp(type, "PHM")) - msn_user_set_mobile_phone(session->user, NULL); - } -} - -static void -lsg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session = cmdproc->session; - const char *name; - int group_id; - - group_id = atoi(cmd->params[0]); - name = purple_url_decode(cmd->params[1]); - - msn_group_new(session->userlist, group_id, name); - - /* HACK */ - if (group_id == 0) - { - /* Group of ungroupped buddies */ - if (session->sync->total_users == 0) - { - cmdproc->cbs_table = session->sync->old_cbs_table; - - msn_session_finish_login(session); - - msn_sync_destroy(session->sync); - session->sync = NULL; - } - return; - } - - if ((purple_find_group(name)) == NULL) - { - PurpleGroup *g = purple_group_new(name); - purple_blist_add_group(g, NULL); - } -} - -static void -lst_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSession *session = cmdproc->session; - char *passport = NULL; - const char *friend = NULL; - int list_op; - MsnUser *user; - - passport = cmd->params[0]; - friend = purple_url_decode(cmd->params[1]); - list_op = atoi(cmd->params[2]); - - user = msn_user_new(session->userlist, passport, friend); - - msn_userlist_add_user(session->userlist, user); - - session->sync->last_user = user; - - /* TODO: This can be improved */ - - if (list_op & MSN_LIST_FL_OP) - { - char **c; - char **tokens; - const char *group_nums; - GSList *group_ids; - - group_nums = cmd->params[3]; - - group_ids = NULL; - - tokens = g_strsplit(group_nums, ",", -1); - - for (c = tokens; *c != NULL; c++) - { - int id; - - id = atoi(*c); - group_ids = g_slist_append(group_ids, GINT_TO_POINTER(id)); - } - - g_strfreev(tokens); - - msn_got_lst_user(session, user, list_op, group_ids); - - g_slist_free(group_ids); - } - else - { - msn_got_lst_user(session, user, list_op, NULL); - } - - session->sync->num_users++; - - if (session->sync->num_users == session->sync->total_users) - { - cmdproc->cbs_table = session->sync->old_cbs_table; - - msn_session_finish_login(session); - - msn_sync_destroy(session->sync); - session->sync = NULL; - } -} - -static void -bpr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ - MsnSync *sync = cmdproc->session->sync; - const char *type, *value; - MsnUser *user; - - user = sync->last_user; - - g_return_if_fail(user != NULL); - - type = cmd->params[0]; - value = cmd->params[1]; - - if (value) - { - if (!strcmp(type, "MOB")) - { - if (!strcmp(value, "Y")) - user->mobile = TRUE; - else if (!strcmp(value, "N")) - user->mobile = FALSE; - } - else if (!strcmp(type, "PHH")) - msn_user_set_home_phone(user, purple_url_decode(value)); - else if (!strcmp(type, "PHW")) - msn_user_set_work_phone(user, purple_url_decode(value)); - else if (!strcmp(type, "PHM")) - msn_user_set_mobile_phone(user, purple_url_decode(value)); - } -} - -void -msn_sync_init(void) -{ - /* TODO: check prp, blp, bpr */ - - cbs_table = msn_table_new(); - - /* Syncing */ - msn_table_add_cmd(cbs_table, NULL, "GTC", NULL); - msn_table_add_cmd(cbs_table, NULL, "BLP", blp_cmd); - msn_table_add_cmd(cbs_table, NULL, "PRP", prp_cmd); - msn_table_add_cmd(cbs_table, NULL, "LSG", lsg_cmd); - msn_table_add_cmd(cbs_table, NULL, "LST", lst_cmd); - msn_table_add_cmd(cbs_table, NULL, "BPR", bpr_cmd); -} - -void -msn_sync_end(void) -{ - msn_table_destroy(cbs_table); -} - -MsnSync * -msn_sync_new(MsnSession *session) -{ - MsnSync *sync; - - sync = g_new0(MsnSync, 1); - - sync->session = session; - sync->cbs_table = cbs_table; - - return sync; -} - -void -msn_sync_destroy(MsnSync *sync) -{ - g_free(sync); -}
--- a/libpurple/protocols/msnp9/sync.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/** - * @file sync.h MSN list synchronization functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_SYNC_H_ -#define _MSN_SYNC_H_ - -typedef struct _MsnSync MsnSync; - -#include "session.h" -#include "table.h" -#include "user.h" - -struct _MsnSync -{ - MsnSession *session; - MsnTable *cbs_table; - MsnTable *old_cbs_table; - - int num_users; - int total_users; - int num_groups; - int total_groups; - MsnUser *last_user; -}; - -void msn_sync_init(void); -void msn_sync_end(void); - -MsnSync * msn_sync_new(MsnSession *session); -void msn_sync_destroy(MsnSync *sync); - -#endif /* _MSN_SYNC_H_ */
--- a/libpurple/protocols/msnp9/table.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/** - * @file table.c MSN helper structure - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "table.h" - -static void -null_cmd_cb(MsnCmdProc *cmdproc, MsnCommand *cmd) -{ -} - -static void -null_error_cb(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) -{ -} - -MsnTable * -msn_table_new() -{ - MsnTable *table; - - table = g_new0(MsnTable, 1); - - table->cmds = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)g_hash_table_destroy); - table->msgs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); - table->errors = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); - - table->async = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); - table->fallback = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); - - return table; -} - -void -msn_table_destroy(MsnTable *table) -{ - g_return_if_fail(table != NULL); - - g_hash_table_destroy(table->cmds); - g_hash_table_destroy(table->msgs); - g_hash_table_destroy(table->errors); - - g_hash_table_destroy(table->async); - g_hash_table_destroy(table->fallback); - - g_free(table); -} - -void -msn_table_add_cmd(MsnTable *table, - char *command, char *answer, MsnTransCb cb) -{ - GHashTable *cbs; - - g_return_if_fail(table != NULL); - g_return_if_fail(answer != NULL); - - cbs = NULL; - - if (command == NULL) - { - cbs = table->async; - } - else if (strcmp(command, "fallback") == 0) - { - cbs = table->fallback; - } - else - { - cbs = g_hash_table_lookup(table->cmds, command); - - if (cbs == NULL) - { - cbs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); - g_hash_table_insert(table->cmds, command, cbs); - } - } - - if (cb == NULL) - cb = null_cmd_cb; - - g_hash_table_insert(cbs, answer, cb); -} - -void -msn_table_add_error(MsnTable *table, - char *answer, MsnErrorCb cb) -{ - g_return_if_fail(table != NULL); - g_return_if_fail(answer != NULL); - - if (cb == NULL) - cb = null_error_cb; - - g_hash_table_insert(table->errors, answer, cb); -} - -void -msn_table_add_msg_type(MsnTable *table, - char *type, MsnMsgTypeCb cb) -{ - g_return_if_fail(table != NULL); - g_return_if_fail(type != NULL); - g_return_if_fail(cb != NULL); - -#if 0 - if (cb == NULL) - cb = null_msg_cb; -#endif - - g_hash_table_insert(table->msgs, type, cb); -}
--- a/libpurple/protocols/msnp9/table.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/** - * @file table.h MSN helper structure - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_TABLE_H_ -#define _MSN_TABLE_H_ - -typedef struct _MsnTable MsnTable; - -#include "cmdproc.h" -#include "transaction.h" -#include "msg.h" - -typedef void (*MsnMsgTypeCb)(MsnCmdProc *cmdproc, MsnMessage *msg); - -struct _MsnTable -{ - GHashTable *cmds; - GHashTable *msgs; - GHashTable *errors; - - GHashTable *async; - GHashTable *fallback; -}; - -MsnTable *msn_table_new(void); -void msn_table_destroy(MsnTable *table); - -void msn_table_add_cmd(MsnTable *table, char *command, char *answer, - MsnTransCb cb); -void msn_table_add_error(MsnTable *table, char *answer, MsnErrorCb cb); -void msn_table_add_msg_type(MsnTable *table, char *type, MsnMsgTypeCb cb); - -#endif /* _MSN_TABLE_H_ */
--- a/libpurple/protocols/msnp9/transaction.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,221 +0,0 @@ -/** - * @file transaction.c MSN transaction functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "transaction.h" - -MsnTransaction * -msn_transaction_new(MsnCmdProc *cmdproc, const char *command, - const char *format, ...) -{ - MsnTransaction *trans; - va_list arg; - - g_return_val_if_fail(command != NULL, NULL); - - trans = g_new0(MsnTransaction, 1); - - trans->cmdproc = cmdproc; - trans->command = g_strdup(command); - - if (format != NULL) - { - va_start(arg, format); - trans->params = g_strdup_vprintf(format, arg); - va_end(arg); - } - - /* trans->queue = g_queue_new(); */ - - return trans; -} - -void -msn_transaction_destroy(MsnTransaction *trans) -{ - g_return_if_fail(trans != NULL); - - g_free(trans->command); - g_free(trans->params); - g_free(trans->payload); - -#if 0 - if (trans->pendent_cmd != NULL) - msn_message_unref(trans->pendent_msg); -#endif - -#if 0 - MsnTransaction *elem; - if (trans->queue != NULL) - { - while ((elem = g_queue_pop_head(trans->queue)) != NULL) - msn_transaction_destroy(elem); - - g_queue_free(trans->queue); - } -#endif - - if (trans->callbacks != NULL && trans->has_custom_callbacks) - g_hash_table_destroy(trans->callbacks); - - if (trans->timer) - purple_timeout_remove(trans->timer); - - g_free(trans); -} - -char * -msn_transaction_to_string(MsnTransaction *trans) -{ - char *str; - - g_return_val_if_fail(trans != NULL, FALSE); - - if (trans->params != NULL) - str = g_strdup_printf("%s %u %s\r\n", trans->command, trans->trId, trans->params); - else - str = g_strdup_printf("%s %u\r\n", trans->command, trans->trId); - - return str; -} - -void -msn_transaction_queue_cmd(MsnTransaction *trans, MsnCommand *cmd) -{ - purple_debug_info("msn", "queueing command.\n"); - trans->pendent_cmd = cmd; - msn_command_ref(cmd); -} - -void -msn_transaction_unqueue_cmd(MsnTransaction *trans, MsnCmdProc *cmdproc) -{ - MsnCommand *cmd; - - if (!cmdproc->servconn->connected) - return; - - purple_debug_info("msn", "unqueueing command.\n"); - cmd = trans->pendent_cmd; - - g_return_if_fail(cmd != NULL); - - msn_cmdproc_process_cmd(cmdproc, cmd); - msn_command_unref(cmd); - - trans->pendent_cmd = NULL; -} - -#if 0 -void -msn_transaction_queue(MsnTransaction *trans, MsnTransaction *elem) -{ - if (trans->queue == NULL) - trans->queue = g_queue_new(); - - g_queue_push_tail(trans->queue, elem); -} - -void -msn_transaction_unqueue(MsnTransaction *trans, MsnCmdProc *cmdproc) -{ - MsnTransaction *elem; - - while ((elem = g_queue_pop_head(trans->queue)) != NULL) - msn_cmdproc_send_trans(cmdproc, elem); -} -#endif - -void -msn_transaction_set_payload(MsnTransaction *trans, - const char *payload, int payload_len) -{ - g_return_if_fail(trans != NULL); - g_return_if_fail(payload != NULL); - - trans->payload = g_strdup(payload); - trans->payload_len = payload_len ? payload_len : strlen(trans->payload); -} - -void -msn_transaction_set_data(MsnTransaction *trans, void *data) -{ - g_return_if_fail(trans != NULL); - - trans->data = data; -} - -void -msn_transaction_add_cb(MsnTransaction *trans, char *answer, - MsnTransCb cb) -{ - g_return_if_fail(trans != NULL); - g_return_if_fail(answer != NULL); - - if (trans->callbacks == NULL) - { - trans->has_custom_callbacks = TRUE; - trans->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, - NULL); - } - else if (trans->has_custom_callbacks != TRUE) - g_return_if_reached (); - - g_hash_table_insert(trans->callbacks, answer, cb); -} - -static gboolean -transaction_timeout(gpointer data) -{ - MsnTransaction *trans; - - trans = data; - g_return_val_if_fail(trans != NULL, FALSE); - -#if 0 - purple_debug_info("msn", "timed out: %s %d %s\n", trans->command, trans->trId, trans->params); -#endif - - if (trans->timeout_cb != NULL) - trans->timeout_cb(trans->cmdproc, trans); - - return FALSE; -} - -void -msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb) -{ - if (trans->timer) - { - purple_debug_error("msn", "This shouldn't be happening\n"); - purple_timeout_remove(trans->timer); - } - trans->timeout_cb = cb; - trans->timer = purple_timeout_add_seconds(60, transaction_timeout, trans); -} - -void -msn_transaction_set_error_cb(MsnTransaction *trans, MsnErrorCb cb) -{ - trans->error_cb = cb; -}
--- a/libpurple/protocols/msnp9/transaction.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/** - * @file transaction.h MSN transaction functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_TRANSACTION_H -#define _MSN_TRANSACTION_H - -typedef struct _MsnTransaction MsnTransaction; - -#include "command.h" -#include "cmdproc.h" - -typedef void (*MsnTransCb)(MsnCmdProc *cmdproc, MsnCommand *cmd); -typedef void (*MsnTimeoutCb)(MsnCmdProc *cmdproc, MsnTransaction *trans); -typedef void (*MsnErrorCb)(MsnCmdProc *cmdproc, MsnTransaction *trans, - int error); - -/** - * A transaction. A sending command that will initiate the transaction. - */ -struct _MsnTransaction -{ - MsnCmdProc *cmdproc; - unsigned int trId; - - char *command; - char *params; - - int timer; - - void *data; /**< The data to be used on the different callbacks. */ - GHashTable *callbacks; - gboolean has_custom_callbacks; - MsnErrorCb error_cb; - MsnTimeoutCb timeout_cb; - - char *payload; - size_t payload_len; - - GQueue *queue; - MsnCommand *pendent_cmd; /**< The command that is waiting for the result of - this transaction. */ -}; - -MsnTransaction *msn_transaction_new(MsnCmdProc *cmdproc, - const char *command, - const char *format, ...); -void msn_transaction_destroy(MsnTransaction *trans); - -char *msn_transaction_to_string(MsnTransaction *trans); -void msn_transaction_queue_cmd(MsnTransaction *trans, MsnCommand *cmd); -void msn_transaction_unqueue_cmd(MsnTransaction *trans, MsnCmdProc *cmdproc); -void msn_transaction_set_payload(MsnTransaction *trans, - const char *payload, int payload_len); -void msn_transaction_set_data(MsnTransaction *trans, void *data); -void msn_transaction_add_cb(MsnTransaction *trans, char *answer, - MsnTransCb cb); -void msn_transaction_set_error_cb(MsnTransaction *trans, MsnErrorCb cb); -void msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb); - -#endif /* _MSN_TRANSACTION_H */
--- a/libpurple/protocols/msnp9/user.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,332 +0,0 @@ -/** - * @file user.c User functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "user.h" -#include "slp.h" - -MsnUser * -msn_user_new(MsnUserList *userlist, const char *passport, - const char *friendly_name) -{ - MsnUser *user; - - user = g_new0(MsnUser, 1); - - user->userlist = userlist; - - msn_user_set_passport(user, passport); - if (friendly_name != NULL) - msn_user_set_friendly_name(user, friendly_name); - - return user; -} - -void -msn_user_destroy(MsnUser *user) -{ - g_return_if_fail(user != NULL); - - if (user->clientcaps != NULL) - g_hash_table_destroy(user->clientcaps); - - if (user->group_ids != NULL) - g_list_free(user->group_ids); - - if (user->msnobj != NULL) - msn_object_destroy(user->msnobj); - - g_free(user->passport); - g_free(user->friendly_name); - g_free(user->phone.home); - g_free(user->phone.work); - g_free(user->phone.mobile); - - g_free(user); -} - -void -msn_user_update(MsnUser *user) -{ - PurpleAccount *account; - - account = user->userlist->session->account; - - if (user->status != NULL) { - if (!strcmp(user->status, "offline") && user->mobile) { - purple_prpl_got_user_status(account, user->passport, "offline", NULL); - purple_prpl_got_user_status(account, user->passport, "mobile", NULL); - } else { - purple_prpl_got_user_status(account, user->passport, user->status, NULL); - purple_prpl_got_user_status_deactive(account, user->passport, "mobile"); - } - } - - if (user->idle) - purple_prpl_got_user_idle(account, user->passport, TRUE, -1); - else - purple_prpl_got_user_idle(account, user->passport, FALSE, 0); -} - -void -msn_user_set_state(MsnUser *user, const char *state) -{ - const char *status; - - if (!g_ascii_strcasecmp(state, "BSY")) - status = "busy"; - else if (!g_ascii_strcasecmp(state, "BRB")) - status = "brb"; - else if (!g_ascii_strcasecmp(state, "AWY")) - status = "away"; - else if (!g_ascii_strcasecmp(state, "PHN")) - status = "phone"; - else if (!g_ascii_strcasecmp(state, "LUN")) - status = "lunch"; - else - status = "available"; - - if (!g_ascii_strcasecmp(state, "IDL")) - user->idle = TRUE; - else - user->idle = FALSE; - - user->status = status; -} - -void -msn_user_set_passport(MsnUser *user, const char *passport) -{ - g_return_if_fail(user != NULL); - - g_free(user->passport); - user->passport = g_strdup(passport); -} - -void -msn_user_set_friendly_name(MsnUser *user, const char *name) -{ - MsnCmdProc *cmdproc; - MsnSession *session; - const char *encoded; - - g_return_if_fail(user != NULL); - - encoded = purple_url_encode(name); - session = user->userlist->session; - - if (user->friendly_name && strcmp(user->friendly_name, name) - && (strlen(encoded) < 387) && session->passport_info.verified && - (user->list_op & MSN_LIST_FL_OP)) { - /* copy the new name to the server list, but only when new */ - /* should we check this more thoroughly? */ - cmdproc = session->notification->cmdproc; - msn_cmdproc_send(cmdproc, "REA", "%s %s", - user->passport, - encoded); - } - - g_free(user->friendly_name); - user->friendly_name = g_strdup(name); -} - -void -msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img) -{ - MsnObject *msnobj = NULL; - - g_return_if_fail(user != NULL); - - msnobj = msn_object_new_from_image(img, "TFR2C2.tmp", - user->passport, MSN_OBJECT_USERTILE); - - if(!msnobj) - purple_debug_error("msn", "Unable to open buddy icon from %s!\n", user->passport); - - msn_user_set_object(user, msnobj); -} - -void -msn_user_add_group_id(MsnUser *user, int id) -{ - MsnUserList *userlist; - PurpleAccount *account; - PurpleBuddy *b; - PurpleGroup *g; - const char *passport; - const char *group_name; - - g_return_if_fail(user != NULL); - g_return_if_fail(id >= 0); - - user->group_ids = g_list_append(user->group_ids, GINT_TO_POINTER(id)); - - userlist = user->userlist; - account = userlist->session->account; - passport = msn_user_get_passport(user); - - group_name = msn_userlist_find_group_name(userlist, id); - - g = purple_find_group(group_name); - - if ((id == 0) && (g == NULL)) - { - g = purple_group_new(group_name); - purple_blist_add_group(g, NULL); - } - - b = purple_find_buddy_in_group(account, passport, g); - - if (b == NULL) - { - b = purple_buddy_new(account, passport, NULL); - - purple_blist_add_buddy(b, NULL, g, NULL); - } - - b->proto_data = user; -} - -void -msn_user_remove_group_id(MsnUser *user, int id) -{ - g_return_if_fail(user != NULL); - g_return_if_fail(id >= 0); - - user->group_ids = g_list_remove(user->group_ids, GINT_TO_POINTER(id)); -} - -void -msn_user_set_home_phone(MsnUser *user, const char *number) -{ - g_return_if_fail(user != NULL); - - if (user->phone.home != NULL) - g_free(user->phone.home); - - user->phone.home = (number == NULL ? NULL : g_strdup(number)); -} - -void -msn_user_set_work_phone(MsnUser *user, const char *number) -{ - g_return_if_fail(user != NULL); - - if (user->phone.work != NULL) - g_free(user->phone.work); - - user->phone.work = (number == NULL ? NULL : g_strdup(number)); -} - -void -msn_user_set_mobile_phone(MsnUser *user, const char *number) -{ - g_return_if_fail(user != NULL); - - if (user->phone.mobile != NULL) - g_free(user->phone.mobile); - - user->phone.mobile = (number == NULL ? NULL : g_strdup(number)); -} - -void -msn_user_set_object(MsnUser *user, MsnObject *obj) -{ - g_return_if_fail(user != NULL); - - if (user->msnobj != NULL) - msn_object_destroy(user->msnobj); - - user->msnobj = obj; - - if (user->list_op & MSN_LIST_FL_OP) - msn_queue_buddy_icon_request(user); -} - -void -msn_user_set_client_caps(MsnUser *user, GHashTable *info) -{ - g_return_if_fail(user != NULL); - g_return_if_fail(info != NULL); - - if (user->clientcaps != NULL) - g_hash_table_destroy(user->clientcaps); - - user->clientcaps = info; -} - -const char * -msn_user_get_passport(const MsnUser *user) -{ - g_return_val_if_fail(user != NULL, NULL); - - return user->passport; -} - -const char * -msn_user_get_friendly_name(const MsnUser *user) -{ - g_return_val_if_fail(user != NULL, NULL); - - return user->friendly_name; -} - -const char * -msn_user_get_home_phone(const MsnUser *user) -{ - g_return_val_if_fail(user != NULL, NULL); - - return user->phone.home; -} - -const char * -msn_user_get_work_phone(const MsnUser *user) -{ - g_return_val_if_fail(user != NULL, NULL); - - return user->phone.work; -} - -const char * -msn_user_get_mobile_phone(const MsnUser *user) -{ - g_return_val_if_fail(user != NULL, NULL); - - return user->phone.mobile; -} - -MsnObject * -msn_user_get_object(const MsnUser *user) -{ - g_return_val_if_fail(user != NULL, NULL); - - return user->msnobj; -} - -GHashTable * -msn_user_get_client_caps(const MsnUser *user) -{ - g_return_val_if_fail(user != NULL, NULL); - - return user->clientcaps; -}
--- a/libpurple/protocols/msnp9/user.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,266 +0,0 @@ -/** - * @file user.h User functions - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_USER_H_ -#define _MSN_USER_H_ - -typedef struct _MsnUser MsnUser; - -#include "session.h" -#include "object.h" - -#include "userlist.h" - -/** - * A user. - */ -struct _MsnUser -{ -#if 0 - MsnSession *session; /**< The MSN session. */ -#endif - MsnUserList *userlist; - - char *passport; /**< The passport account. */ - char *friendly_name; /**< The friendly name. */ - - const char *status; /**< The state of the user. */ - gboolean idle; /**< The idle state of the user. */ - - struct - { - char *home; /**< Home phone number. */ - char *work; /**< Work phone number. */ - char *mobile; /**< Mobile phone number. */ - - } phone; - - gboolean authorized; /**< Authorized to add this user. */ - gboolean mobile; /**< Signed up with MSN Mobile. */ - - GList *group_ids; /**< The group IDs. */ - - MsnObject *msnobj; /**< The user's MSN Object. */ - - GHashTable *clientcaps; /**< The client's capabilities. */ - - int list_op; -}; - -/**************************************************************************/ -/** @name User API */ -/**************************************************************************/ -/*@{*/ - -/** - * Creates a new user structure. - * - * @param session The MSN session. - * @param passport The initial passport. - * @param stored_name The initial stored name. - * - * @return A new user structure. - */ -MsnUser *msn_user_new(MsnUserList *userlist, const char *passport, - const char *friendly_name); - -/** - * Destroys a user structure. - * - * @param user The user to destroy. - */ -void msn_user_destroy(MsnUser *user); - - -/** - * Updates the user. - * - * Communicates with the core to update the ui, etc. - * - * @param user The user to update. - */ -void msn_user_update(MsnUser *user); - -/** - * Sets the new state of user. - * - * @param user The user. - * @param state The state string. - */ -void msn_user_set_state(MsnUser *user, const char *state); - -/** - * Sets the passport account for a user. - * - * @param user The user. - * @param passport The passport account. - */ -void msn_user_set_passport(MsnUser *user, const char *passport); - -/** - * Sets the friendly name for a user. - * - * @param user The user. - * @param name The friendly name. - */ -void msn_user_set_friendly_name(MsnUser *user, const char *name); - -/** - * Sets the buddy icon for a local user. - * - * @param user The user. - * @param img The buddy icon image - */ -void msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img); - -/** - * Sets the group ID list for a user. - * - * @param user The user. - * @param ids The group ID list. - */ -void msn_user_set_group_ids(MsnUser *user, GList *ids); - -/** - * Adds the group ID for a user. - * - * @param user The user. - * @param id The group ID. - */ -void msn_user_add_group_id(MsnUser *user, int id); - -/** - * Removes the group ID from a user. - * - * @param user The user. - * @param id The group ID. - */ -void msn_user_remove_group_id(MsnUser *user, int id); - -/** - * Sets the home phone number for a user. - * - * @param user The user. - * @param number The home phone number. - */ -void msn_user_set_home_phone(MsnUser *user, const char *number); - -/** - * Sets the work phone number for a user. - * - * @param user The user. - * @param number The work phone number. - */ -void msn_user_set_work_phone(MsnUser *user, const char *number); - -/** - * Sets the mobile phone number for a user. - * - * @param user The user. - * @param number The mobile phone number. - */ -void msn_user_set_mobile_phone(MsnUser *user, const char *number); - -/** - * Sets the MSNObject for a user. - * - * @param user The user. - * @param obj The MSNObject. - */ -void msn_user_set_object(MsnUser *user, MsnObject *obj); - -/** - * Sets the client information for a user. - * - * @param user The user. - * @param info The client information. - */ -void msn_user_set_client_caps(MsnUser *user, GHashTable *info); - - -/** - * Returns the passport account for a user. - * - * @param user The user. - * - * @return The passport account. - */ -const char *msn_user_get_passport(const MsnUser *user); - -/** - * Returns the friendly name for a user. - * - * @param user The user. - * - * @return The friendly name. - */ -const char *msn_user_get_friendly_name(const MsnUser *user); - -/** - * Returns the home phone number for a user. - * - * @param user The user. - * - * @return The user's home phone number. - */ -const char *msn_user_get_home_phone(const MsnUser *user); - -/** - * Returns the work phone number for a user. - * - * @param user The user. - * - * @return The user's work phone number. - */ -const char *msn_user_get_work_phone(const MsnUser *user); - -/** - * Returns the mobile phone number for a user. - * - * @param user The user. - * - * @return The user's mobile phone number. - */ -const char *msn_user_get_mobile_phone(const MsnUser *user); - -/** - * Returns the MSNObject for a user. - * - * @param user The user. - * - * @return The MSNObject. - */ -MsnObject *msn_user_get_object(const MsnUser *user); - -/** - * Returns the client information for a user. - * - * @param user The user. - * - * @return The client information. - */ -GHashTable *msn_user_get_client_caps(const MsnUser *user); - -/*@}*/ - -#endif /* _MSN_USER_H_ */
--- a/libpurple/protocols/msnp9/userlist.c Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,709 +0,0 @@ -/** - * @file userlist.c MSN user list support - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#include "msn.h" -#include "userlist.h" - -const char *lists[] = { "FL", "AL", "BL", "RL" }; - -typedef struct -{ - PurpleConnection *gc; - char *who; - char *friendly; - -} MsnPermitAdd; - -/************************************************************************** - * Callbacks - **************************************************************************/ -static void -msn_accept_add_cb(gpointer data) -{ - MsnPermitAdd *pa = data; - MsnSession *session; - MsnUserList *userlist; - - if (PURPLE_CONNECTION_IS_VALID(pa->gc)) { - session = pa->gc->proto_data; - userlist = session->userlist; - - msn_userlist_add_buddy(userlist, pa->who, MSN_LIST_AL, NULL); - } - - g_free(pa->who); - g_free(pa->friendly); - g_free(pa); -} - -static void -msn_cancel_add_cb(gpointer data) -{ - MsnPermitAdd *pa = data; - MsnSession *session; - MsnUserList *userlist; - - if (PURPLE_CONNECTION_IS_VALID(pa->gc)) { - session = pa->gc->proto_data; - userlist = session->userlist; - - msn_userlist_add_buddy(userlist, pa->who, MSN_LIST_BL, NULL); - } - - g_free(pa->who); - g_free(pa->friendly); - g_free(pa); -} - -static void -got_new_entry(PurpleConnection *gc, const char *passport, const char *friendly) -{ - MsnPermitAdd *pa; - - pa = g_new0(MsnPermitAdd, 1); - pa->who = g_strdup(passport); - pa->friendly = g_strdup(friendly); - pa->gc = gc; - - purple_account_request_authorization(purple_connection_get_account(gc), passport, NULL, friendly, NULL, - purple_find_buddy(purple_connection_get_account(gc), passport) != NULL, - msn_accept_add_cb, msn_cancel_add_cb, pa); -} - -/************************************************************************** - * Utility functions - **************************************************************************/ - -static gboolean -user_is_in_group(MsnUser *user, int group_id) -{ - if (user == NULL) - return FALSE; - - if (group_id < 0) - return FALSE; - - if (g_list_find(user->group_ids, GINT_TO_POINTER(group_id))) - return TRUE; - - return FALSE; -} - -static gboolean -user_is_there(MsnUser *user, int list_id, int group_id) -{ - int list_op; - - if (user == NULL) - return FALSE; - - list_op = 1 << list_id; - - if (!(user->list_op & list_op)) - return FALSE; - - if (list_id == MSN_LIST_FL) - { - if (group_id >= 0) - return user_is_in_group(user, group_id); - } - - return TRUE; -} - -static const char* -get_friendly_name(MsnUser *user) -{ - const char *friendly_name; - - g_return_val_if_fail(user != NULL, NULL); - - friendly_name = msn_user_get_friendly_name(user); - - if (friendly_name != NULL) - friendly_name = purple_url_encode(friendly_name); - else - friendly_name = msn_user_get_passport(user); - - /* this might be a bit of a hack, but it should prevent notification server - * disconnections for people who have buddies with insane friendly names - * who added you to their buddy list from being disconnected. Stu. */ - /* Shx: What? Isn't the store_name obtained from the server, and hence it's - * below the BUDDY_ALIAS_MAXLEN ? */ - /* Stu: yeah, that's why it's a bit of a hack, as you pointed out, we're - * probably decoding the incoming store_name wrong, or something. bleh. */ - - if (strlen(friendly_name) > BUDDY_ALIAS_MAXLEN) - friendly_name = msn_user_get_passport(user); - - return friendly_name; -} - -static void -msn_request_add_group(MsnUserList *userlist, const char *who, - const char *old_group_name, const char *new_group_name) -{ - MsnCmdProc *cmdproc; - MsnTransaction *trans; - MsnMoveBuddy *data; - - cmdproc = userlist->session->notification->cmdproc; - data = g_new0(MsnMoveBuddy, 1); - - data->who = g_strdup(who); - - if (old_group_name) - data->old_group_name = g_strdup(old_group_name); - - trans = msn_transaction_new(cmdproc, "ADG", "%s %d", - purple_url_encode(new_group_name), - 0); - - msn_transaction_set_data(trans, data); - - msn_cmdproc_send_trans(cmdproc, trans); -} - -/************************************************************************** - * Server functions - **************************************************************************/ - -MsnListId -msn_get_list_id(const char *list) -{ - if (list[0] == 'F') - return MSN_LIST_FL; - else if (list[0] == 'A') - return MSN_LIST_AL; - else if (list[0] == 'B') - return MSN_LIST_BL; - else if (list[0] == 'R') - return MSN_LIST_RL; - - return -1; -} - -void -msn_got_add_user(MsnSession *session, MsnUser *user, - MsnListId list_id, int group_id) -{ - PurpleAccount *account; - const char *passport; - const char *friendly; - - account = session->account; - - passport = msn_user_get_passport(user); - friendly = msn_user_get_friendly_name(user); - - if (list_id == MSN_LIST_FL) - { - PurpleConnection *gc; - - gc = purple_account_get_connection(account); - - serv_got_alias(gc, passport, friendly); - - if (group_id >= 0) - { - msn_user_add_group_id(user, group_id); - } - else - { - /* session->sync->fl_users_count++; */ - } - } - else if (list_id == MSN_LIST_AL) - { - purple_privacy_permit_add(account, passport, TRUE); - } - else if (list_id == MSN_LIST_BL) - { - purple_privacy_deny_add(account, passport, TRUE); - } - else if (list_id == MSN_LIST_RL) - { - PurpleConnection *gc; - PurpleConversation *convo; - - gc = purple_account_get_connection(account); - - purple_debug_info("msn", - "%s has added you to his or her buddy list.\n", - passport); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, passport, account); - if (convo) { - PurpleBuddy *buddy; - char *msg; - - buddy = purple_find_buddy(account, passport); - msg = g_strdup_printf( - _("%s has added you to his or her buddy list."), - buddy ? purple_buddy_get_contact_alias(buddy) : passport); - purple_conv_im_write(PURPLE_CONV_IM(convo), passport, msg, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - g_free(msg); - } - - if (!(user->list_op & (MSN_LIST_AL_OP | MSN_LIST_BL_OP))) - { - /* - * TODO: The friendly name was NULL for me when I - * looked at this. Maybe we should use the store - * name instead? --KingAnt - */ - got_new_entry(gc, passport, friendly); - } - } - - user->list_op |= (1 << list_id); - /* purple_user_add_list_id (user, list_id); */ -} - -void -msn_got_rem_user(MsnSession *session, MsnUser *user, - MsnListId list_id, int group_id) -{ - PurpleAccount *account; - const char *passport; - - account = session->account; - - passport = msn_user_get_passport(user); - - if (list_id == MSN_LIST_FL) - { - /* TODO: When is the user totally removed? */ - if (group_id >= 0) - { - msn_user_remove_group_id(user, group_id); - return; - } - else - { - /* session->sync->fl_users_count--; */ - } - } - else if (list_id == MSN_LIST_AL) - { - purple_privacy_permit_remove(account, passport, TRUE); - } - else if (list_id == MSN_LIST_BL) - { - purple_privacy_deny_remove(account, passport, TRUE); - } - else if (list_id == MSN_LIST_RL) - { - PurpleConversation *convo; - - purple_debug_info("msn", - "%s has removed you from his or her buddy list.\n", - passport); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, passport, account); - if (convo) { - PurpleBuddy *buddy; - char *msg; - - buddy = purple_find_buddy(account, passport); - msg = g_strdup_printf( - _("%s has removed you from his or her buddy list."), - buddy ? purple_buddy_get_contact_alias(buddy) : passport); - purple_conv_im_write(PURPLE_CONV_IM(convo), passport, msg, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - g_free(msg); - } - } - - user->list_op &= ~(1 << list_id); - /* purple_user_remove_list_id (user, list_id); */ - - if (user->list_op == 0) - { - purple_debug_info("msn", "Buddy '%s' shall be deleted?.\n", - passport); - - } -} - -void -msn_got_lst_user(MsnSession *session, MsnUser *user, - int list_op, GSList *group_ids) -{ - PurpleConnection *gc; - PurpleAccount *account; - const char *passport; - const char *store; - - account = session->account; - gc = purple_account_get_connection(account); - - passport = msn_user_get_passport(user); - store = msn_user_get_friendly_name(user); - - if (list_op & MSN_LIST_AL_OP) - { - /* These are users who are allowed to see our status. */ - purple_privacy_deny_remove(account, passport, TRUE); - purple_privacy_permit_add(account, passport, TRUE); - } - - if (list_op & MSN_LIST_BL_OP) - { - /* These are users who are not allowed to see our status. */ - purple_privacy_permit_remove(account, passport, TRUE); - purple_privacy_deny_add(account, passport, TRUE); - } - - if (list_op & MSN_LIST_FL_OP) - { - GSList *c; - for (c = group_ids; c != NULL; c = g_slist_next(c)) - { - int group_id; - group_id = GPOINTER_TO_INT(c->data); - msn_user_add_group_id(user, group_id); - } - - /* FIXME: It might be a real alias */ - /* Umm, what? This might fix bug #1385130 */ - serv_got_alias(gc, passport, store); - } - - if (list_op & MSN_LIST_RL_OP) - { - /* These are users who have us on their buddy list. */ - /* - * TODO: What is store name set to when this happens? - * For one of my accounts "something@hotmail.com" - * the store name was "something." Maybe we - * should use the friendly name, instead? --KingAnt - */ - - if (!(list_op & (MSN_LIST_AL_OP | MSN_LIST_BL_OP))) - { - got_new_entry(gc, passport, store); - } - } - - user->list_op = list_op; -} - -/************************************************************************** - * UserList functions - **************************************************************************/ - -MsnUserList* -msn_userlist_new(MsnSession *session) -{ - MsnUserList *userlist; - - userlist = g_new0(MsnUserList, 1); - - userlist->session = session; - userlist->buddy_icon_requests = g_queue_new(); - - /* buddy_icon_window is the number of allowed simultaneous buddy icon requests. - * XXX With smarter rate limiting code, we could allow more at once... 5 was the limit set when - * we weren't retrieiving any more than 5 per MSN session. */ - userlist->buddy_icon_window = 1; - - return userlist; -} - -void -msn_userlist_destroy(MsnUserList *userlist) -{ - GList *l; - - for (l = userlist->users; l != NULL; l = l->next) - { - msn_user_destroy(l->data); - } - - g_list_free(userlist->users); - - for (l = userlist->groups; l != NULL; l = l->next) - { - msn_group_destroy(l->data); - } - - g_list_free(userlist->groups); - - g_queue_free(userlist->buddy_icon_requests); - - if (userlist->buddy_icon_request_timer) - purple_timeout_remove(userlist->buddy_icon_request_timer); - - g_free(userlist); -} - -void -msn_userlist_add_user(MsnUserList *userlist, MsnUser *user) -{ - userlist->users = g_list_prepend(userlist->users, user); -} - -void -msn_userlist_remove_user(MsnUserList *userlist, MsnUser *user) -{ - userlist->users = g_list_remove(userlist->users, user); -} - -MsnUser * -msn_userlist_find_user(MsnUserList *userlist, const char *passport) -{ - GList *l; - - g_return_val_if_fail(passport != NULL, NULL); - - for (l = userlist->users; l != NULL; l = l->next) - { - MsnUser *user = (MsnUser *)l->data; - - g_return_val_if_fail(user->passport != NULL, NULL); - - if (!strcmp(passport, user->passport)) - return user; - } - - return NULL; -} - -void -msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group) -{ - userlist->groups = g_list_append(userlist->groups, group); -} - -void -msn_userlist_remove_group(MsnUserList *userlist, MsnGroup *group) -{ - userlist->groups = g_list_remove(userlist->groups, group); -} - -MsnGroup * -msn_userlist_find_group_with_id(MsnUserList *userlist, int id) -{ - GList *l; - - g_return_val_if_fail(userlist != NULL, NULL); - g_return_val_if_fail(id >= 0, NULL); - - for (l = userlist->groups; l != NULL; l = l->next) - { - MsnGroup *group = l->data; - - if (group->id == id) - return group; - } - - return NULL; -} - -MsnGroup * -msn_userlist_find_group_with_name(MsnUserList *userlist, const char *name) -{ - GList *l; - - g_return_val_if_fail(userlist != NULL, NULL); - g_return_val_if_fail(name != NULL, NULL); - - for (l = userlist->groups; l != NULL; l = l->next) - { - MsnGroup *group = l->data; - - if ((group->name != NULL) && !g_ascii_strcasecmp(name, group->name)) - return group; - } - - return NULL; -} - -int -msn_userlist_find_group_id(MsnUserList *userlist, const char *group_name) -{ - MsnGroup *group; - - group = msn_userlist_find_group_with_name(userlist, group_name); - - if (group != NULL) - return msn_group_get_id(group); - else - return -1; -} - -const char * -msn_userlist_find_group_name(MsnUserList *userlist, int group_id) -{ - MsnGroup *group; - - group = msn_userlist_find_group_with_id(userlist, group_id); - - if (group != NULL) - return msn_group_get_name(group); - else - return NULL; -} - -void -msn_userlist_rename_group_id(MsnUserList *userlist, int group_id, - const char *new_name) -{ - MsnGroup *group; - - group = msn_userlist_find_group_with_id(userlist, group_id); - - if (group != NULL) - msn_group_set_name(group, new_name); -} - -void -msn_userlist_remove_group_id(MsnUserList *userlist, int group_id) -{ - MsnGroup *group; - - group = msn_userlist_find_group_with_id(userlist, group_id); - - if (group != NULL) - { - msn_userlist_remove_group(userlist, group); - msn_group_destroy(group); - } -} - -void -msn_userlist_rem_buddy(MsnUserList *userlist, - const char *who, int list_id, const char *group_name) -{ - MsnUser *user; - int group_id; - const char *list; - - user = msn_userlist_find_user(userlist, who); - group_id = -1; - - if (group_name != NULL) - { - group_id = msn_userlist_find_group_id(userlist, group_name); - - if (group_id < 0) - { - /* Whoa, there is no such group. */ - purple_debug_error("msn", "Group doesn't exist: %s\n", group_name); - return; - } - } - - /* First we're going to check if not there. */ - if (!(user_is_there(user, list_id, group_id))) - { - list = lists[list_id]; - purple_debug_error("msn", "User '%s' is not there: %s\n", - who, list); - return; - } - - /* Then request the rem to the server. */ - list = lists[list_id]; - - msn_notification_rem_buddy(userlist->session->notification, list, who, group_id); -} - -void -msn_userlist_add_buddy(MsnUserList *userlist, - const char *who, int list_id, - const char *group_name) -{ - MsnUser *user; - int group_id; - const char *list; - const char *friendly_name; - - group_id = -1; - - if (!purple_email_is_valid(who)) - { - /* only notify the user about problems adding to the friends list - * maybe we should do something else for other lists, but it probably - * won't cause too many problems if we just ignore it */ - if (list_id == MSN_LIST_FL) - { - char *str = g_strdup_printf(_("Unable to add \"%s\"."), who); - purple_notify_error(NULL, NULL, str, - _("The username specified is invalid.")); - g_free(str); - } - - return; - } - - if (group_name != NULL) - { - group_id = msn_userlist_find_group_id(userlist, group_name); - - if (group_id < 0) - { - /* Whoa, we must add that group first. */ - msn_request_add_group(userlist, who, NULL, group_name); - return; - } - } - - user = msn_userlist_find_user(userlist, who); - - /* First we're going to check if it's already there. */ - if (user_is_there(user, list_id, group_id)) - { - list = lists[list_id]; - purple_debug_error("msn", "User '%s' is already there: %s\n", who, list); - return; - } - - friendly_name = (user != NULL) ? get_friendly_name(user) : who; - - /* Then request the add to the server. */ - list = lists[list_id]; - - msn_notification_add_buddy(userlist->session->notification, list, who, - friendly_name, group_id); -} - -void -msn_userlist_move_buddy(MsnUserList *userlist, const char *who, - const char *old_group_name, const char *new_group_name) -{ - int new_group_id; - - new_group_id = msn_userlist_find_group_id(userlist, new_group_name); - - if (new_group_id < 0) - { - msn_request_add_group(userlist, who, old_group_name, new_group_name); - return; - } - - msn_userlist_add_buddy(userlist, who, MSN_LIST_FL, new_group_name); - msn_userlist_rem_buddy(userlist, who, MSN_LIST_FL, old_group_name); -}
--- a/libpurple/protocols/msnp9/userlist.h Tue Mar 09 21:41:41 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/** - * @file userlist.h MSN user list support - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _MSN_USERLIST_H_ -#define _MSN_USERLIST_H_ - -typedef struct _MsnUserList MsnUserList; - -#include "cmdproc.h" -#include "user.h" -#include "group.h" - -typedef enum -{ - MSN_LIST_FL, - MSN_LIST_AL, - MSN_LIST_BL, - MSN_LIST_RL - -} MsnListId; - -typedef struct -{ - char *who; - char *old_group_name; - -} MsnMoveBuddy; - -struct _MsnUserList -{ - MsnSession *session; - - /* MsnUsers *users; */ - /* MsnGroups *groups; */ - - GList *users; - GList *groups; - - GQueue *buddy_icon_requests; - int buddy_icon_window; - guint buddy_icon_request_timer; - - int fl_users_count; - -}; - -MsnListId msn_get_list_id(const char *list); - -void msn_got_add_user(MsnSession *session, MsnUser *user, - MsnListId list_id, int group_id); -void msn_got_rem_user(MsnSession *session, MsnUser *user, - MsnListId list_id, int group_id); -void msn_got_lst_user(MsnSession *session, MsnUser *user, - int list_op, GSList *group_ids); - -MsnUserList *msn_userlist_new(MsnSession *session); -void msn_userlist_destroy(MsnUserList *userlist); -void msn_userlist_add_user(MsnUserList *userlist, MsnUser *user); -void msn_userlist_remove_user(MsnUserList *userlist, MsnUser *user); -MsnUser *msn_userlist_find_user(MsnUserList *userlist, - const char *passport); -void msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group); -void msn_userlist_remove_group(MsnUserList *userlist, MsnGroup *group); -MsnGroup *msn_userlist_find_group_with_id(MsnUserList *userlist, int id); -MsnGroup *msn_userlist_find_group_with_name(MsnUserList *userlist, - const char *name); -int msn_userlist_find_group_id(MsnUserList *userlist, - const char *group_name); -const char *msn_userlist_find_group_name(MsnUserList *userlist, - int group_id); -void msn_userlist_rename_group_id(MsnUserList *userlist, int group_id, - const char *new_name); -void msn_userlist_remove_group_id(MsnUserList *userlist, int group_id); - -void msn_userlist_rem_buddy(MsnUserList *userlist, const char *who, - int list_id, const char *group_name); -void msn_userlist_add_buddy(MsnUserList *userlist, const char *who, - int list_id, const char *group_name); -void msn_userlist_move_buddy(MsnUserList *userlist, const char *who, - const char *old_group_name, - const char *new_group_name); - -#endif /* _MSN_USERLIST_H_ */