diff -urN kdenetwork-3.4.3.orig/debian/changelog kdenetwork-3.4.3/debian/changelog
--- kdenetwork-3.4.3.orig/debian/changelog	2005-12-21 17:06:52.000000000 +0800
+++ kdenetwork-3.4.3/debian/changelog	2005-12-21 17:10:52.000000000 +0800
@@ -1,3 +1,9 @@
+kdenetwork (4:3.4.3-0jk) breezy; urgency=low
+
+  * Add meanwhile support
+
+ -- jeremy Kerr <jk@ozlabs.org>  wed, 21 Dec 2005 17:10:29 +0800
+
 kdenetwork (4:3.4.3-0ubuntu1) breezy; urgency=low
 
   * New upstream release
diff -urN kdenetwork-3.4.3.orig/debian/kopete.install kdenetwork-3.4.3/debian/kopete.install
--- kdenetwork-3.4.3.orig/debian/kopete.install	2005-12-21 17:06:52.000000000 +0800
+++ kdenetwork-3.4.3/debian/kopete.install	2005-12-21 17:09:18.000000000 +0800
@@ -69,6 +69,8 @@
 debian/tmp/usr/lib/kde3/kopete_jabber.so
 debian/tmp/usr/lib/kde3/kopete_latex.la
 debian/tmp/usr/lib/kde3/kopete_latex.so
+debian/tmp/usr/lib/kde3/kopete_meanwhile.la
+debian/tmp/usr/lib/kde3/kopete_meanwhile.so
 debian/tmp/usr/lib/kde3/kopete_msn.la
 debian/tmp/usr/lib/kde3/kopete_msn.so
 debian/tmp/usr/lib/kde3/kopete_netmeeting.la
@@ -179,6 +181,10 @@
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/actions/kopeteavailable.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/actions/kopeteaway.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/actions/logging.png
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/actions/meanwhile_unknown.png
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/actions/meanwhile_away.png
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/actions/meanwhile_dnd.png
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/actions/meanwhile_idle.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/actions/metacontact_away.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/actions/metacontact_offline.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/actions/metacontact_online.png
@@ -211,6 +217,7 @@
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/apps/icq_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/apps/irc_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/apps/jabber_protocol.png
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/apps/meanwhile_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/apps/msn_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/apps/sms_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/16x16/apps/yahoo_protocol.png
@@ -222,6 +229,7 @@
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/22x22/actions/logging.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/22x22/apps
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/22x22/apps/groupwise_protocol.png
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/22x22/apps/meanwhile_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/32x32
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/32x32/actions
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/32x32/actions/account_offline_overlay.png
@@ -244,6 +252,7 @@
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/32x32/apps/irc_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/32x32/apps/jabber_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/32x32/apps/latex.png
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/32x32/apps/meanwhile_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/32x32/apps/msn_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/32x32/apps/sms_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/32x32/apps/texteffect.png
@@ -261,6 +270,7 @@
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/48x48/apps/groupwise_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/48x48/apps/icq_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/48x48/apps/jabber_protocol.png
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/48x48/apps/meanwhile_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/48x48/apps/msn_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/48x48/apps/sms_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/48x48/apps/yahoo_protocol.png
@@ -272,11 +282,14 @@
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/64x64/apps/groupwise_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/64x64/apps/icq_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/64x64/apps/msn_protocol.png
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/64x64/apps/meanwhile_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/64x64/apps/sms_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/64x64/apps/yahoo_protocol.png
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/128x128/apps/meanwhile_protocol.png
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/scalable
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/scalable/actions
 debian/tmp/usr/share/apps/kopete/icons/crystalsvg/scalable/actions/account_offline_overlay.svgz
+debian/tmp/usr/share/apps/kopete/icons/crystalsvg/scalable/apps/meanwhile_protocol.svgz
 debian/tmp/usr/share/apps/kopete/icons/hicolor
 debian/tmp/usr/share/apps/kopete/icons/hicolor/16x16
 debian/tmp/usr/share/apps/kopete/icons/hicolor/16x16/actions
@@ -803,6 +816,7 @@
 debian/tmp/usr/share/services/kopete_irc.desktop
 debian/tmp/usr/share/services/kopete_jabber.desktop
 debian/tmp/usr/share/services/kopete_latex.desktop
+debian/tmp/usr/share/services/kopete_meanwhile.desktop
 debian/tmp/usr/share/services/kopete_msn.desktop
 debian/tmp/usr/share/services/kopete_netmeeting.desktop
 debian/tmp/usr/share/services/kopete_nowlistening.desktop
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/configure.in.in kdenetwork-3.4.3/kopete/protocols/configure.in.in
--- kdenetwork-3.4.3.orig/kopete/protocols/configure.in.in	2005-10-05 21:23:35.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/configure.in.in	2005-12-21 17:09:21.000000000 +0800
@@ -153,57 +153,60 @@
 AC_SUBST(IDN_CPPFLAGS)
 AC_SUBST(IDN_LIBS)
 
-# meanwhile support
-# default is not to compile
-# if enabled, check that meanwhile and glib headers/libs are present
-
-MEANWHILE_INCLUDES=""
-MEANWHILE_LIBS=""
-
-AC_ARG_WITH(libmeanwhile-includes,
-	AC_HELP_STRING([--with-libmeanwhile-includes=DIR], [where the libmeanwhile includes are.]),
-	[ if test "x$withval" != "x" ; then MEANWHILE_INCLUDES="-I$withval"; fi ]
-)
-
-AC_ARG_WITH(libmeanwhile-libs,
-	AC_HELP_STRING([--with-libmeanwhile-libs=DIR], [where the libmeanwhile libraries are.]),
-	[ if test "x$withval" != "x" ; then MEANWHILE_LIBS="-L$withval"; fi ]
-)
-
-#FIXME: search for glib, or maybe use pkg-config
-MEANWHILE_INCLUDES="$MEANWHILE_INCLUDES -I/usr/lib/glib-2.0/include -I/usr/include/glib-2.0 -I/usr/include/glib-2.0/glib"
-MEANWHILE_LIBS="$MEANWHILE_LIBS -lmeanwhile -lglib-2.0"
-
-ac_save_LIBS="$LIBS"
-ac_save_CFLAGS="$CFLAGS"
-LIBS="$MEANWHILE_LIBS"
-CFLAGS="$CFLAGS $MEANWHILE_INCLUDES"
-AC_MSG_CHECKING([for libmeanwhile])
-AC_TRY_RUN(
-[
-	#include <meanwhile/meanwhile.h>
-	#include <meanwhile/st_list.h>
-	
-	int main()
-	{
-#if defined LIST_VERSION_MAJOR
-		if ( LIST_VERSION_MAJOR >= 3 )
-			return 0;
-#endif
-		return 1;
-	}
-], [
-	AC_MSG_RESULT([yes])
-	AC_SUBST(MEANWHILE_INCLUDES)
-	AC_SUBST(MEANWHILE_LIBS)
-	COMPILE_MEANWHILE=true
-	AC_SUBST(COMPILE_MEANWHILE)
-], [
-	AC_MSG_RESULT([no])
-	COMPILE_MEANWHILE=
-	AC_SUBST(COMPILE_MEANWHILE)	
-])
-LIBS="$ac_save_LIBS"
-CFLAGS="$ac_save_CFLAGS"
+# Sametime support
 
-AM_CONDITIONAL(include_meanwhile, test -n "$COMPILE_MEANWHILE")
+# lower and upper-bound versions of Meanwhile library
+m4_define(libmeanwhile_version_min, 1.0.1)
+m4_define(libmeanwhile_version_max, 1.1.0)
+
+# Let the user disable the plugin
+AC_ARG_ENABLE(meanwhile,
+      AC_HELP_STRING([--disable-meanwhile],
+      [disable the Kopete Meanwhile plugin (Lotus Sametime support) @<:@default=enabled@:>@]),
+      )
+
+if test "x$enable_meanwhile" != "xno"; then
+    # Check and setup for libmeanwhile
+    KDE_PKG_CHECK_MODULES(MEANWHILE,
+        [meanwhile >= libmeanwhile_version_min meanwhile < libmeanwhile_version_max],
+        [have_libmeanwhile=yes], [have_libmeanwhile=no])
+
+    if test "x$have_libmeanwhile" = "xno"; then
+        enable_meanwhile=no
+        AC_MSG_RESULT([not found])
+    else
+        AC_MSG_RESULT([found])
+    fi
+fi
+
+AC_SUBST(MEANWHILE_CFLAGS)
+AC_SUBST(MEANWHILE_LIBS)
+
+AC_MSG_CHECKING([if Meanwhile plugin should be compiled])
+if test "x$enable_meanwhile" != "xno"; then
+    AC_MSG_RESULT([yes])
+else
+    AC_MSG_RESULT([no])
+fi
+
+# Set the flag to compile meanwhile
+AM_CONDITIONAL(include_meanwhile, [test "x$enable_meanwhile" != "xno"])
+
+# testbed protocol
+dnl define the configure option that disables testbed protocol
+AC_ARG_ENABLE(testbed, [  --disable-testbed     disable kopete testbed protocol compilation ],  with_testbed=$enableval, with_testbed=yes)
+AM_CONDITIONAL(include_testbed, test "$with_testbed" = "yes")
+
+if test "x$have_glib" != "xyes"; then
+    compile_msn_webcam=no
+    msn_webcam_val=0
+else
+    compile_msn_webcam=yes
+    msn_webcam_val=1
+fi
+
+AC_MSG_CHECKING([if MSN webcam support should be enabled])
+AC_MSG_RESULT($compile_msn_webcam)
+AC_DEFINE_UNQUOTED(MSN_WEBCAM, $msn_webcam_val, [Define if MSN webcam support can be enabled])
+
+AM_CONDITIONAL(include_msn_webcam, test "x$compile_msn_webcam" = "xyes")
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/configure.in.in.orig kdenetwork-3.4.3/kopete/protocols/configure.in.in.orig
--- kdenetwork-3.4.3.orig/kopete/protocols/configure.in.in.orig	1970-01-01 08:00:00.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/configure.in.in.orig	2005-12-21 17:09:18.000000000 +0800
@@ -0,0 +1,212 @@
+AC_DEFUN([AC_LIBGADU_DEFINE],
+[
+sed -e "s/#undef __GG_LIBGADU_$1/#define __GG_LIBGADU_$1/" \
+${srcdir}/kopete/protocols/gadu/libgadu/libgadu-config.h > ${srcdir}/kopete/protocols/gadu/libgadu/libgadu-config.h.1
+mv ${srcdir}/kopete/protocols/gadu/libgadu/libgadu-config.h.1 ${srcdir}/kopete/protocols/gadu/libgadu/libgadu-config.h
+])
+	 
+LIBGG_INCLUDES=""
+LIBGG_LIBS=""
+ac_libgadu_includes=""
+ac_libgadu_libs=""
+
+AC_ARG_WITH(libgadu-includes,
+	AC_HELP_STRING([--with-libgadu-includes=DIR], [where the libgadu includes are.]),
+	[  ac_libgadu_includes="$withval" ])
+
+if test "$ac_libgadu_includes" != "" ; then
+LIBGG_INCLUDES="-I$ac_libgadu_includes"
+fi
+
+AC_ARG_WITH(libgadu-libs,
+	AC_HELP_STRING([--with-libgadu-libs=DIR], [where the libgadu libraries are.]),
+	[  ac_libgadu_libs="$withval" ])
+
+if test "$ac_libgadu_libs" != "" ; then
+	LIBGG_LIBS="-L$ac_libgadu_libs"
+fi
+
+
+ac_save_LIBS="$LIBS"
+ac_save_CFLAGS="$CFLAGS"
+LIBS="$LIBGG_LIBS -lgadu $LIBPTHREAD"
+CFLAGS="$CFLAGS $LIBGG_INCLUDES"
+AC_MSG_CHECKING([libgadu version 1.5(rcX) with pthread support])
+	AC_TRY_RUN(
+	[
+	
+	#include <libgadu.h>
+	#include <stdio.h>
+	#include <string.h>
+		
+	int main()
+	{
+#if defined __GG_LIBGADU_HAVE_PTHREAD && defined GG_LOGIN60
+		int maj, min, date;
+		sscanf( gg_libgadu_version(), "%u.%u.%u", &maj,&min,&date );
+		if ( maj != 1 ) {
+			return 1;
+		}
+		if ( ( min == 4 || min == 5 ) && date < 20040520 ) {
+			return 1;
+		}
+
+		if ( min == 5 ){
+			return 0;
+		}
+			     
+#endif
+	    return 1;
+	}
+	], [
+	LIBGG_LIBS="$LIBGG_LIBS -lgadu $LIBPTHREAD"
+	AC_MSG_RESULT([yes])
+	AC_SUBST(LIBGG_INCLUDES)
+	AC_SUBST(LIBGG_LIBS)
+	COMPILE_GADU=true
+	AC_SUBST(COMPILE_GADU)
+	use_libgadu_copy=
+	], [
+	if test "$kde_use_threading" = "yes" ; then
+	AC_MSG_RESULT([no, falling back on supplied libgadu-copy])
+	use_libgadu_copy=yes
+	COMPILE_GADU=true
+	else
+	use_libgadu_copy=
+	AC_MSG_RESULT([no, cannot fall back on libgadu-copy (no pthread)])
+	COMPILE_GADU=	
+	fi
+	AC_SUBST(COMPILE_GADU)	
+	])
+AM_CONDITIONAL(include_gadu, test -n "$COMPILE_GADU")
+AM_CONDITIONAL(include_libggcopy, test -n "$use_libgadu_copy")
+LIBS="$ac_save_LIBS"
+CFLAGS="$ac_save_CFLAGS"
+
+
+if test "$use_libgadu_copy" = "yes"; then
+	cp ${srcdir}/kopete/protocols/gadu/libgadu/libgadu-config.h.in \
+	${srcdir}/kopete/protocols/gadu/libgadu/libgadu-config.h
+	if test "$ac_cv_c_bigendian" = "yes"; then
+		AC_LIBGADU_DEFINE([BIGENDIAN])	
+	fi
+	KDE_CHECK_LONG_LONG()
+	if test "$kde_cv_c_long_long" = "yes"; then
+	AC_LIBGADU_DEFINE([HAVE_LONG_LONG])
+	fi
+	KDE_CHECK_SSL()
+	if test  "$have_ssl" = "yes"; then
+	AC_LIBGADU_DEFINE([HAVE_OPENSSL])
+	fi
+	AC_MSG_CHECKING([for C99-compatible vsnprintf()])
+	AC_TRY_RUN(
+	[
+		#include <stdio.h>
+		int main()
+		{
+			char tmp;
+			return (snprintf(&tmp, sizeof(tmp), "test") != 4);
+		}
+	],[
+		AC_MSG_RESULT([yes])
+		AC_LIBGADU_DEFINE([HAVE_C99_VSNPRINTF])
+	], [
+		 AC_MSG_RESULT([no])
+	])
+	AC_CHECK_FUNCS([va_copy],
+		       [AC_LIBGADU_DEFINE([HAVE_VA_COPY])],[])
+	AC_CHECK_FUNCS([_va_copy],
+		       [AC_LIBGADU_DEFINE([HAVE__VA_COPY])],[])
+fi
+
+
+AC_ARG_WITH(libidn, AC_HELP_STRING([--with-libidn=DIR],
+            [Support IDN (needs GNU Libidn)]),
+            libidn=$withval, libidn=yes)
+
+if test "$libidn" != "no"; then
+	if test "$libidn" != "yes"; then
+		IDN_LDFLAGS="${LDFLAGS} -L$libidn/lib"
+		IDN_CPPFLAGS="${CPPFLAGS} -I$libidn/include"
+	fi
+fi
+
+KDE_CHECK_HEADER(idna.h,, libidn=no)
+
+if test "$libidn" != "no" ; then
+	KDE_CHECK_LIB(idn, stringprep_check_version,
+		[libidn=yes; IDN_LIBS="-lidn"], libidn=no)
+fi
+
+if test "$libidn" != "no" ; then
+	AC_DEFINE(LIBIDN, 1, [Define to 1 if you want IDN support.])
+else
+	AC_MSG_WARN([Libidn not found, Kopete Jabber plugin will not be compiled])
+fi
+
+AC_MSG_CHECKING([if Libidn can be used])
+AC_MSG_RESULT($libidn)
+
+AM_CONDITIONAL(include_jabber, test "$libidn" = "yes")
+
+AC_SUBST(IDN_LDFLAGS)
+AC_SUBST(IDN_CPPFLAGS)
+AC_SUBST(IDN_LIBS)
+
+# Sametime support
+
+# lower and upper-bound versions of Meanwhile library
+m4_define(libmeanwhile_version_min, 0.5.0)
+m4_define(libmeanwhile_version_max, 0.6.0)
+
+# Let the user disable the plugin
+AC_ARG_ENABLE(meanwhile,
+      AC_HELP_STRING([--disable-meanwhile],
+      [disable the Kopete Meanwhile plugin (Lotus Sametime support) @<:@default=enabled@:>@]),
+      )
+
+if test "x$enable_meanwhile" != "xno"; then
+    # Check and setup for libmeanwhile
+    KDE_PKG_CHECK_MODULES(MEANWHILE,
+        [meanwhile >= libmeanwhile_version_min meanwhile < libmeanwhile_version_max],
+        [have_libmeanwhile=yes], [have_libmeanwhile=no])
+
+    if test "x$have_libmeanwhile" = "xno"; then
+        enable_meanwhile=no
+        AC_MSG_RESULT([not found])
+    else
+        AC_MSG_RESULT([found])
+    fi
+fi
+
+AC_SUBST(MEANWHILE_CFLAGS)
+AC_SUBST(MEANWHILE_LIBS)
+
+AC_MSG_CHECKING([if Meanwhile plugin should be compiled])
+if test "x$enable_meanwhile" != "xno"; then
+    AC_MSG_RESULT([yes])
+else
+    AC_MSG_RESULT([no])
+fi
+
+# Set the flag to compile meanwhile
+AM_CONDITIONAL(include_meanwhile, [test "x$enable_meanwhile" != "xno"])
+
+# testbed protocol
+dnl define the configure option that disables testbed protocol
+AC_ARG_ENABLE(testbed, [  --disable-testbed     disable kopete testbed protocol compilation ],  with_testbed=$enableval, with_testbed=yes)
+AM_CONDITIONAL(include_testbed, test "$with_testbed" = "yes")
+
+if test "x$have_glib" != "xyes"; then
+    compile_msn_webcam=no
+    msn_webcam_val=0
+else
+    compile_msn_webcam=yes
+    msn_webcam_val=1
+fi
+
+AC_MSG_CHECKING([if MSN webcam support should be enabled])
+AC_MSG_RESULT($compile_msn_webcam)
+AC_DEFINE_UNQUOTED(MSN_WEBCAM, $msn_webcam_val, [Define if MSN webcam support can be enabled])
+
+AM_CONDITIONAL(include_msn_webcam, test "x$compile_msn_webcam" = "xyes")
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/Makefile.am kdenetwork-3.4.3/kopete/protocols/meanwhile/Makefile.am
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/Makefile.am	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/Makefile.am	2005-12-21 17:09:18.000000000 +0800
@@ -5,7 +5,7 @@
 	-I$(srcdir)/ui \
 	-I./ui \
 	$(all_includes) \
-	$(MEANWHILE_INCLUDES)
+	$(MEANWHILE_CFLAGS)
 
 noinst_HEADERS = \
 	meanwhileprotocol.h \
@@ -13,9 +13,8 @@
 	meanwhileeditaccountwidget.h \
 	meanwhileaccount.h \
 	meanwhilecontact.h \
-	meanwhilelibrary.h \
-	meanwhileplugin.h \
-	meanwhileserver.h
+	meanwhilesession.h \
+	meanwhileplugin.h
 
 kde_module_LTLIBRARIES =  kopete_meanwhile.la
 
@@ -25,9 +24,8 @@
 	meanwhileeditaccountwidget.cpp \
 	meanwhileaccount.cpp \
 	meanwhilecontact.cpp \
-	meanwhilelibrary.cpp \
-	meanwhileplugin.cpp \
-	meanwhileserver.cpp
+	meanwhilesession.cpp \
+	meanwhileplugin.cpp
 
 kopete_meanwhile_la_LDFLAGS = -no-undefined -module \
 	$(KDE_PLUGIN) $(all_libraries) 
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/kopete_meanwhile.desktop kdenetwork-3.4.3/kopete/protocols/meanwhile/kopete_meanwhile.desktop
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/kopete_meanwhile.desktop	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/kopete_meanwhile.desktop	2005-12-21 17:09:18.000000000 +0800
@@ -6,8 +6,8 @@
 ServiceTypes=Kopete/Protocol
 X-KDE-Library=kopete_meanwhile
 X-Kopete-Messaging-Protocol=messaging/meanwhile
-X-KDE-PluginInfo-Author=Sivaram Gottimukkala
-X-KDE-PluginInfo-Email=sivaram@somewhere.net
+X-KDE-PluginInfo-Author=Jeremy Kerr
+X-KDE-PluginInfo-Email=jk@ozlabs.org
 X-KDE-PluginInfo-Name=kopete_meanwhile
 X-KDE-PluginInfo-Version=0.0.1
 X-KDE-PluginInfo-Website=http://kopete.kde.org
@@ -16,41 +16,8 @@
 X-KDE-PluginInfo-License=GPL
 X-KDE-PluginInfo-EnabledByDefault=false
 Name=Meanwhile
-Name[hi]=मीनव्हाइल
 Name[is]=Á meðan
 Name[mk]=Во меѓувреме
 Name[nb]=Imens
 Name[ta]=இடைப்பட்ட பொழுதில்
-Comment=Meanwhile protocol plugin
-Comment[bg]=Протокол за връзка с Meanwhile
-Comment[ca]=Connector de protocol Meanwhile
-Comment[cs]=Modul protokolu Meanwhile
-Comment[da]=Meanwhile-protokol-plugin
-Comment[de]=Meanwhile Protokoll-Modul
-Comment[el]=Πρόσθετο του πρωτοκόλλου Meanwhile
-Comment[es]=Plugin del protocolo de Meanwhile
-Comment[et]=Meanwhile protokolli plugin
-Comment[eu]=Meanwhile protokolo plugin-a
-Comment[fi]=Meanwhile-yhteyskäytäntöliitännäinen
-Comment[fr]=Module du protocole Meanwhile
-Comment[he]=תוסף פרוטוקול של Meanwhile
-Comment[hi]=मीनव्हाइल प्रोटोकॉल प्लगइन
-Comment[hu]=Meanwhile modul
-Comment[is]=Á meðan samskiptureglu íforrit
-Comment[it]=Plugin del protocollo di Meanwhile
-Comment[lt]=Meanwhile protokolo įskiepis
-Comment[nb]=Programtillegg for Imens-protokoll
-Comment[nl]=Procotol voor Meanwhile
-Comment[pl]=Wtyczka protokołu Meanwhile
-Comment[pt]='Plugin' de protocolo Meanwhile
-Comment[pt_BR]=Plugin para o protocolo Meanwhile
-Comment[ro]=Modul de protocol Meanwhile
-Comment[ru]=Модуль протокола Meanwhile
-Comment[sl]=Vstavek za protokol Meanwhile
-Comment[sr]=Прикључак за протокол Meanwhile
-Comment[sr@Latn]=Priključak za protokol Meanwhile
-Comment[sv]=Meanwhile-protokollinsticksprogram
-Comment[ta]=இடைப்பட்ட நெறிமுறை சொருகுப்பொருள்
-Comment[tr]=Meanwhile iletişim kuralı eklentisi
-Comment[uk]=Втулок протоколу для Meanwhile
-Comment[zh_CN]=Meanwhile 协议插件
+Comment=Meanwhile (Lotus Sametime) Protocol
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/log.h kdenetwork-3.4.3/kopete/protocols/meanwhile/log.h
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/log.h	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/log.h	2005-12-21 17:09:18.000000000 +0800
@@ -1,9 +0,0 @@
-#include <stdio.h>
-#include <iostream>
-
-#define LOG(msg) \
-{                \
-    FILE *fp = fopen("/tmp/mean.out","a"); \
-    fprintf(fp,"%s\n",msg);                \
-    fclose(fp);                            \
-}
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileaccount.cpp kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileaccount.cpp
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileaccount.cpp	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileaccount.cpp	2005-12-21 17:09:18.000000000 +0800
@@ -2,6 +2,7 @@
     meanwhileaccount.cpp - a meanwhile account
 
     Copyright (c) 2003-2004 by Sivaram Gottimukkala  <suppandi@gmail.com>
+    Copyright (c) 2005      by Jeremy Kerr <jk@ozlabs.org>
 
     Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
 
@@ -16,82 +17,41 @@
 */
 #include <signal.h>
 #include "meanwhileprotocol.h"
-#include "meanwhileserver.h"
 #include "meanwhileplugin.h"
 #include "meanwhileaccount.h"
 #include "meanwhilecontact.h"
+#include "meanwhilesession.h"
 #include "kopetemessagemanager.h"
+#include "kopetecontactlist.h"
 #include "kopetepassword.h"
 
 #include <kaction.h>
 #include <kpopupmenu.h>
 #include <klocale.h>
+#include <kconfigbase.h>
 #include "kopeteaway.h"
 #include <kinputdialog.h>
 #include <kmessagebox.h>
 #include <qdict.h>
 
-#include "log.h"
-
-#define INIT_SERVER()    \
-    if (server == NULL)  \
-        initServer();    \
-    if (server != NULL)
-
 MeanwhileAccount::MeanwhileAccount(
                         MeanwhileProtocol *parent,
                         const QString &accountID,
                         const char *name)
-    : Kopete::PasswordedAccount ( parent, accountID, 0, name )
+    : Kopete::PasswordedAccount(parent, accountID, 0, name)
 {
-    //signal(SIGSEGV,SIG_DFL);
-    //LOG("MeanwhileAccount");
-    setMyself( new MeanwhileContact(
-                        accountId(),
-                        accountId(),
-                        this,
-                        0L));
-    myself()->setOnlineStatus(MeanwhileProtocol::protocol()->meanwhileOffline);
-    server = NULL;
+    HERE;
+    m_meanwhileId = accountID;
+    m_session = 0L;
+    setMyself(new MeanwhileContact(m_meanwhileId, m_meanwhileId, this, 0L));
+    setOnlineStatus(parent->statusOffline);
     infoPlugin = new MeanwhilePlugin();
 }
 
-void MeanwhileAccount::initServer()
-{
-    server = new MeanwhileServer(serverName(),serverPort());
-    if (server->bad())
-    {
-        delete server;
-        server = NULL;
-    }
-    else
-    {
-        QObject::connect(server,
-                     SIGNAL(loginDone()),
-                     this,
-                     SLOT(slotLoginDone()));
-        QObject::connect(server,
-                     SIGNAL(mesgReceived(const QString &,
-                                         const QString &)),
-                     SLOT(slotMesgReceived(const QString &,
-                                         const QString &)));
-        QObject::connect(server,
-                     SIGNAL(userTyping(const QString &,
-                                       bool)),
-                     SLOT(slotUserTyping(const QString &,
-                                         bool)));
-        QObject::connect(server,
-                     SIGNAL(connectionLost()),
-                     SLOT(slotServerDead()));
-        QObject::connect(server,
-                     SIGNAL(notification(const QString &)),
-                     SLOT(slotServerNotification(const QString&)));
-    }
-}
-
 MeanwhileAccount::~MeanwhileAccount()
 {
-    meanwhileGoOffline();
+    if (m_session)
+        delete m_session;
 }
 
 void MeanwhileAccount::setPlugin(MeanwhilePlugin *plugin)
@@ -104,252 +64,180 @@
                         const QString & contactId ,
                         Kopete::MetaContact * parentContact)
 {
-	MeanwhileContact* newContact =
-                new MeanwhileContact(contactId,
-                                     parentContact->displayName(),
-                                     this,
-                                     parentContact);
-    if ((newContact != NULL) && (server != NULL)
+    MeanwhileContact* newContact = new MeanwhileContact(contactId,
+            parentContact->displayName(), this, parentContact);
+
+    MeanwhileProtocol *p = static_cast<MeanwhileProtocol *>(protocol());
+
+    if ((newContact != 0L) && (m_session != 0L)
         && (myself()->onlineStatus() !=
-                MeanwhileProtocol::protocol()->meanwhileOffline))
-        server->addContact(newContact,contacts());
+                p->statusOffline))
+        m_session->addContact(newContact);
 
-	return newContact != NULL;
+    return newContact != 0L;
 }
 
 void MeanwhileAccount::connectWithPassword(const QString &password)
 {
-    if (password.isEmpty())
+    if (password.isEmpty()) {
+        disconnect(Kopete::Account::Manual);
         return;
+    }
 
-    if (server==NULL)
-        meanwhileGoOnline();
-}
+    if (m_session == 0L) {
+        m_session = new MeanwhileSession(this);
+        if (m_session == 0L) {
+            mwDebug() << "session creation failed" << endl;
+            return;
+        }
 
-void MeanwhileAccount::disconnect()
-{
-    meanwhileGoOffline();
-}
+        QObject::connect(m_session,
+                SIGNAL(sessionStateChange(Kopete::OnlineStatus)),
+                this, SLOT(slotSessionStateChange(Kopete::OnlineStatus)));
+        QObject::connect(m_session,
+                SIGNAL(serverNotification(const QString &)),
+                this, SLOT(slotServerNotification(const QString&)));
 
-void MeanwhileAccount::setAway(
-                        bool away,
-                        const QString &reason)
-{
-    if (away)
-    {
-        meanwhileGoAway(reason);
-    }
-    else
-    {
-        meanwhileGoOnline();
     }
-}
 
-KActionMenu * MeanwhileAccount::actionMenu()
-{
-    KActionMenu * theMenu =
-            new KActionMenu(accountId(),
-                            myself()->onlineStatus().iconFor(this),
-                            this);
-    theMenu->popupMenu()->insertTitle(
-                            myself()->icon(),
-                            i18n("Meanwhile (%1)").arg(accountId()));
-    theMenu->insert(
-           new KAction( i18n( "Go Online" ),
-                        MeanwhileProtocol::protocol()->meanwhileOnline.iconFor(this),
-                        0, this, SLOT(meanwhileGoOnline()), this, "meanwhileGoOnline"));
-
-    theMenu->insert(
-           new KAction( i18n( "Go Offline" ),
-                        MeanwhileProtocol::protocol()->meanwhileOffline.iconFor(this),
-                        0, this, SLOT(meanwhileGoOffline()), this, "meanwhileGoOffline"));
-
-    theMenu->insert(
-           new KAction( i18n( "Go Away" ),
-                        MeanwhileProtocol::protocol()->meanwhileAway.iconFor(this),
-                        0, this, SLOT(meanwhileGoAway()), this, "meanwhileGoAway"));
-
-    theMenu->insert(
-           new KAction( i18n( "Mark as Busy" ),
-                        MeanwhileProtocol::protocol()->meanwhileBusy.iconFor(this),
-                        0, this, SLOT(meanwhileGoDND()), this, "meanwhileGoDND"));
-
-    theMenu->popupMenu()->insertSeparator();
-
-    theMenu->insert(
-           new KAction( i18n("&Change Status Message"), QString::null,
-                        0, this, SLOT(meanwhileChangeStatus()), this,
-                        "meanwhileChangeStatus"));
-
-    infoPlugin->addCustomMenus(theMenu);
-
-    return theMenu;
-}
-
-void MeanwhileAccount::meanwhileGoOnline()
-{
-    if (server!=NULL)
-    {
-        server->goActive(statusMesg);
+    if (m_session == 0L) {
+        mwDebug() << "No memory for session" << endl;
         return;
     }
 
-    QString passwd = password().cachedValue();
-    if (!passwd.isNull())
-    {
-        INIT_SERVER()
-        {
-            server->login(accountId(),passwd);
-        }
-    }
-    else
-    {
-        connect();
-    }
-}
+    if (!m_session->isConnected() && !m_session->isConnecting())
+        m_session->connect(configGroup()->readEntry("Server"),
+                configGroup()->readNumEntry("Port"),
+                m_meanwhileId, password);
 
-void MeanwhileAccount::meanwhileGoOffline()
-{
-    if ((server!=NULL) &&
-        (myself()->onlineStatus() !=
-            MeanwhileProtocol::protocol()->meanwhileOffline))
-            server->logoff();
-    if (server!=NULL)
-    {
-        delete server;
-        server = NULL;
-    }
-    myself()->setOnlineStatus(MeanwhileProtocol::protocol()->meanwhileOffline);
-    setAllContactsStatus(MeanwhileProtocol::protocol()->meanwhileOffline);
-    disconnected( Manual );
+    m_session->setStatus(initialStatus());
 }
 
-void MeanwhileAccount::meanwhileGoAway()
+void MeanwhileAccount::disconnect()
 {
-    meanwhileGoAway(Kopete::Away::getInstance()->message());
+    disconnect(Manual);
 }
 
-void MeanwhileAccount::meanwhileGoAway(const QString &statusmsg)
+void MeanwhileAccount::disconnect(Kopete::Account::DisconnectReason reason)
 {
-    if ((server!=NULL) &&
-        (myself()->onlineStatus() !=
-            MeanwhileProtocol::protocol()->meanwhileOffline))
-        server->goAway(statusmsg);
-}
+    if (m_session == 0L)
+        return;
 
-void MeanwhileAccount::meanwhileGoDND()
-{
-    if ((server!=NULL) &&
-        (myself()->onlineStatus() !=
-            MeanwhileProtocol::protocol()->meanwhileOffline))
-        server->goDND(QString("Please do not disturb"));
+    MeanwhileProtocol *p = static_cast<MeanwhileProtocol *>(protocol());
+    setAllContactsStatus(p->statusOffline);
+    disconnected(reason);
+    emit isConnectedChanged();
+
+    delete m_session;
+    m_session = 0L;
 }
 
-void MeanwhileAccount::slotLoginDone()
+KActionMenu * MeanwhileAccount::actionMenu()
 {
-    myself()->setOnlineStatus(MeanwhileProtocol::protocol()->meanwhileOnline);
-    statusMesg = QString("I am active");
-    server->changeStatus(statusMesg);
-    server->addContacts(contacts());
+    KActionMenu *menu = Kopete::Account::actionMenu();
+
+    menu->popupMenu()->insertSeparator();
+
+#if 0
+    menu->insert(new KAction(i18n("&Change Status Message"), QString::null, 0,
+                this, SLOT(meanwhileChangeStatus()), this,
+                "meanwhileChangeStatus"));
+    //infoPlugin->addCustomMenus(theMenu);
+#endif
+    return menu;
 }
 
-QString MeanwhileAccount::serverName()
+QString MeanwhileAccount::getServerName()
 {
-    return pluginData(protocol(),"Server");
+    return configGroup()->readEntry("Server");
 }
 
-int MeanwhileAccount::serverPort()
+int MeanwhileAccount::getServerPort()
 {
-    return pluginData(protocol(),"Port").toInt();
+    return configGroup()->readNumEntry("Port");
 }
 
 void MeanwhileAccount::setServerName(const QString &server)
 {
-    setPluginData(protocol(), "Server", server);
+    configGroup()->writeEntry("Server", server);
 }
 
 void MeanwhileAccount::setServerPort(int port)
 {
-    setPluginData(protocol(), "Port", QString::number(port));
+    configGroup()->writeEntry("Port", port);
 }
 
-void MeanwhileAccount::slotMesgReceived(
-                            const QString &fromUser,
-                            const QString &msg)
+void MeanwhileAccount::slotServerNotification(const QString &mesg)
 {
-    MeanwhileContact *contact = static_cast<MeanwhileContact *>(contacts()[fromUser]);
-    if(!contact)
-        addContact( fromUser, 0L, Kopete::Account::DontChangeKABC );
+    KMessageBox::queuedMessageBox(0, KMessageBox::Error , mesg,
+            i18n("Meanwhile Plugin: Message from server"), KMessageBox::Notify);
+}
 
-    contact = static_cast<MeanwhileContact *>(contacts()[fromUser]);
-    // Create a Kopete::Message
-    Kopete::ContactPtrList contactList;
-    contactList.append( myself() );
-    Kopete::Message newMessage( contact, contactList, msg, Kopete::Message::Inbound );
+QString MeanwhileAccount::meanwhileId() const
+{
+    return m_meanwhileId;
+}
 
-    // Add it to the manager
-    Kopete::ChatSession *mm = contact->manager(Kopete::Contact::CanCreate);
-    mm->appendMessage(newMessage);
+void MeanwhileAccount::setAway(bool away, const QString &reason)
+{
+    MeanwhileProtocol *p = static_cast<MeanwhileProtocol *>(protocol());
+    setOnlineStatus(away ? p->statusIdle : p->statusOnline, reason);
 }
 
-void MeanwhileAccount::slotUserTyping(
-                            const QString &user,
-                            bool isTyping)
+void MeanwhileAccount::setOnlineStatus(const Kopete::OnlineStatus &status,
+        const QString &reason)
 {
-    MeanwhileContact *contact = static_cast<MeanwhileContact *>(contacts()[user]);
-    if(!contact)
-        addContact( user, 0L, Kopete::Account::DontChangeKABC );
+    HERE;
+    Kopete::OnlineStatus oldstatus = myself()->onlineStatus();
 
-    contact = static_cast<MeanwhileContact *>(contacts()[user]);
-    // Create a Kopete::Message
-    Kopete::ContactPtrList contactList;
-    contactList.append( myself() );
+    mwDebug() << "From: " << oldstatus.description() << "(" <<
+        oldstatus.internalStatus() << "):" << oldstatus.isDefinitelyOnline()
+                                              << endl;
+    mwDebug() << "To:   " << status.description() << "(" <<
+        status.internalStatus() << "):" << status.isDefinitelyOnline() << endl;
 
-    // Add it to the manager
-    Kopete::ChatSession *mm = contact->manager(Kopete::Contact::CanCreate);
-    mm->receivedTypingMsg(contact, isTyping);
-}
+    if (oldstatus == status)
+        return;
 
-void MeanwhileAccount::meanwhileChangeStatus()
-{
-    bool ok;
-    statusMesg = KInputDialog::getText( i18n( "Change Status Message - Meanwhile Plugin" ),
-        i18n( "Enter the message to show under your status:" ),
-        statusMesg, &ok );
+    if (!oldstatus.isDefinitelyOnline() && status.isDefinitelyOnline()) {
+        connect();
 
-    if ( ok )
-    {
-        if ( server!=NULL )
-            server->changeStatus(statusMesg);
-    }
-}
+    } else if (oldstatus.isDefinitelyOnline() && !status.isDefinitelyOnline()) {
+        disconnect(Kopete::Account::Manual);
 
-void MeanwhileAccount::slotServerNotification(const QString &mesg)
-{
-    KMessageBox::queuedMessageBox(
-                        0, KMessageBox::Error ,
-                        mesg,
-                        i18n( "Meanwhile Plugin: Message from server" ),
-                        KMessageBox::Notify );
+    } else if (m_session)
+        /* todo: check session state? */
+        m_session->setStatus(status, reason);
+
+    else
+        mwDebug() << "Trying to set status, but no session exists" << endl;
+
+    /* we should set this on the callback below */
+    //myself()->setOnlineStatus(status);
 }
 
-void MeanwhileAccount::slotServerDead()
+void MeanwhileAccount::syncContactsToServer()
 {
-    delete server;
-    server = NULL;
-    meanwhileGoOffline();
+    if (m_session != 0L)
+        m_session->syncContactsToServer();
 }
 
-void MeanwhileAccount::setOnlineStatus( const Kopete::OnlineStatus & status  , const QString &reason)
+void MeanwhileAccount::slotSessionStateChange(Kopete::OnlineStatus status)
 {
- 	if ( myself()->onlineStatus().status() == Kopete::OnlineStatus::Offline && status.status() == Kopete::OnlineStatus::Online )
-		connect( status );
-	else if ( myself()->onlineStatus().status() != Kopete::OnlineStatus::Offline && status.status() == Kopete::OnlineStatus::Offline )
-		disconnect();
-	else if ( myself()->onlineStatus().status() != Kopete::OnlineStatus::Offline && status.status() == Kopete::OnlineStatus::Away )
-		setAway( true, reason );
+    HERE;
+    Kopete::OnlineStatus oldstatus = myself()->onlineStatus();
+    myself()->setOnlineStatus(status);
 
+    if (status.isDefinitelyOnline() != oldstatus.isDefinitelyOnline()) {
+        if (status.isDefinitelyOnline())
+            m_session->addContacts(contacts());
+        emit isConnectedChanged();
+    }
 }
 
+MeanwhileSession *MeanwhileAccount::session()
+{
+    return m_session;
+}
 
 #include "meanwhileaccount.moc"
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileaccount.h kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileaccount.h
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileaccount.h	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileaccount.h	2005-12-21 17:09:18.000000000 +0800
@@ -2,6 +2,7 @@
     meanwhileaccount.h - meanwhile account
 
     Copyright (c) 2003-2004 by Sivaram Gottimukkala  <suppandi@gmail.com>
+    Copyright (c) 2005      by Jeremy Kerr <jk@ozlabs.org>
 
     Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
 
@@ -18,66 +19,94 @@
 #define MEANWHILEACCOUNT_H
 
 #include <kopetepasswordedaccount.h>
+#include "meanwhileprotocol.h"
+#include "meanwhileplugin.h"
 
-class MeanwhileServer;
-class MeanwhileProtocol;
-class MeanwhilePlugin;
+class MeanwhileSession;
 
+/**
+ * A class to handle a single Meanwhile Account.
+ */
 class MeanwhileAccount : public Kopete::PasswordedAccount
 {
     Q_OBJECT
 public:
-    MeanwhileAccount(   MeanwhileProtocol *parent,
-                        const QString &accountID,
-                        const char *name = 0 );
+    /**
+     * Create a new Meanwhile account
+     * @param protocol  The MeanwhileProtocol that this acccount is for
+     * @param accountID The (meanwhile) account id of this account
+     * @param name      The name of this account
+     */
+    MeanwhileAccount(MeanwhileProtocol *protocol, const QString &accountID,
+            const char *name = 0L);
 
     ~MeanwhileAccount();
 
-    virtual bool createContact(
-                        const QString &contactId,
+    virtual bool createContact(const QString &contactId,
                         Kopete::MetaContact *parentContact);
 
     virtual void connectWithPassword(const QString &password);
 
     virtual void disconnect();
 
-    virtual void setAway(bool away,
-                        const QString &reason);
+    virtual void disconnect(Kopete::Account::DisconnectReason reason);
 
     virtual KActionMenu *actionMenu();
 
-    QString serverName();
-    int     serverPort();
+    /** Get the server host name */
+    QString getServerName();
+    /** Get the server port */
+    int     getServerPort();
+    /** Set the server host name */
     void    setServerName(const QString &server);
+    /** Set the server port */
     void    setServerPort(int port);
+    /** Provide an information plugin for this account */
     void    setPlugin(MeanwhilePlugin *plugin);
 
-    MeanwhileServer *server;
     MeanwhilePlugin *infoPlugin;
 
-protected slots:
-    void meanwhileGoOnline();
-    void meanwhileGoAway();
-    void meanwhileGoOffline();
-    void meanwhileGoDND();
-    void meanwhileChangeStatus();
+    /**
+     * Save the current contact list to the server
+     */
+    void syncContactsToServer();
+
+    /**
+     * Get a reference to the meanwhile session object, if one exists
+     */
+    MeanwhileSession *session();
+
+    /**
+     * Get the meanwhile id for this account
+     * @return The meanwhile ID for the account
+     */
+    QString meanwhileId() const;
 
 public slots:
-    void slotLoginDone();
-    void slotMesgReceived(const QString &fromUser,
-                          const QString &msg);
-    void slotUserTyping(  const QString &user,
-                          bool isTyping);
+    /**
+     * Called by the session to notify that the state has changed
+     */
+    void slotSessionStateChange(Kopete::OnlineStatus status);
+
+    /**
+     * Called by the session when a notification message has been received
+     */
     void slotServerNotification(const QString &mesg);
-    void slotServerDead();
 
     /** Reimplemented from Kopete::Account */
-	void setOnlineStatus( const Kopete::OnlineStatus& status , const QString &reason = QString::null);
+    void setOnlineStatus(const Kopete::OnlineStatus& status,
+            const QString &reason = QString::null);
+    void setAway(bool away, const QString&reason = QString::null);
 
 private:
-    void initServer();
-    void meanwhileGoAway(const QString &statusmsg);
-    QString statusMesg;
+    /** Current online status */
+    Kopete::OnlineStatus status;
+
+    /** A meanwhile session */
+    MeanwhileSession *m_session;
+
+    /* The user id for this account */
+    QString m_meanwhileId;
 };
 
 #endif
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileaddcontactpage.cpp kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileaddcontactpage.cpp
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileaddcontactpage.cpp	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileaddcontactpage.cpp	2005-12-21 17:09:18.000000000 +0800
@@ -22,7 +22,6 @@
 #include <qlineedit.h>
 
 #include "meanwhileprotocol.h"
-#include "meanwhileserver.h"
 #include "meanwhileaccount.h"
 #include "meanwhileplugin.h"
 
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilecontact.cpp kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilecontact.cpp
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilecontact.cpp	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilecontact.cpp	2005-12-21 17:09:18.000000000 +0800
@@ -24,23 +24,20 @@
 #include "kopetemetacontact.h"
 
 #include "meanwhileprotocol.h"
-#include "meanwhileserver.h"
+#include "meanwhilesession.h"
 #include "meanwhileaccount.h"
 #include "meanwhilecontact.h"
 #include "meanwhileplugin.h"
 
-MeanwhileContact::MeanwhileContact( 
-						QString _userId , 
-						QString _nickname,
-						MeanwhileAccount *_account,
-						Kopete::MetaContact *_parent )
-	: Kopete::Contact( _account, _userId, _parent )
+MeanwhileContact::MeanwhileContact(QString userId, QString nickname,
+		MeanwhileAccount *account, Kopete::MetaContact *parent)
+		: Kopete::Contact(account, userId, parent)
 {
-	setDisplayName( _nickname );
+	setNickName(nickname);
 	m_msgManager = 0L;
-	meanwhileId = _userId;
-
-	setOnlineStatus( MeanwhileProtocol::protocol()->meanwhileOffline );
+	m_meanwhileId = userId;
+	setOnlineStatus(static_cast<MeanwhileProtocol *>(account->protocol())
+			->statusOffline);
 }
 
 MeanwhileContact::~MeanwhileContact()
@@ -49,100 +46,84 @@
 
 bool MeanwhileContact::isReachable()
 {
-    return true;
+    return isOnline();
 }
 
-void MeanwhileContact::serialize( 
-			QMap< QString, 
-			QString > &serializedData, 
-			QMap< QString, 
-			QString > & addressBookData )
+void MeanwhileContact::serialize(QMap<QString, QString> &serializedData,
+		QMap<QString, QString> &addressBookData)
 {
 	Kopete::Contact::serialize(serializedData, addressBookData);
 }
 
-Kopete::ChatSession* MeanwhileContact::manager( Kopete::Contact::CanCreateFlags canCreate  )
+void MeanwhileContact::showContactSettings()
+{
+}
+
+void MeanwhileContact::slotUserInfo()
 {
-	if ( m_msgManager || canCreate != Kopete::Contact::CanCreate )
-	{
+	MeanwhileAccount *theAccount = static_cast<MeanwhileAccount *>( account());
+	theAccount->infoPlugin->showUserInfo(m_meanwhileId);
+}
+
+Kopete::ChatSession* MeanwhileContact::manager(CanCreateFlags canCreate)
+{
+	if (m_msgManager != 0L || canCreate == Kopete::Contact::CannotCreate)
 		return m_msgManager;
-	}
-	else
-	{
-		QPtrList<Kopete::Contact> contacts;
-		contacts.append(this);
-
-		m_msgManager = 
-				Kopete::ChatSessionManager::self()->create(
-									account()->myself(), 
-									contacts, protocol());
-
-		connect(m_msgManager, 
-				SIGNAL(messageSent(Kopete::Message&, Kopete::ChatSession*)),
-				this, SLOT( sendMessage( Kopete::Message& ) ) );
 
-		connect(m_msgManager, SIGNAL(destroyed()), 
-				this, SLOT(slotChatSessionDestroyed()));
+	QPtrList<Kopete::Contact> contacts;
+	contacts.append(this);
+	m_msgManager = Kopete::ChatSessionManager::self()->
+		create(account()->myself(), contacts, protocol());
 
-		connect(m_msgManager, SIGNAL(myselfTyping(bool)),
-				this, SLOT(slotMeTypingMsg(bool)));
+	connect(m_msgManager,
+			SIGNAL(messageSent(Kopete::Message&, Kopete::ChatSession*)),
+			this, SLOT(sendMessage(Kopete::Message&)));
 
-		return m_msgManager;
-	}
-}
+	connect(m_msgManager, SIGNAL(myselfTyping(bool)),
+			this, SLOT(slotSendTyping(bool)));
 
+	connect(m_msgManager, SIGNAL(destroyed()),
+			this, SLOT(slotChatSessionDestroyed()));
 
-QPtrList<KAction> *MeanwhileContact::customContextMenuActions() 
-{
-	return 0L;
+	return m_msgManager;
 }
 
-void MeanwhileContact::showContactSettings()
+QString MeanwhileContact::meanwhileId() const
 {
+	return m_meanwhileId;
 }
 
-void MeanwhileContact::slotUserInfo()
+void MeanwhileContact::sendMessage(Kopete::Message &message)
 {
-	MeanwhileAccount *theAccount = static_cast<MeanwhileAccount *>( account());
-	theAccount->infoPlugin->showUserInfo(meanwhileId);
+	static_cast<MeanwhileAccount *>(account())->session()->sendMessage(message);
 }
 
-void MeanwhileContact::sendMessage( Kopete::Message &message )
+void MeanwhileContact::slotSendTyping(bool isTyping)
 {
-	Kopete::ContactPtrList m_them = manager(Kopete::Contact::CanCreate)->members();
-    Kopete::Contact *target = m_them.first();
-	(static_cast<MeanwhileAccount *>( account() ))->server->sendIm(
-			static_cast<MeanwhileContact*>(target),
-			message.plainBody() ); 
-	manager(Kopete::Contact::CanCreate)->appendMessage( message );
-	manager(Kopete::Contact::CanCreate)->messageSucceeded();
+	static_cast<MeanwhileAccount *>(account())->session()->
+		sendTyping(this, isTyping);
 }
 
-void MeanwhileContact::receivedMessage( const QString &message )
+void MeanwhileContact::receivedMessage(const QString &message)
 {
-	Kopete::Message *newMessage;
 	Kopete::ContactPtrList contactList;
-	account();
-	contactList.append( account()->myself() );
-	newMessage = new Kopete::Message( this, contactList, 
-							message, Kopete::Message::Inbound );
+	contactList.append(account()->myself());
+	Kopete::Message kmessage(this, contactList, message,
+			Kopete::Message::Inbound);
 
-	manager(Kopete::Contact::CanCreate)->appendMessage (*newMessage);
-
-	delete newMessage;
+	manager(Kopete::Contact::CanCreate)->appendMessage(kmessage);
 }
 
-void MeanwhileContact::slotChatSessionDestroyed()
+void MeanwhileContact::sync(unsigned int changed)
 {
-	m_msgManager = 0L;
+	if (changed)
+		static_cast<MeanwhileAccount *>(account())->syncContactsToServer();
 }
 
-void MeanwhileContact::slotMeTypingMsg(bool isTyping)
+void MeanwhileContact::slotChatSessionDestroyed()
 {
-	Kopete::ContactPtrList m_them = manager(Kopete::Contact::CanCreate)->members();
-    Kopete::Contact *target = m_them.first();
-	(static_cast<MeanwhileAccount *>( account() ))->server->sendTyping(
-			static_cast<MeanwhileContact*>(target),isTyping);
+	m_msgManager->deref();
+	m_msgManager = 0L;
 }
 
 #include "meanwhilecontact.moc"
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilecontact.h kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilecontact.h
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilecontact.h	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilecontact.h	2005-12-21 17:09:18.000000000 +0800
@@ -30,40 +30,39 @@
 
 class MeanwhileContact : public Kopete::Contact
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
 
-	MeanwhileContact( QString userId,
-	                  QString nickname,
-	                  MeanwhileAccount *account,
-	                  Kopete::MetaContact *parent);
-	~MeanwhileContact();
+    MeanwhileContact(QString userId, QString nickname,
+            MeanwhileAccount *account, Kopete::MetaContact *parent);
+    ~MeanwhileContact();
 
-	virtual bool isReachable();
+    virtual bool isReachable();
 
-	virtual void serialize(QMap<QString, QString> &serializedData, QMap<QString, QString> &addressBookData);
+    virtual void serialize(QMap<QString, QString> &serializedData,
+            QMap<QString, QString> &addressBookData);
 
-	virtual QPtrList<KAction> *customContextMenuActions();
+    virtual Kopete::ChatSession *manager(
+            CanCreateFlags canCreate = CanCreate);
 
-	virtual Kopete::ChatSession *manager( CanCreateFlags canCreate = CanCreate );
+    QString meanwhileId() const;
 
-	QString meanwhileId;
+        virtual void sync(unsigned int changed = 0xff);
 
 public slots:
 
-	void sendMessage( Kopete::Message &message );
-	void receivedMessage( const QString &message );
-	virtual void slotUserInfo();
+    void sendMessage( Kopete::Message &message );
+    void receivedMessage( const QString &message );
+    virtual void slotUserInfo();
 
 protected slots:
-	void showContactSettings();
-	void slotChatSessionDestroyed();
-	void slotMeTypingMsg(bool isTyping);
+    void showContactSettings();
+    void slotChatSessionDestroyed();
+    void slotSendTyping(bool isTyping);
 	
-protected:
-	Kopete::ChatSession* m_msgManager;
-	KActionCollection* m_actionCollection;
-	KAction* m_actionPrefs;
+private:
+    QString m_meanwhileId;
+    Kopete::ChatSession *m_msgManager;
 };
 
 #endif
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileeditaccountwidget.cpp kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileeditaccountwidget.cpp
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileeditaccountwidget.cpp	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileeditaccountwidget.cpp	2005-12-21 17:09:18.000000000 +0800
@@ -25,12 +25,9 @@
 #include <kmessagebox.h>
 #include <klocale.h>
 #include "meanwhileprotocol.h"
-#include "meanwhileserver.h"
 #include "meanwhileaccount.h"
 #include "meanwhileeditaccountwidget.h"
 
-#include "log.h"
-
 #define DEFAULT_SERVER "messaging.opensource.ibm.com"
 #define DEFAULT_PORT 1533
 
@@ -51,8 +48,8 @@
         mPasswordWidget->load(&static_cast<MeanwhileAccount*>(account())->password());
         mAutoConnect->setChecked(account()->excludeConnect());
         MeanwhileAccount *myAccount = static_cast<MeanwhileAccount *>(account());
-        mServerName->setText(myAccount->serverName());
-        mServerPort->setValue(myAccount->serverPort());
+        mServerName->setText(myAccount->getServerName());
+        mServerPort->setValue(myAccount->getServerPort());
     }
     else
     {
@@ -73,9 +70,7 @@
 Kopete::Account* MeanwhileEditAccountWidget::apply()
 {
     if(!account())
-        setAccount(
-                new MeanwhileAccount( 
-                        MeanwhileProtocol::protocol(), mScreenName->text()));
+        setAccount(new MeanwhileAccount(protocol, mScreenName->text()));
 
     MeanwhileAccount *myAccount = static_cast<MeanwhileAccount *>(account());
 
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilelibrary.cpp kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilelibrary.cpp
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilelibrary.cpp	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilelibrary.cpp	1970-01-01 08:00:00.000000000 +0800
@@ -1,605 +0,0 @@
-/*
-    meanwhilelibrary.cpp - interface to the 'C' meanwhile library
-
-    Copyright (c) 2003-2004 by Sivaram Gottimukkala  <suppandi@gmail.com>
-
-    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
-
-    *************************************************************************
-    *                                                                       *
-    * 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.                                   *
-    *                                                                       *
-    *************************************************************************
-*/
-
-#include <string.h>
-#include <stdlib.h>
-#include <kmessagebox.h>
-#include <klocale.h>
-#include <kdebug.h>
-
-#define MEANWHILELIBRARY_CPP
-
-#include "meanwhilelibrary.h"
-#include "meanwhileprotocol.h"
-#include "meanwhileserver.h"
-#include "meanwhilecontact.h"
-
-#define HERE kdDebug() << k_funcinfo << endl;
-
-extern "C"
-{
-#include <meanwhile/channel.h>
-#include <meanwhile/message.h>
-#include <meanwhile/error.h>
-#include <meanwhile/service.h>
-#include <meanwhile/session.h>
-#include <meanwhile/srvc_aware.h>
-#include <meanwhile/srvc_conf.h>
-#include <meanwhile/srvc_im.h>
-
-}
-
-#define ADVERTISE_KOPETE(s) (s+" *using kopete")
-void prettyprint(const char *buffer,int c)
-{
-    int i,j;
-    i=j=0;
-    while(i<c)
-    {
-        printf("%.2hhx",*(buffer+i));
-        i++;
-        if (i%30 == 0)
-        {
-            printf(" ");
-            for(;i!=j;j++)
-                printf("%c",(*(buffer+j)<32)?'.':*(buffer+j));
-            printf("\n");
-        }
-    }
-    printf(" ");
-    for(;i!=j;j++)
-        printf("%c",(*(buffer+j)==0)?'.':*(buffer+j));
-    printf("\n");
-}
-
-struct kopete_handler
-{
-    struct mwSessionHandler public_data;
-    struct 
-    {
-        MeanwhileLibrary *library;
-    } private_data;
-};
-
-int MeanwhileLibrary::Away = mwStatus_AWAY;
-int MeanwhileLibrary::Active = mwStatus_ACTIVE;
-int MeanwhileLibrary::Idle = mwStatus_IDLE;
-int MeanwhileLibrary::Busy = mwStatus_BUSY;
-
-#define REMOVE_UNUSED_VAR_WARNING(x) x=NULL
-#define NOT_IMPLEMENTED NULL
-
-#define MEANWHILE_HOOK(func,call)                       \
-void MeanwhileLibrary::_ ## func                        \
-{                                                       \
-    MeanwhileLibrary *lib =                             \
-	((struct kopete_handler *)s->handler)->         \
-		private_data.library;                   \
-    lib-> call;                                         \
-}                                                       \
-                                                        \
-void MeanwhileLibrary:: func 
-
-#define MEANWHILE_HOOK_SVC(func,call)                   \
-void MeanwhileLibrary::_ ## func                        \
-{                                                       \
-    struct mwSession *s =                               \
-	((struct mwService*)srvc)->session;             \
-    MeanwhileLibrary *lib =                             \
-	((struct kopete_handler *)s->handler)->         \
-		private_data.library;                   \
-    lib-> call;                                         \
-}                                                       \
-                                                        \
-void MeanwhileLibrary:: func 
-
-#define MEANWHILE_HOOK_CONF(func,call)                  \
-void MeanwhileLibrary::_ ## func                        \
-{                                                       \
-    struct mwSession *s =                               \
-	((struct mwService*)conf->srvc)->session;       \
-    MeanwhileLibrary *lib =                             \
-	((struct kopete_handler *)s->handler)->         \
-		private_data.library;                   \
-    lib-> call;                                         \
-}                                                       \
-                                                        \
-void MeanwhileLibrary:: func 
-
-MEANWHILE_HOOK(on_start(struct mwSession *s),
-               on_start(s))
-{
-HERE
-    onStart_sendHandshake(s);
-}
-
-
-MEANWHILE_HOOK(on_loginAck(
-                    struct mwSession *s, 
-                    struct mwMsgLoginAck *msg) ,
-               on_loginAck(s,msg))
-
-{
-HERE
-    REMOVE_UNUSED_VAR_WARNING(msg);
-    
-    mwService_start(MW_SERVICE(srvc_aware));
-
-    struct mwUserStatus stat = { mwStatus_ACTIVE, 0, NULL };
-    emit loginDone();
-    mwSession_setUserStatus(s, &stat);
-}
-
-MEANWHILE_HOOK(on_stop(
-                    struct mwSession *s,
-                    guint32 reason) ,
-               on_stop(s,reason))
-{
-HERE
-    REMOVE_UNUSED_VAR_WARNING(s);
-
- kdDebug() << "close: " << mwError(reason) << endl;
-    if (reason & ERR_FAILURE)
-    {
-        emit serverNotificationReceived(QString(mwError(reason)));
-    }
-
-}
-
-MEANWHILE_HOOK(on_setUserStatus(
-                    struct mwSession *s,
-                    struct mwMsgSetUserStatus *msg) ,
-               on_setUserStatus(s,msg))
-{
-HERE
-    kdDebug() << "meanwhile status for " << ((s->login.user_id==NULL)?"null":s->login.user_id) << " changed to " << (msg->status.status) << endl;
-        struct mwAwareIdBlock id = 
-                { 
-                    mwAware_USER,
-                    s->login.user_id, 
-                    s->login.community 
-                };
-
-        mwServiceAware_setStatus(srvc_aware, &id, &msg->status);
-}
-
-MEANWHILE_HOOK_SVC(got_aware(
-                    struct mwAwareList *list, 
-                    struct mwSnapshotAwareIdBlock *idb, 
-                    struct mwService *srvc),
-                got_aware(list,idb,srvc))
-{
-HERE
-    REMOVE_UNUSED_VAR_WARNING(list);
-    REMOVE_UNUSED_VAR_WARNING(srvc);
-
-    time_t idletime;
-    idletime = 0; 
-    if (idb->status.status == mwStatus_IDLE)
-    	idletime = (idb->status.time == 0xdeadbeef)?
-                            0:idb->status.time;
-    
-    emit userStatusChanged(QString(idb->id.user),
-                        idb->online,
-                        idletime,
-                        idb->status.status,
-                        QString(idb->status.desc));
-}
-
-MEANWHILE_HOOK_SVC(got_error(
-                    struct mwServiceIM *srvc, 
-                    struct mwIdBlock *who, 
-                    unsigned int err) ,
-               got_error(srvc,who,err))
-{
-HERE
-    REMOVE_UNUSED_VAR_WARNING(srvc);
-
-    emit mesgSendError(QString(who->user),QString(mwError(err)));
-}
-
-MEANWHILE_HOOK_SVC(got_text(
-                    struct mwServiceIM *srvc, 
-                    struct mwIdBlock *who, 
-                    const char *text) ,
-               got_text(srvc,who,text))
-{
-HERE
-    REMOVE_UNUSED_VAR_WARNING(srvc);
-
-    emit mesgReceived(QString(who->user),QString(text));
-}
-
-MEANWHILE_HOOK_SVC(got_typing(
-                    struct mwServiceIM *srvc, 
-                    struct mwIdBlock *who, 
-                    int typing) ,
-               got_typing(srvc,who,typing))
-{
-HERE
-    REMOVE_UNUSED_VAR_WARNING(srvc);
-
-    emit userTyping(QString(who->user),(typing!=0));
-}
-
-MEANWHILE_HOOK_CONF(got_invite(
-                    struct mwConference *conf,
-                    struct mwIdBlock *id,
-                    const char *text) ,
-               got_invite(conf,id,text))
-{
-HERE
-    emit invitedToConf(conf,
-                QString(id->user),
-                QString(conf->name),
-                QString(conf->topic),
-                QString(text));
-}
-
-MEANWHILE_HOOK_CONF(got_welcome(
-                    struct mwConference *conf,
-                    struct mwIdBlock *members,
-                    gsize count) ,
-               got_welcome(conf,members,count))
-{
-HERE
-    QString *chatMembers = new QString[count];
-    unsigned int i;
-    for(i=0;i<count;i++,members++)
-    {
-        chatMembers[i] = QString(members->user);
-    }
-    emit welcomeReceived(conf,chatMembers,count);
-}
-
-MEANWHILE_HOOK_CONF(got_closed(
-                    struct mwConference *conf) ,
-               got_closed(conf))
-{
-HERE
-    emit confClosed(conf);
-}
-
-MEANWHILE_HOOK_CONF(got_join(
-                    struct mwConference *conf, 
-                    struct mwIdBlock *id) ,
-               got_join(conf,id))
-{
-HERE
-    emit userJoinedConf(conf,QString(id->user));
-}
-
-
-MEANWHILE_HOOK_CONF(got_part(
-                    struct mwConference *conf, 
-                    struct mwIdBlock *id) ,
-               got_part(conf,id))
-{
-HERE
-    emit userLeftConf(conf,QString(id->user));
-}
-
-MEANWHILE_HOOK_CONF(got_conf_text(
-                    struct mwConference *conf, 
-                    struct mwIdBlock *id,
-                    const char *text) ,
-               got_conf_text(conf,id,text))
-{
-HERE
-    emit confMesgReceived(conf,QString(id->user),
-                          QString(text));
-}
-
-MEANWHILE_HOOK_CONF(got_conf_typing(
-                    struct mwConference *conf, 
-                    struct mwIdBlock *id,
-                    int typing) ,
-               got_conf_typing(conf,id,typing))
-{
-HERE
-    emit confUserTyping(conf,
-                    QString(id->user),
-                    typing!=0);
-}
-
-
-MEANWHILE_HOOK(on_handshakeAck(
-                    struct mwSession *s,
-                    struct mwMsgHandshakeAck *msg) ,
-               on_handshakeAck(s,msg))
-{
-HERE
-    onHandshakeAck_sendLogin(s, msg);
-}
-
-MeanwhileLibrary::MeanwhileLibrary(QString server, int port)
-{
-HERE
-    newSession();
-
-    sock2server = getConnectedSocket(server,port);
-    if (sock2server == NULL);
-}
-
-MeanwhileLibrary::~MeanwhileLibrary()
-{
-HERE
-    free(handler);
-    if (session != NULL)
-        mwSession_free(session);
-    if (sock2server != NULL)
-        delete sock2server; 
-}
-
-bool MeanwhileLibrary::bad()
-{
-HERE
-    return (sock2server == NULL);
-}
-
-void MeanwhileLibrary::login(QString username, QString passwd)
-{
-HERE
-    session->login.user_id = strdup(username.ascii());
-    session->auth.password = strdup(passwd.ascii());
-
-    mwSession_start(session);
-}
-
-void MeanwhileLibrary::logoff()
-{
-HERE
-    if(session) 
-      mwSession_stop(session, ERR_SUCCESS);
-}
-
-int MeanwhileLibrary::_writeToSocket(
-                        struct mwSessionHandler *handler,
-                        const char *buffer,
-                        gsize count)
-{
-HERE
-    return ((kopete_handler*)handler)->private_data.library->
-			writeToSocket(handler,buffer,count);
-}
-
-int MeanwhileLibrary::writeToSocket(
-                        struct mwSessionHandler *handler,
-                        const char *buffer,
-                        unsigned int count)
-{
-HERE
-    REMOVE_UNUSED_VAR_WARNING(handler);
-//prettyprint(buffer,count);
-    int returnval = sock2server->writeBlock(buffer,count);
-    sock2server->flush();
-    return returnval;
-}
-
-void MeanwhileLibrary::_closeSocket(
-                        struct mwSessionHandler *handler) 
-{
-HERE
-    return ((kopete_handler*)handler)->private_data.library->
-                       closeSocket(handler);
-}
-
-void MeanwhileLibrary::closeSocket(
-                        struct mwSessionHandler *handler)
-{
-HERE
-    REMOVE_UNUSED_VAR_WARNING(handler);
-
-    QObject::disconnect(sock2server, SIGNAL(closed(int)),
-                     this,SLOT(slotSocketClosed(int)));
-    sock2server->flush();
-    sock2server->closeNow();
-    emit connectionLost();
-}
-
-void MeanwhileLibrary::newSession()
-{
-HERE
-    /* session setup */
-    session = mwSession_new();
-    session->on_start = _on_start;
-    session->on_stop = _on_stop;
-    
-    session->on_channelOpen = NOT_IMPLEMENTED;
-    session->on_channelClose = NOT_IMPLEMENTED;
-    
-    session->on_handshake = NOT_IMPLEMENTED;
-    session->on_handshakeAck = _on_handshakeAck;
-    session->on_login = NOT_IMPLEMENTED;
-    session->on_loginRedirect = NOT_IMPLEMENTED;
-    session->on_loginContinue = NOT_IMPLEMENTED;
-    session->on_loginAck = _on_loginAck;
-    
-    session->on_setPrivacyInfo = NOT_IMPLEMENTED;
-    session->on_setUserStatus = _on_setUserStatus;
-    session->on_admin = NOT_IMPLEMENTED;
-
-    /* awareness service setup */
-    srvc_aware = mwServiceAware_new(session);
-    aware_list = mwAwareList_new(srvc_aware);
-    mwAwareList_setOnAware(aware_list,
-                        (mwAwareList_onAwareHandler)_got_aware,
-                        srvc_aware);
-    mwSession_putService(session, (struct mwService *) srvc_aware);
-
-    /* im  */
-    srvc_im = mwServiceIM_new(session);
-    srvc_im->got_error = _got_error;
-    srvc_im->got_text = _got_text;
-    srvc_im->got_typing = _got_typing;
-    mwSession_putService(session, (struct mwService *) srvc_im);
-
-    /* conference */
-    struct mwServiceConf *srvc_conf;
-    srvc_conf = mwServiceConf_new(session);
-    srvc_conf->got_invite = _got_invite;
-    srvc_conf->got_welcome = _got_welcome;
-    srvc_conf->got_closed = _got_closed;
-    srvc_conf->got_join = _got_join;
-    srvc_conf->got_part = _got_part;
-    srvc_conf->got_text = _got_conf_text;
-    srvc_conf->got_typing = _got_conf_typing;
-    mwSession_putService(session, (struct mwService *) srvc_conf);
-
-    /* socket writer */
-    handler = (struct mwSessionHandler*)
-                    malloc(sizeof(struct kopete_handler));
-    ((struct kopete_handler*)handler)->public_data.write = _writeToSocket;
-    ((struct kopete_handler*)handler)->public_data.close = _closeSocket;
-    ((struct kopete_handler*)handler)->private_data.library = this;
-    session->handler = (struct mwSessionHandler*)handler;
-}
-
-KExtendedSocket *MeanwhileLibrary::getConnectedSocket(QString server, int port)
-{
-HERE
-    KExtendedSocket *sock = new KExtendedSocket( server, port, 
-                                        KExtendedSocket::bufferedSocket );
-    int error = sock->connect();
-    if (error)
-    {
-        KMessageBox::queuedMessageBox( 
-                        0, KMessageBox::Error , 
-                        i18n( "Could not connect to server"),
-                        i18n( "Meanwhile Plugin" ), 
-                        KMessageBox::Notify );
-        delete sock;
-        return NULL;
-    }
-    sock->enableRead(true);
-//    sock->enableWrite(true);
-    QObject::connect(sock, SIGNAL(readyRead()) , 
-                     SLOT(slotSocketReader()));
-    QObject::connect(sock, SIGNAL(closed(int)),
-                     SLOT(slotSocketClosed(int)));
-    return sock;
-}
-
-void MeanwhileLibrary::slotSocketReader()
-{
-HERE
-    char buffer[4000];
-    int readAmount;
-    readAmount = sock2server->readBlock(buffer,4000);
-    if (readAmount < 0)
-        return;
-//prettyprint(buffer,readAmount);
-    mwSession_recv(session, buffer, (unsigned int) readAmount);
-}
-
-void MeanwhileLibrary::slotSocketClosed(int reason)
-{
-    reason = 0; //  something to eat the compile warning
-/*    if (reason == KExtendedSocket::involuntary)
-    { */
-        emit serverNotificationReceived(QString("Server closed connection"));
-        emit connectionLost();
-//    }
-}
-
-void MeanwhileLibrary::addContacts(const QDict<Kopete::Contact>& contacts)
-{
-HERE
-    QDictIterator<Kopete::Contact> it(contacts); 
-
-    struct mwAwareIdBlock *buddies,*aBuddy;
-    int count;
-
-    count = contacts.count();
-    aBuddy = buddies = 
-                (struct mwAwareIdBlock*)
-			malloc(sizeof(struct mwAwareIdBlock)*count);
-    memset(buddies,0,sizeof(struct mwIdBlock)*count);
-   
-    for( ; it.current(); ++it, aBuddy++ )
-    {
-        MeanwhileContact *contact = 
-                static_cast<MeanwhileContact *>(it.current());
-        aBuddy->user = (gchar*)contact->meanwhileId.ascii();
-        aBuddy->community = NULL;
-	aBuddy->type = mwAware_USER;
-    }
-
-    mwAwareList_addAware(aware_list, buddies, count);
-
-    free(buddies);
-HERE
-}
-
-void MeanwhileLibrary::addContact(const QString & contact)
-{
-HERE
-    struct mwAwareIdBlock aBuddy = 
-		{ mwAware_USER, (char*) contact.ascii(), NULL };
-    
-    mwAwareList_addAware(aware_list, &aBuddy, 1);
-}
-
-int MeanwhileLibrary::sendIm(const QString &toUser, const QString &msg)
-{
-HERE
-  struct mwIdBlock t = { (char *) toUser.ascii(), NULL };
-
-  kdDebug() << "sending data to user " << toUser.ascii() << endl;
-  kdDebug() << msg.ascii() << endl;
-  //prettyprint(msg.ascii(),14);
-  return !mwServiceIM_sendText(srvc_im, &t, msg.ascii());
-}
-
-void MeanwhileLibrary::sendTyping(const QString &toUser, bool isTyping)
-{
-HERE
-  struct mwIdBlock t = { (char *) toUser.ascii(), NULL };
-  mwServiceIM_sendTyping(srvc_im, &t, isTyping);
-}
-
-void MeanwhileLibrary::setState(int state,const QString &stateMsg)
-{
-HERE
-    struct mwUserStatus stat;
-    mwUserStatus_clone(&stat, &session->status);
-
-    free(stat.desc);
-
-    stat.status = (mwStatusType)state;
-    stat.desc = (gchar*)strdup(ADVERTISE_KOPETE(stateMsg).ascii());
-
-    mwSession_setUserStatus(session,&stat);
-    mwUserStatus_clear(&stat);
-}
-
-void MeanwhileLibrary::setStatusMesg(const QString &statusMesg)
-{
-HERE
-    if(statusMesg.isNull())
-        return;
-    struct mwUserStatus stat;
-    mwUserStatus_clone(&stat, &session->status);
-
-    free(stat.desc);
-    stat.desc = (gchar*)strdup(ADVERTISE_KOPETE(statusMesg).ascii());
-
-    mwSession_setUserStatus(session,&stat);
-    mwUserStatus_clear(&stat);
-}
-
-#include "meanwhilelibrary.moc"
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilelibrary.h kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilelibrary.h
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilelibrary.h	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilelibrary.h	1970-01-01 08:00:00.000000000 +0800
@@ -1,180 +0,0 @@
-/*
-    meanwhilelibrary.h - interface to the 'C' meanwhile library
-
-    Copyright (c) 2003-2004 by Sivaram Gottimukkala  <suppandi@gmail.com>
-
-    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
-
-    *************************************************************************
-    *                                                                       *
-    * 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.                                   *
-    *                                                                       *
-    *************************************************************************
-*/
-#ifndef MEANWHILELIBRARY_H
-#define MEANWHILELIBRARY_H
-
-#include <qptrlist.h>
-#include <qdict.h>
-#include <qobject.h>
-
-#include <time.h>
-#include <ghash.h>
-#include <kextsock.h>
-
-#include "kopetecontact.h"
-
-class MeanwhileLibrary : public QObject
-{
-    Q_OBJECT
-
-    public:
-        MeanwhileLibrary(QString server,int port);
-        ~MeanwhileLibrary();
-        bool bad();
-        void login(QString username, QString passwd);
-        void logoff();
-        void addContacts(const QDict<Kopete::Contact> &contacts);
-        void addContact(const QString &contact);
-        int sendIm(const QString &toUser, const QString &msg);
-        void sendTyping(const QString &toUser, bool isTyping);
-        void setState(int state,const QString &awayMsg);
-        void setStatusMesg(const QString &statusMesg);
-
-        static int Active;
-        static int Idle;
-        static int Away;
-        static int Busy;
-
-    signals:
-        void loginDone();
-        void connectionLost();
-        void userStatusChanged(
-                            const QString &user,
-                            bool    isOnline,
-                            time_t  idletime,
-                            int     fullStatus,
-                            const QString &statusMessage);
-        void mesgSendError(const QString &toUser,
-                            const QString &errorString);
-        void mesgReceived(const QString &fromUser,
-                            const QString &mesg);
-        void userTyping(const QString &user,bool isTyping);
-        void invitedToConf(void *confId,
-                            const QString &byUser,
-                            const QString &confName,
-                            const QString &confTopic, 
-                            const QString &mesgText);
-        void welcomeReceived(void *confId,
-                            QString *confMembers,
-                            int memberCount);
-        void confClosed(void *confId);
-        void userJoinedConf(void *confId,
-                            const QString &user);
-        void userLeftConf(void *confId,
-                            const QString &user);
-        void confMesgReceived(void *confId,
-                            const QString &fromUser,
-                            const QString &msgText);
-        void confUserTyping(void *confId,
-                            const QString &user,
-                            bool isTyping);
-        void serverNotificationReceived(const QString &mesgString);
-
-#define DEFINE_MW_HOOK(func) \
-    static void _ ## func;   \
-    void func
-    
-    private:
-        DEFINE_MW_HOOK(on_start(
-                            struct mwSession *s));
-        DEFINE_MW_HOOK(on_handshake(
-                            struct mwSession *s, 
-                            struct mwMsgHandshake *msg));
-        DEFINE_MW_HOOK(on_loginAck(
-                            struct mwSession *s, 
-                            struct mwMsgLoginAck *msg));
-        DEFINE_MW_HOOK(on_stop(
-                            struct mwSession *session, 
-                            guint32 reason));
-        DEFINE_MW_HOOK(on_setUserStatus(
-                            struct mwSession *s,
-                            struct mwMsgSetUserStatus *msg));
-        DEFINE_MW_HOOK(got_aware(
-                            struct mwAwareList *list, 
-                            struct mwSnapshotAwareIdBlock *idb, 
-                            struct mwService *srvc));
-        DEFINE_MW_HOOK(got_error(
-                            struct mwServiceIM *srvc, 
-                            struct mwIdBlock *who, 
-                            unsigned int err));
-        DEFINE_MW_HOOK(got_text(
-                            struct mwServiceIM *srvc,
-                            struct mwIdBlock *who,
-                            const char *mesg));
-        DEFINE_MW_HOOK(got_typing(
-                            struct mwServiceIM *srvc, 
-                            struct mwIdBlock *who, 
-                            int typing));
-        DEFINE_MW_HOOK(got_invite(
-                            struct mwConference *conf, 
-                            struct mwIdBlock *id,
-                            const char *text));
-        DEFINE_MW_HOOK(got_welcome(
-                            struct mwConference *conf, 
-                            struct mwIdBlock *members,
-                            gsize count));
-        DEFINE_MW_HOOK(got_closed(
-                            struct mwConference *conf));
-        DEFINE_MW_HOOK(got_join(
-                            struct mwConference *conf, 
-                            struct mwIdBlock *id));
-        DEFINE_MW_HOOK(got_part(
-                            struct mwConference *conf, 
-                            struct mwIdBlock *id));
-        DEFINE_MW_HOOK(got_conf_text(
-                            struct mwConference *conf, 
-                            struct mwIdBlock *id,
-                            const char *text));
-        DEFINE_MW_HOOK(got_conf_typing(
-                            struct mwConference *conf, 
-                            struct mwIdBlock *id,
-                            int typing));
-        DEFINE_MW_HOOK(on_handshakeAck(
-                            struct mwSession *s,
-                            struct mwMsgHandshakeAck *msg));
-        static int _writeToSocket(
-                            struct mwSessionHandler *handler,
-                            const char *buffer,
-                            gsize count);
-        int writeToSocket(
-                            struct mwSessionHandler *handler,
-                            const char *buffer,
-                            unsigned int count);
-        static void _closeSocket(
-                            struct mwSessionHandler *handler);
-        void closeSocket(
-                            struct mwSessionHandler *handler);
-
-        void newSession();
-
-        KExtendedSocket *getConnectedSocket(QString server, int port);
-
-
-        struct mwSession *session;
-        struct mwServiceAware *srvc_aware;
-        struct mwSessionHandler *handler;
-        struct mwAwareList *aware_list; 
-        mwServiceIM *srvc_im;
-        KExtendedSocket *sock2server;
-
-    public slots:
-        void slotSocketReader();
-        void slotSocketClosed(int reason);
-};
-
-#endif
-
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileprotocol.cpp kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileprotocol.cpp
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileprotocol.cpp	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileprotocol.cpp	2005-12-21 17:09:21.000000000 +0800
@@ -17,85 +17,77 @@
 #include "meanwhileprotocol.h"
 #include "meanwhileaddcontactpage.h"
 #include "meanwhileeditaccountwidget.h"
-#include "meanwhileserver.h"
 #include "meanwhileaccount.h"
 #include <kgenericfactory.h>
 #include "kopeteaccountmanager.h"
 #include "kopeteglobal.h"
 #include "kopeteonlinestatusmanager.h"
 
-MeanwhileProtocol *MeanwhileProtocol::s_protocol = 0L;
+#include "mw_common.h"
 
 typedef KGenericFactory<MeanwhileProtocol> MeanwhileProtocolFactory;
-K_EXPORT_COMPONENT_FACTORY( 
-                kopete_meanwhile, 
-                MeanwhileProtocolFactory( "kopete_meanwhile" ))
-
-MeanwhileProtocol::MeanwhileProtocol( QObject* parent, 
-                                      const char *name, 
-                                      const QStringList &/*args*/)
-    : Kopete::Protocol(MeanwhileProtocolFactory::instance(), 
-                     parent, name ),
-      meanwhileOffline( Kopete::OnlineStatus::Offline, 
-                        25, this, 0, QString::null,
-                        i18n( "Offline" ),
-						i18n( "Go Offline" ), Kopete::OnlineStatusManager::Offline ),
-      meanwhileOnline( Kopete::OnlineStatus::Online, 
-                        25, this, 1, QString::null,
-                        i18n( "Online" ), 
-						i18n( "Go Online" ), Kopete::OnlineStatusManager::Online   ),
-      meanwhileAway( Kopete::OnlineStatus::Away, 
-                        25, this, 2, "meanwhile_away",
-                        i18n( "Away" ) ,
-                        i18n( "Go Away" ), Kopete::OnlineStatusManager::Away ),
-      meanwhileBusy( Kopete::OnlineStatus::Away, 
-                        25, this, 3, "meanwhile_dnd",
-                        i18n( "Busy" ) , 
-						i18n( "Mark as Busy" ), Kopete::OnlineStatusManager::Busy ),
-      meanwhileIdle( Kopete::OnlineStatus::Away, 
-                        25, this, 4, "meanwhile_idle",
-                        i18n( "Idle" ), 
-                        i18n( "Marked as Idle" ), Kopete::OnlineStatusManager::Idle ),
-      meanwhileUnknown( Kopete::OnlineStatus::Unknown, 
-                        25, this, 5, "meanwhile_unknown",
-                        i18n( "Catch me if you can" ) ),
-      statusMessage(QString::fromLatin1("statusMessage"), i18n("Status Message"),QString::null,false,true),
-	  awayMessage(Kopete::Global::Properties::self()->awayMessage())
+K_EXPORT_COMPONENT_FACTORY(kopete_meanwhile,
+    MeanwhileProtocolFactory("kopete_meanwhile"))
+
+MeanwhileProtocol::MeanwhileProtocol(QObject* parent, const char *name,
+        const QStringList &/*args*/)
+: Kopete::Protocol(MeanwhileProtocolFactory::instance(), parent, name),
+
+    statusOffline(Kopete::OnlineStatus::Offline, 25, this, 0, QString::null,
+            i18n("Offline"), i18n("Offline"),
+            Kopete::OnlineStatusManager::Offline,
+	    Kopete::OnlineStatusManager::DisabledIfOffline),
+
+    statusOnline(Kopete::OnlineStatus::Online, 25, this, mwStatus_ACTIVE,
+            QString::null, i18n("Online"), i18n("Online"),
+            Kopete::OnlineStatusManager::Online, 0),
+
+    statusAway(Kopete::OnlineStatus::Away, 20, this, mwStatus_AWAY,
+            "meanwhile_away", i18n("Away"), i18n("Away"),
+            Kopete::OnlineStatusManager::Away,
+	    Kopete::OnlineStatusManager::HasAwayMessage),
+
+    statusBusy(Kopete::OnlineStatus::Away, 25, this, mwStatus_BUSY,
+            "meanwhile_dnd", i18n("Busy"), i18n("Busy"),
+          Kopete::OnlineStatusManager::Busy,
+	  Kopete::OnlineStatusManager::HasAwayMessage),
+
+    statusIdle(Kopete::OnlineStatus::Away, 30, this, mwStatus_AWAY,
+            "meanwhile_idle", i18n("Idle"), i18n("Idle"),
+            Kopete::OnlineStatusManager::Idle, 0),
+
+    statusAccountOffline(Kopete::OnlineStatus::Offline, 0, this, 0,
+            QString::null, i18n("Account Offline")),
+
+    statusMessage(QString::fromLatin1("statusMessage"),
+        i18n("Status Message"), QString::null, false, true),
+
+    awayMessage(Kopete::Global::Properties::self()->awayMessage())
 {
-//    LOG("MeanwhileProtocol()");
-    s_protocol = this;
+    HERE;
 
-    addAddressBookField( "messaging/meanwhile", Kopete::Plugin::MakeIndexField );
+    addAddressBookField("messaging/meanwhile", Kopete::Plugin::MakeIndexField);
 }
 
 MeanwhileProtocol::~MeanwhileProtocol()
 {
 }
 
-AddContactPage * MeanwhileProtocol::createAddContactWidget(
-                                    QWidget *parent, 
-                                    Kopete::Account * account )
+AddContactPage * MeanwhileProtocol::createAddContactWidget(QWidget *parent,
+        Kopete::Account *account )
 {
 	return new MeanwhileAddContactPage(parent, account);
 }
 
-KopeteEditAccountWidget * MeanwhileProtocol::createEditAccountWidget( 
-                                    Kopete::Account *account, 
-                                    QWidget *parent )
+KopeteEditAccountWidget * MeanwhileProtocol::createEditAccountWidget(
+        Kopete::Account *account, QWidget *parent )
 {
-//    LOG("createEditAccountWidget");
-	return new MeanwhileEditAccountWidget( parent, account, this );
+	return new MeanwhileEditAccountWidget(parent, account, this);
 }
 
-Kopete::Account *MeanwhileProtocol::createNewAccount( 
-                                    const QString &accountId )
+Kopete::Account *MeanwhileProtocol::createNewAccount(const QString &accountId)
 {
-	return new MeanwhileAccount( this, accountId, accountId.ascii() );
-}
-
-MeanwhileProtocol *MeanwhileProtocol::protocol()
-{
-    return s_protocol;
+	return new MeanwhileAccount(this, accountId, accountId.ascii());
 }
 
 Kopete::Contact *MeanwhileProtocol::deserializeContact( 
@@ -110,7 +102,7 @@
     MeanwhileAccount *theAccount = 
             static_cast<MeanwhileAccount*>(
                             Kopete::AccountManager::self()->
-                                    findAccount(protocol()->pluginId(), accountId));
+                                    findAccount(pluginId(), accountId));
 
     if(!theAccount)
     {
@@ -121,5 +113,9 @@
     return theAccount->contacts()[contactId];
 }
 
+const Kopete::OnlineStatus MeanwhileProtocol::accountOfflineStatus()
+{
+    return statusAccountOffline;
+}
 
 #include "meanwhileprotocol.moc"
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileprotocol.h kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileprotocol.h
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileprotocol.h	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileprotocol.h	2005-12-21 17:09:18.000000000 +0800
@@ -1,6 +1,7 @@
 /*
     meanwhileprotocl.h - the meanwhile protocol definition
 
+    Copyright (c) 2005      by Jeremy Kerr <jk@ozlabs.org>
     Copyright (c) 2003-2004 by Sivaram Gottimukkala  <suppandi@gmail.com>
 
     Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
@@ -22,8 +23,14 @@
 #include "kopetecontact.h"
 #include "kopetemetacontact.h"
 #include "kopeteonlinestatus.h"
+#include "kopeteonlinestatusmanager.h"
 #include "addcontactpage.h"
 
+#include <kdebug.h>
+#define MEANWHILE_DEBUG 14200
+#define HERE kdDebug(MEANWHILE_DEBUG) << k_funcinfo << endl
+#define mwDebug() kdDebug(MEANWHILE_DEBUG)
+
 class MeanwhileAccount;
 class MeanwhileEditAccountWidget;
 class MeanwhileAddContactPage;
@@ -32,43 +39,36 @@
 {
     Q_OBJECT
 public:
-/* const */
-    MeanwhileProtocol(QObject *parent, 
-                      const char *name, 
-                      const QStringList &args);
-/* destructor */
+    MeanwhileProtocol(QObject *parent, const char *name,
+            const QStringList &args);
+
     ~MeanwhileProtocol();
-    
-    virtual AddContactPage * createAddContactWidget( 
-                                    QWidget *parent, 
-                                    Kopete::Account *account );
-                                    
-    virtual KopeteEditAccountWidget * createEditAccountWidget( 
-                                    Kopete::Account *account, 
-                                    QWidget *parent );     
-
-    virtual Kopete::Account * createNewAccount( 
-                                    const QString &accountId );                               
-
-    virtual Kopete::Contact *deserializeContact( Kopete::MetaContact *metaContact,
-                     const QMap<QString,QString> &serializedData,
-                     const QMap<QString, QString> &addressBookData );
-
-/* kopete doesnt know about these funcs */
-    static MeanwhileProtocol *protocol();
-
-    const Kopete::OnlineStatus meanwhileOffline;
-    const Kopete::OnlineStatus meanwhileOnline;
-    const Kopete::OnlineStatus meanwhileAway;
-    const Kopete::OnlineStatus meanwhileBusy;
-    const Kopete::OnlineStatus meanwhileIdle;
-    const Kopete::OnlineStatus meanwhileUnknown;
 
-    const Kopete::ContactPropertyTmpl statusMessage;
-    const Kopete::ContactPropertyTmpl awayMessage;
+    virtual AddContactPage *createAddContactWidget(QWidget *parent,
+            Kopete::Account *account);
+
+    virtual KopeteEditAccountWidget *createEditAccountWidget(
+            Kopete::Account *account, QWidget *parent);
+
+    virtual Kopete::Account *createNewAccount(const QString &accountId);
+
+    virtual Kopete::Contact *deserializeContact(
+            Kopete::MetaContact *metaContact,
+            const QMap<QString,QString> &serializedData,
+            const QMap<QString, QString> &addressBookData);
+
+    const Kopete::OnlineStatus accountOfflineStatus();
+
+    const Kopete::OnlineStatus statusOffline;
+    const Kopete::OnlineStatus statusOnline;
+    const Kopete::OnlineStatus statusAway;
+    const Kopete::OnlineStatus statusBusy;
+    const Kopete::OnlineStatus statusIdle;
+    const Kopete::OnlineStatus statusAccountOffline;
+
+    Kopete::ContactPropertyTmpl statusMessage;
+    Kopete::ContactPropertyTmpl awayMessage;
 
-protected:
-	static MeanwhileProtocol *s_protocol;
 };
 
 #endif
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileserver.cpp kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileserver.cpp
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileserver.cpp	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileserver.cpp	2005-12-21 17:09:18.000000000 +0800
@@ -1,208 +0,0 @@
-/*
-    meanwhileserver.cpp - server for an account.
-
-    Copyright (c) 2003-2004 by Sivaram Gottimukkala  <suppandi@gmail.com>
-
-    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
-
-    *************************************************************************
-    *                                                                       *
-    * 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.                                   *
-    *                                                                       *
-    *************************************************************************
-*/
-#include <qstring.h>
-#include <klocale.h>
-#include "meanwhilelibrary.h"
-#include "meanwhileprotocol.h"
-#include "meanwhileserver.h"
-#include "meanwhilecontact.h"
-
-#define HERE 
-
-#define MEANWHILESERVER_CPP 1
-MeanwhileServer::MeanwhileServer(QString server, int port)
-{
-HERE
-    library = new MeanwhileLibrary(server,port); 
-    if (library->bad())
-    {
-        delete library;
-        library = NULL;
-    }
-    else
-    {
-        QObject::connect(library, 
-                     SIGNAL(loginDone()),
-                     SLOT(slotLoginDone())); 
-        QObject::connect(library, 
-                     SIGNAL(connectionLost()),
-                     SLOT(slotConnectionLost())); 
-        QObject::connect(library, 
-                     SIGNAL(serverNotificationReceived(const QString&)),
-                     SLOT(slotServerNotification(const QString&))); 
-        QObject::connect(library, 
-                     SIGNAL(userStatusChanged(
-                                const QString &,
-                                bool,
-                                time_t,
-                                int,
-                                const QString &)),
-                     SLOT(slotUserStatusChanged(
-                                const QString &,
-                                bool,
-                                time_t,
-                                int,
-                                const QString &)));
-        QObject::connect(library, 
-                     SIGNAL(mesgReceived(
-                                const QString &,
-                                const QString &)),
-                     SLOT(slotMesgReceived(
-                                const QString &,
-                                const QString &)));
-        QObject::connect(library, 
-                     SIGNAL(userTyping(
-                                const QString &,
-                                bool)),
-                     SLOT(slotUserTyping(
-                                const QString &,
-                                bool)));
-    }
-}
-
-MeanwhileServer::~MeanwhileServer()
-{
-HERE
-    delete library;
-}
-
-bool MeanwhileServer::bad()
-{
-HERE
-    return (library == NULL);
-}
-
-int MeanwhileServer::login(QString username, QString passwd)
-{
-HERE
-    library->login(username,passwd);
-    return 0;
-}
-
-void MeanwhileServer::logoff()
-{
-HERE
-    library->logoff();
-}
-
-void MeanwhileServer::slotLoginDone()
-{
-HERE
-    emit loginDone();
-}
-
-void MeanwhileServer::slotServerNotification(const QString &errMesg)
-{
-    emit notificationAvailable(errMesg);
-}
-
-void MeanwhileServer::slotConnectionLost()
-{
-    emit connectionLost();
-}
-
-void MeanwhileServer::addContacts(const QDict<Kopete::Contact>& _contacts)
-{
-    library->addContacts(contacts=_contacts);
-}
-
-void MeanwhileServer::addContact(Kopete::Contact *_contact,
-                                const QDict<Kopete::Contact>& _contacts)
-{
-    contacts = _contacts;
-    MeanwhileContact *contact = static_cast<MeanwhileContact *>(_contact);
-    library->addContact(contact->meanwhileId);
-}
-
-int MeanwhileServer::sendIm(Kopete::Contact *_contact, const QString &msg)
-{
-    MeanwhileContact *contact = static_cast<MeanwhileContact *>(_contact);
-    return library->sendIm(contact->meanwhileId,msg);
-}
-
-void MeanwhileServer::sendTyping(Kopete::Contact *_contact, bool isTyping)
-{
-    MeanwhileContact *contact = static_cast<MeanwhileContact *>(_contact);
-    library->sendTyping(contact->meanwhileId,isTyping);
-}
-
-void MeanwhileServer::goAway(const QString &awayMsg)
-{
-    library->setState(MeanwhileLibrary::Away,awayMsg);
-}
-
-void MeanwhileServer::goDND(const QString &dndMsg)
-{
-    library->setState(MeanwhileLibrary::Busy,dndMsg);
-}
-
-void MeanwhileServer::changeStatus(const QString &statusMesg)
-{
-    library->setStatusMesg(statusMesg);
-}
-
-void MeanwhileServer::slotMesgReceived(const QString &fromUser,
-                                       const QString &mesg)
-{
-    emit mesgReceived(fromUser,mesg);
-}
-
-void MeanwhileServer::slotUserTyping(const QString &user,
-                                     bool isTyping)
-{
-    emit userTyping(user,isTyping);
-}
-
-void MeanwhileServer::goActive(const QString &status)
-{
-    library->setState(MeanwhileLibrary::Active,status);
-}
-
-#define STATUS(VALUE,onlinestatus)                        \
-    (status==MeanwhileLibrary::VALUE)?                    \
-            MeanwhileProtocol::protocol()->onlinestatus:
-void MeanwhileServer::slotUserStatusChanged(
-                                const QString & userid,
-                                bool isOnline,
-                                time_t idletime,
-                                int status,
-                                const QString & statusDesc)
-{
-    MeanwhileContact *contact = static_cast<MeanwhileContact *>(contacts[userid]);
-    if (contact != NULL)
-    {
-          contact->setProperty(MeanwhileProtocol::protocol()->statusMessage,
-                               statusDesc);
-          contact->setProperty(MeanwhileProtocol::protocol()->awayMessage,
-                               statusDesc);
-          contact->setOnlineStatus( 
-                      isOnline?
-                         STATUS(Away,meanwhileAway)
-                         STATUS(Active,meanwhileOnline)
-                         STATUS(Idle,meanwhileIdle)
-                         STATUS(Busy,meanwhileBusy)
-                         MeanwhileProtocol::protocol()->meanwhileUnknown:
-                         MeanwhileProtocol::protocol()->meanwhileOffline);
-	   
-/*        if ((status == MeanwhileLibrary::Idle) && (idletime != 0))
-            contact->setStatusDescription(statusDesc + "["+QString::number(idletime/60)+" mins]");
-        else
-            contact->setStatusDescription(statusDesc); */
-    }
-}
-#undef STATUS
-#include "meanwhileserver.moc"
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileserver.h kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileserver.h
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhileserver.h	2005-10-05 21:23:31.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhileserver.h	2005-12-21 17:09:18.000000000 +0800
@@ -1,77 +0,0 @@
-/*
-    meanwhileserver.h - server interface to an account
-
-    Copyright (c) 2003-2004 by Sivaram Gottimukkala  <suppandi@gmail.com>
-
-    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
-
-    *************************************************************************
-    *                                                                       *
-    * 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.                                   *
-    *                                                                       *
-    *************************************************************************
-*/
-#ifndef MEANWHILESERVER_H
-#define MEANWHILESERVER_H
-
-#include "kopetecontact.h"
-#include "meanwhilelibrary.h"
-#include "qdict.h"
-
-class MeanwhileServer : public QObject
-{
-    Q_OBJECT
-
-    public:
-        MeanwhileServer(QString server, int port);
-        ~MeanwhileServer();
-        bool bad();
-        int login(QString username, QString passwd);
-        void logoff();
-        void addContacts(const QDict<Kopete::Contact>& contacts);
-        void addContact(Kopete::Contact *contact,
-                        const QDict<Kopete::Contact>& contacts);
-        int sendIm(Kopete::Contact *contact, const QString & msg);
-        void sendTyping(Kopete::Contact *contact, bool isTyping);
-        void goAway(const QString &awayMsg);
-        void goDND(const QString &dndMsg);
-        void goActive(const QString &activeMsg);
-        void changeStatus(const QString &statusMesg);
-
-    signals:
-        void loginDone();
-        void mesgReceived(const QString &fromUser,
-                          const QString &mesg);
-        void userTyping(  const QString & user,
-                          bool isTyping);
-        void connectionLost();
-        void notificationAvailable(const QString &reason);
-
-    private:
-        MeanwhileLibrary *library;
-        QString server;
-        int port;
-        QDict<Kopete::Contact> contacts;
-
-    protected slots:
-        void slotLoginDone();
-        void slotConnectionLost();
-        void slotServerNotification(const QString &errMesg);
-        void slotUserStatusChanged(
-                                const QString & userid,
-                                bool isOnline,
-                                time_t idletime,
-                                int status,
-                                const QString & statusDesc);
-        void slotMesgReceived(
-                                const QString & fromUser,
-                                const QString & msg);
-        void slotUserTyping(
-                                const QString & user,
-                                bool isTyping);
-};
-
-#endif
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilesession.cpp kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilesession.cpp
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilesession.cpp	1970-01-01 08:00:00.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilesession.cpp	2005-12-21 17:09:21.000000000 +0800
@@ -0,0 +1,899 @@
+/*
+    meanwhilesession.cpp - interface to the 'C' meanwhile library
+
+    Copyright (c) 2003-2004 by Sivaram Gottimukkala  <suppandi@gmail.com>
+    Copyright (c) 2005      by Jeremy Kerr <jk@ozlabs.org>
+
+    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
+
+    *************************************************************************
+    *                                                                       *
+    * 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.                                   *
+    *                                                                       *
+    *************************************************************************
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+
+#include <kopetepassword.h>
+#include <kopetemessagemanager.h>
+#include <kopetegroup.h>
+#include <kopetecontactlist.h>
+#include "meanwhilesession.h"
+#include "meanwhileprotocol.h"
+
+#include <mw_channel.h>
+#include <mw_message.h>
+#include <mw_error.h>
+#include <mw_service.h>
+#include <mw_session.h>
+#include <mw_srvc_aware.h>
+#include <mw_srvc_conf.h>
+#include <mw_srvc_im.h>
+#include <mw_srvc_store.h>
+#include <mw_cipher.h>
+#include <mw_st_list.h>
+
+#define set_session_handler(a,b) sessionHandler.a = _handleSession ## b
+#define set_aware_handler(a,b)   awareHandler.a = _handleAware ## b
+#define set_aware_list_handler(a,b) \
+    awareListHandler.a = _handleAwareList ## b
+#define set_im_handler(a,b)   imHandler.a = _handleIm ## b
+
+#define get_protocol() (static_cast<MeanwhileProtocol *>(account->protocol()))
+
+MeanwhileSession::MeanwhileSession(MeanwhileAccount *account)
+{
+    HERE;
+    this->account = account;
+    session = 0L;
+    socket = 0L;
+    state = mwSession_STOPPED;
+
+    /* set up main session hander */
+    memset(&sessionHandler, 0, sizeof(sessionHandler));
+    set_session_handler(io_write,          IOWrite);
+    set_session_handler(io_close,          IOClose);
+    set_session_handler(on_stateChange,    StateChange);
+    set_session_handler(on_setPrivacyInfo, SetPrivacyInfo);
+    set_session_handler(on_setUserStatus,  SetUserStatus);
+    set_session_handler(on_admin,          Admin);
+    set_session_handler(on_announce,       Announce);
+    set_session_handler(clear,             Clear);
+
+    session = mwSession_new(&sessionHandler);
+    mwSession_setClientData(session, this, 0L);
+
+    /* set up the aware service */
+    memset(&awareHandler, 0, sizeof(awareHandler));
+    set_aware_handler(on_attrib, Attrib);
+
+    awareService = mwServiceAware_new(session, &awareHandler);
+    mwSession_addService(session, (struct mwService *)awareService);
+
+    /* create an aware list */
+    memset(&awareListHandler, 0, sizeof(awareListHandler));
+    set_aware_list_handler(on_aware,  Aware);
+    set_aware_list_handler(on_attrib, Attrib);
+    awareList = mwAwareList_new(awareService, &awareListHandler);
+    mwAwareList_setClientData(awareList, this, 0L);
+
+    /* set up an im service */
+    memset(&imHandler, 0, sizeof(imHandler));
+    set_im_handler(conversation_opened, ConvOpened);
+    set_im_handler(conversation_closed, ConvClosed);
+    set_im_handler(conversation_recv,   ConvReceived);
+    imHandler.place_invite = 0L;
+    imHandler.clear = 0L;
+
+    imService = mwServiceIm_new(session, &imHandler);
+    mwService_setClientData((struct mwService *)imService, this, 0L);
+    mwSession_addService(session, (struct mwService *) imService);
+
+    /* add resolve service */
+    resolveService = mwServiceResolve_new(session);
+    mwService_setClientData((struct mwService *)resolveService, this, 0L);
+    mwSession_addService(session, (struct mwService *) resolveService);
+
+    /* storage service */
+    storageService = mwServiceStorage_new(session);
+    mwService_setClientData((struct mwService *)storageService, this, 0L);
+    mwSession_addService(session, (struct mwService *) storageService);
+
+#if 0
+    /* conference service setup - just declines invites for now. */
+    memset(&conf_handler, 0, sizeof(conf_handler));
+    conf_handler.on_invited = _conference_invite;
+
+    srvc_conf = mwServiceConference_new(session, &conf_handler);
+    mwService_setClientData((struct mwService *)srvc_conf, this, 0L);
+    mwSession_addService(session, (struct mwService *) srvc_conf);
+#endif
+
+    /* add a necessary cipher */
+    mwSession_addCipher(session, mwCipher_new_RC2_40(session));
+}
+
+MeanwhileSession::~MeanwhileSession()
+{
+    HERE;
+    if (isConnected() || isConnecting())
+        disconnect();
+
+    mwSession_removeService(session, mwService_STORAGE);
+    mwSession_removeService(session, mwService_RESOLVE);
+    mwSession_removeService(session, mwService_IM);
+    mwSession_removeService(session, mwService_AWARE);
+
+    mwAwareList_free(awareList);
+    mwService_free(MW_SERVICE(storageService));
+    mwService_free(MW_SERVICE(resolveService));
+    mwService_free(MW_SERVICE(imService));
+    mwService_free(MW_SERVICE(awareService));
+    mwCipher_free(mwSession_getCipher(session, mwCipher_RC2_40));
+
+    mwSession_free(session);
+
+    if (socket)
+        delete socket;
+}
+
+/* external interface called by meanwhileaccount */
+void MeanwhileSession::connect(QString host, int port,
+        QString account, QString password)
+{
+    HERE;
+
+    KExtendedSocket *sock = new KExtendedSocket(host, port,
+            KExtendedSocket::bufferedSocket);
+
+    if (sock->connect()) {
+        KMessageBox::queuedMessageBox(0, KMessageBox::Error,
+                i18n( "Could not connect to server"), i18n("Meanwhile Plugin"),
+                KMessageBox::Notify);
+        delete sock;
+        return;
+    }
+    socket = sock;
+    /* we want to receive signals when there is data to read */
+    sock->enableRead(true);
+    QObject::connect(sock, SIGNAL(readyRead()), this,
+                     SLOT(slotSocketDataAvailable()));
+    QObject::connect(sock, SIGNAL(closed(int)), this,
+                     SLOT(slotSocketClosed(int)));
+
+    mwSession_setProperty(session, mwSession_AUTH_USER_ID,
+                    g_strdup(account.ascii()), g_free);
+    mwSession_setProperty(session, mwSession_AUTH_PASSWORD,
+                    g_strdup(password.ascii()), g_free);
+
+    /* go!! */
+    mwSession_start(session);
+}
+
+void MeanwhileSession::disconnect()
+{
+    HERE;
+    if (state == mwSession_STOPPED || state == mwSession_STOPPING)
+        return;
+
+    mwSession_stop(session, ERR_SUCCESS);
+}
+
+bool MeanwhileSession::isConnected()
+{
+	return mwSession_isStarted(session);
+}
+
+bool MeanwhileSession::isConnecting()
+{
+	return mwSession_isStarting(session);
+}
+
+static void free_id_block(void *data, void *p)
+{
+    if (p != 0L || data == 0L)
+        return;
+    struct mwAwareIdBlock *id = (struct mwAwareIdBlock *)data;
+    free(id->user);
+    free(id);
+}
+
+void MeanwhileSession::addContacts(const QDict<Kopete::Contact>& contacts)
+{
+    HERE;
+    QDictIterator<Kopete::Contact> it(contacts);
+    GList *buddies = 0L;
+
+    /** Convert our QDict of kopete contact to a GList of meanwhile buddies */
+    for( ; it.current(); ++it) {
+        MeanwhileContact *contact =
+                static_cast<MeanwhileContact *>(it.current());
+        struct mwAwareIdBlock *id = (struct mwAwareIdBlock *)
+            malloc(sizeof(*id));
+        if (id == 0L)
+            continue;
+        id->user = strdup(contact->meanwhileId().ascii());
+        id->community = 0L;
+        id->type = mwAware_USER;
+        buddies = g_list_append(buddies, id);
+    }
+
+    mwAwareList_addAware(awareList, buddies);
+
+    g_list_foreach(buddies, free_id_block, 0L);
+    g_list_free(buddies);
+}
+
+/* private functions used only by the meanwhile session object */
+void MeanwhileSession::addContact(const Kopete::Contact *contact)
+{
+    HERE;
+    struct mwAwareIdBlock id = { mwAware_USER,
+        strdup(static_cast<const MeanwhileContact *>(contact)
+                ->meanwhileId().ascii()),
+        0L };
+
+    GList *buddies = g_list_prepend(0L, &id);
+    mwAwareList_addAware(awareList, buddies);
+    g_list_free(buddies);
+    free(id.user);
+}
+
+int MeanwhileSession::sendMessage(Kopete::Message &message)
+{
+    HERE;
+    MeanwhileContact *contact =
+        static_cast<MeanwhileContact *>(message.to().first());
+    if (!contact) {
+        mwDebug() << "No target for message!" <<endl;
+        return 0;
+    }
+
+    struct mwIdBlock target = { strdup(contact->meanwhileId().ascii()), 0L };
+    struct mwConversation *conv;
+
+    conv = mwServiceIm_getConversation(imService, &target);
+    free(target.user);
+    if (conv == 0L) {
+        mwDebug() << "No target for conversation with '"
+            << contact->meanwhileId() << "'" << endl;
+        return 0;
+    }
+
+    struct ConversationData *convdata = (struct ConversationData *)
+        mwConversation_getClientData(conv);
+
+    if (convdata == 0L) {
+        convdata = createConversationData(conv, contact, true);
+        if (convdata == 0L) {
+            mwDebug() << "No memory for conversation data!" << endl;
+            return 0;
+        }
+    }
+
+    /* if there's other messages in the queue, or the conversation isn't open,
+     * then append to the queue instead of sending right away */
+    if ((convdata->queue && !convdata->queue->isEmpty()) ||
+            !mwConversation_isOpen(conv)) {
+        convdata->queue->append(message);
+        mwConversation_open(conv);
+
+    } else if (!mwConversation_send(conv, mwImSend_PLAIN,
+                message.plainBody().ascii())) {
+        convdata->chat->appendMessage(message);
+        convdata->chat->messageSucceeded();
+    }
+    return 1;
+}
+
+void MeanwhileSession::sendTyping(MeanwhileContact *contact, bool isTyping)
+{
+    HERE;
+    struct mwIdBlock target = { strdup(contact->meanwhileId().ascii()), 0L };
+    struct mwConversation *conv;
+
+    conv = mwServiceIm_getConversation(imService, &target);
+    free(target.user);
+    if (conv == 0L)
+        return;
+
+    if (mwConversation_isOpen(conv))
+        mwConversation_send(conv, mwImSend_TYPING, (void *)isTyping);
+}
+
+void MeanwhileSession::setStatus(Kopete::OnlineStatus status,
+        const QString msg)
+{
+    HERE;
+    mwDebug() << "setStatus: " << status.description() << "("
+        << status.internalStatus() << ")" << endl;
+    if (status.internalStatus() == 0)
+        return;
+
+    struct mwUserStatus stat;
+    mwUserStatus_clone(&stat, mwSession_getUserStatus(session));
+
+    free(stat.desc);
+
+    stat.status = (mwStatusType)status.internalStatus();
+    if (msg.isNull() || msg.isEmpty())
+        stat.desc = strdup(status.description().ascii());
+    else
+        stat.desc = strdup(msg.ascii());
+
+    mwSession_setUserStatus(session, &stat);
+    /* will free stat.desc */
+    mwUserStatus_clear(&stat);
+}
+
+void MeanwhileSession::syncContactsToServer()
+{
+    HERE;
+    struct mwSametimeList *list = mwSametimeList_new();
+
+    /* set up a fallback group for top-level contacts */
+    struct mwSametimeGroup *topstgroup = mwSametimeGroup_new(list,
+            mwSametimeGroup_DYNAMIC, "People");
+    mwSametimeGroup_setOpen(topstgroup, true);
+
+    QDictIterator<Kopete::Contact> it(account->contacts());
+    for( ; it.current(); ++it ) {
+        MeanwhileContact *contact =
+            static_cast<MeanwhileContact *>(it.current());
+
+        /* Find the group that the metacontact is in */
+        Kopete::MetaContact *mc = contact->metaContact();
+        /* myself doesn't have a metacontact */
+        if (mc == 0L)
+            continue;
+
+        Kopete::Group *contactgroup = mc->groups().getFirst();
+        if (contactgroup == 0L)
+            continue;
+
+        if (contactgroup->type() == Kopete::Group::Temporary)
+            continue;
+
+        struct mwSametimeGroup *stgroup;
+        if (contactgroup->type() == Kopete::Group::TopLevel) {
+            stgroup = topstgroup;
+        } else  {
+            /* find (or create) a matching sametime list group */
+            stgroup = mwSametimeList_findGroup(list,
+                        contactgroup->displayName().ascii());
+            if (stgroup == 0L) {
+                stgroup = mwSametimeGroup_new(list, mwSametimeGroup_DYNAMIC,
+                        contactgroup->displayName().ascii());
+            }
+            mwSametimeGroup_setOpen(stgroup, contactgroup->isExpanded());
+            mwSametimeGroup_setAlias(stgroup,
+                    contactgroup->pluginData(account->protocol(), "alias")
+                    .ascii());
+        }
+
+        /* now add the user (by IDBlock) */
+        struct mwIdBlock id =
+            { (gchar*)contact->meanwhileId().ascii(), 0L };
+        struct mwSametimeUser *stuser = mwSametimeUser_new(stgroup,
+                mwSametimeUser_NORMAL, &id);
+
+        mwSametimeUser_setAlias(stuser, contact->nickName().ascii());
+    }
+
+    /* store! */
+    struct mwPutBuffer *buf = mwPutBuffer_new();
+    struct mwStorageUnit *unit = mwStorageUnit_new(mwStore_AWARE_LIST);
+    struct mwOpaque *opaque = mwStorageUnit_asOpaque(unit);
+
+    mwSametimeList_put(buf, list);
+    mwPutBuffer_finalize(opaque, buf);
+
+    mwServiceStorage_save(storageService, unit, NULL, NULL, NULL);
+
+    mwSametimeList_free(list);
+}
+
+void MeanwhileSession::syncContactsFromServer()
+{
+    struct mwStorageUnit *unit = mwStorageUnit_new(mwStore_AWARE_LIST);
+    mwServiceStorage_load(storageService, unit, &_handleStorageLoad, 0L, 0L);
+}
+
+#define MEANWHILE_SESSION_BUFSIZ 4096
+
+void MeanwhileSession::slotSocketDataAvailable()
+{
+    HERE;
+    guchar *buf;
+    Q_LONG bytesRead;
+
+    if (socket == 0L)
+        return;
+
+    if (!(buf = (guchar *)malloc(MEANWHILE_SESSION_BUFSIZ))) {
+        mwDebug() << "buffer malloc failed" << endl;
+        return;
+    }
+
+    while (socket && socket->bytesAvailable() > 0) {
+        bytesRead = socket->readBlock((char *)buf, MEANWHILE_SESSION_BUFSIZ);
+        if (bytesRead < 0)
+            break;
+        mwSession_recv(session, buf, (unsigned int)bytesRead);
+    }
+    free(buf);
+}
+
+void MeanwhileSession::slotSocketClosed(int reason)
+{
+    HERE;
+
+    if (reason & KExtendedSocket::involuntary)
+        emit serverNotification(
+                QString("Lost connection with Meanwhile server"));
+
+    if (socket) {
+        delete socket;
+        socket = 0L;
+    }
+
+    mwSession_stop(session, 0x00);
+}
+
+
+Kopete::OnlineStatus MeanwhileSession::convertStatus(int mstatus)
+{
+    MeanwhileProtocol *protocol =
+        static_cast<MeanwhileProtocol *>(account->protocol());
+
+    switch (mstatus) {
+    case mwStatus_ACTIVE:
+        return protocol->statusOnline;
+        break;
+    case mwStatus_IDLE:
+        return protocol->statusIdle;
+        break;
+    case mwStatus_AWAY:
+        return protocol->statusAway;
+        break;
+    case mwStatus_BUSY:
+        return protocol->statusBusy;
+        break;
+    case 0:
+        return protocol->statusOffline;
+        break;
+    default:
+        mwDebug() << "unknown status lookup: " << mstatus << endl;
+    }
+    return protocol->statusOffline;
+}
+
+void MeanwhileSession::resolveContactNickname(MeanwhileContact *contact)
+{
+    /* @todo: FIXME: leak! */
+    char *id = strdup(contact->meanwhileId().ascii());
+    GList *query = g_list_prepend(NULL, id);
+    mwServiceResolve_resolve(resolveService, query, mwResolveFlag_USERS,
+            _handleResolveLookupResults, contact, NULL);
+}
+
+QString MeanwhileSession::getNickName(struct mwLoginInfo *logininfo)
+{
+    if (logininfo == 0L || logininfo->user_name == 0L)
+        return QString::null;
+    return getNickName(logininfo->user_name);
+}
+
+QString MeanwhileSession::getNickName(QString name)
+{
+
+    int index = name.find(" - ");
+    if (index != -1)
+        name = name.remove(0, index + 3);
+    index = name.find('/');
+    if (index != -1)
+        name = name.left(index);
+
+    return name;
+}
+
+MeanwhileContact *MeanwhileSession::conversationContact(
+        struct mwConversation *conv)
+{
+    struct mwIdBlock *target = mwConversation_getTarget(conv);
+    if (target == 0L || target->user == 0L) {
+        return 0L;
+    }
+    QString user(target->user);
+
+    MeanwhileContact *contact =
+        static_cast<MeanwhileContact *>(account->contacts()[user]);
+
+    struct mwLoginInfo *logininfo = mwConversation_getTargetInfo(conv);
+    QString name = getNickName(logininfo);
+
+    if (!contact) {
+	account->addContact(user, name, 0L, Kopete::Account::Temporary);
+        contact = static_cast<MeanwhileContact *>(account->contacts()[user]);
+    } else
+        contact->setNickName(name);
+
+    return contact;
+}
+
+/* priave session handling functions, called by libmeanwhile callbacks */
+void MeanwhileSession::handleSessionStateChange(
+        enum mwSessionState state, gpointer data)
+{
+    HERE;
+    this->state = state;
+
+    switch (state) {
+        case mwSession_STARTING:
+        case mwSession_HANDSHAKE:
+        case mwSession_HANDSHAKE_ACK:
+        case mwSession_LOGIN:
+        case mwSession_LOGIN_REDIR:
+        case mwSession_LOGIN_CONT:
+        case mwSession_LOGIN_ACK:
+            break;
+
+        case mwSession_STARTED:
+            {
+                struct mwUserStatus stat = { mwStatus_ACTIVE, 0, 0L };
+                mwSession_setUserStatus(session, &stat);
+                struct mwLoginInfo *logininfo = mwSession_getLoginInfo(session);
+                if (logininfo) {
+                    account->myself()->setNickName(getNickName(logininfo));
+                }
+                syncContactsFromServer();
+            }
+            break;
+
+        case mwSession_STOPPING:
+            {
+                unsigned int info = GPOINTER_TO_UINT(data);
+                if (info & ERR_FAILURE) {
+                    if (info == INCORRECT_LOGIN)
+                        account->password().setWrong();
+                    char *reason = mwError(info);
+                    emit serverNotification(QString(reason));
+                    free(reason);
+                }
+            }
+
+            emit sessionStateChange(
+                    static_cast<MeanwhileProtocol *>(account->protocol())
+		    ->statusOffline);
+            break;
+
+        case mwSession_STOPPED:
+            break;
+
+        case mwSession_UNKNOWN:
+        default:
+            mwDebug() << "Unhandled state change " << state << endl;
+    }
+}
+
+int MeanwhileSession::handleSessionIOWrite(const guchar *buffer,
+        unsigned int count)
+{
+    HERE;
+
+    if (socket == 0L)
+        return 1;
+
+    int remaining, retval = 0;
+    for (remaining = count; remaining > 0; remaining -= retval) {
+        retval = socket->writeBlock((char *)buffer, count);
+        if (retval <= 0)
+            return 1;
+    }
+    socket->flush();
+    return 0;
+}
+
+void MeanwhileSession::handleSessionAdmin(const char *text)
+{
+    HERE;
+    emit serverNotification(QString(text));
+}
+
+void MeanwhileSession::handleSessionAnnounce(struct mwLoginInfo *from,
+        gboolean /* may_reply */, const char *text)
+{
+    HERE;
+    QString message;
+    message.sprintf("Announcement from %s:\n%s", from->user_id, text);
+    emit serverNotification(message);
+}
+
+void MeanwhileSession::handleSessionSetUserStatus()
+{
+    struct mwUserStatus *userstatus = mwSession_getUserStatus(session);
+    emit sessionStateChange(convertStatus((unsigned int)userstatus->status));
+}
+
+void MeanwhileSession::handleSessionSetPrivacyInfo()
+{
+}
+
+void MeanwhileSession::handleSessionIOClose()
+{
+    HERE;
+
+    if (socket == 0L)
+        return;
+
+    QObject::disconnect(socket, SIGNAL(closed(int)),
+                     this, SLOT(slotSocketClosed(int)));
+    socket->flush();
+    socket->closeNow();
+
+    delete socket;
+    socket = 0L;
+}
+
+void MeanwhileSession::handleSessionClear()
+{
+}
+
+void MeanwhileSession::handleAwareAttrib(struct mwAwareAttribute * /* attrib */)
+{
+    HERE;
+}
+
+void MeanwhileSession::handleAwareListAware(struct mwAwareSnapshot *snapshot)
+{
+    HERE;
+    MeanwhileContact *contact = static_cast<MeanwhileContact *>
+        (account->contacts()[snapshot->id.user]);
+
+    if (contact == 0L)
+        return;
+
+    /* use the setUserStatus callback for status updates for myself. */
+    if (contact == account->myself())
+        return;
+
+    contact->setProperty(get_protocol()->statusMessage, snapshot->status.desc);
+    contact->setProperty(get_protocol()->awayMessage, snapshot->status.desc);
+
+    Kopete::OnlineStatus onlinestatus;
+    if (snapshot->online) {
+        onlinestatus = convertStatus(snapshot->status.status);
+        resolveContactNickname(contact);
+    } else {
+        onlinestatus = convertStatus(0);
+    }
+
+    contact->setOnlineStatus(onlinestatus);
+
+#if 0
+    /* Commented out in previous kopete/meanwhile plugin for some reason,
+     * but has still been ported to the new API.
+     */
+    time_t idletime = 0;
+    if (snapshot->status.status == mwStatus_IDLE) {
+	idletime = (snapshot->status.time == 0xdeadbeef) ?
+            0 : snapshot->status.time;
+        if (idletime != 0) {
+        contact->setStatusDescription(statusDesc + "[" +
+                QString::number(idletime/60)+" mins]");
+        }
+    } else
+        contact->setStatusDescription(snapshot->status.desc);
+#endif
+}
+
+void MeanwhileSession::handleAwareListAttrib(struct mwAwareIdBlock * /* id */,
+        struct mwAwareAttribute * /* attrib */)
+{
+    HERE;
+}
+
+struct MeanwhileSession::ConversationData
+    *MeanwhileSession::createConversationData(
+        struct mwConversation *conv, MeanwhileContact *contact,
+        bool createQueue)
+{
+    struct ConversationData *cd = new ConversationData();
+
+    if (cd == 0L)
+        return 0L;
+
+    cd->contact = contact;
+    cd->chat    = contact->manager(Kopete::Contact::CanCreate);
+    cd->chat->ref();
+    if (createQueue)
+        cd->queue = new QValueList<Kopete::Message>();
+
+    mwConversation_setClientData(conv, cd, 0L);
+
+    return cd;
+}
+
+void MeanwhileSession::handleImConvOpened(struct mwConversation *conv)
+{
+    HERE;
+
+    struct ConversationData *convdata =
+        (struct ConversationData *)mwConversation_getClientData(conv);
+
+    if (convdata == 0L) {
+        /* a new conversation */
+        convdata = createConversationData(conv, conversationContact(conv));
+
+        if (convdata == 0L) {
+            mwDebug() << "No memory for conversation data!" << endl;
+            return;
+        }
+
+    } else if (convdata->queue && !convdata->queue->isEmpty()) {
+        /* send any messages that were waiting for the conversation to open */
+        QValueList<Kopete::Message>::iterator it;
+        for (it = convdata->queue->begin(); it != convdata->queue->end();
+                ++it) {
+            mwConversation_send(conv, mwImSend_PLAIN,
+                    (*it).plainBody().ascii());
+            convdata->chat->appendMessage(*it);
+            convdata->chat->messageSucceeded();
+        }
+        convdata->queue->clear();
+        delete convdata->queue;
+        convdata->queue = 0L;
+    }
+    resolveContactNickname(convdata->contact);
+}
+
+void MeanwhileSession::handleImConvClosed(struct mwConversation *conv,
+        guint32)
+{
+    HERE;
+
+    ConversationData *convdata =
+        (ConversationData *)mwConversation_getClientData(conv);
+
+    if (!convdata)
+        return;
+
+    mwConversation_setClientData(conv, 0L, 0L);
+
+    convdata->chat->removeContact(convdata->contact);
+    convdata->chat->deref();
+    convdata->chat = 0L;
+    if (convdata->queue != 0L) {
+        convdata->queue->clear();
+        delete convdata->queue;
+        convdata->queue = 0L;
+    }
+    free(convdata);
+}
+
+void MeanwhileSession::handleImConvReceived(struct mwConversation *conv,
+        enum mwImSendType type, gconstpointer msg)
+{
+    HERE;
+    ConversationData *convdata =
+        (ConversationData *)mwConversation_getClientData(conv);
+
+    if (!convdata)
+        return;
+
+    switch (type) {
+    case mwImSend_PLAIN:
+        {
+            Kopete::Message message(convdata->contact, account->myself(),
+                    QString((char *)msg), Kopete::Message::Inbound);
+            convdata->chat->appendMessage(message);
+        }
+        break;
+    case mwImSend_TYPING:
+        convdata->chat->receivedTypingMsg(convdata->contact);
+        break;
+    default:
+        mwDebug() << "Unable to handle message type: " << type << endl;
+    }
+}
+
+void MeanwhileSession::handleResolveLookupResults(
+        struct mwServiceResolve * /* srvc */, guint32 /* id */,
+        guint32 /* code */, GList *results, gpointer data)
+{
+    struct mwResolveResult *result;
+    struct mwResolveMatch *match;
+
+    if (results == 0L)
+        return;
+    if ((result = (struct mwResolveResult *)results->data) == 0L)
+        return;
+
+    if (result->matches == 0L)
+        return;
+    if ((match = (struct mwResolveMatch *)result->matches->data) == 0L)
+        return;
+
+    mwDebug() << "resolve lookup returned '" << match->name << "'" << endl;
+
+    MeanwhileContact *contact = (MeanwhileContact *)data;
+    if (contact == 0L)
+        return;
+
+    contact->setNickName(getNickName(match->name));
+}
+
+void MeanwhileSession::handleStorageLoad(struct mwServiceStorage * /* srvc */,
+        guint32 result, struct mwStorageUnit *item, gpointer /* data */)
+{
+    HERE;
+    if (result != ERR_SUCCESS) {
+        mwDebug() << "contact list load returned " << result << endl;
+        return;
+    }
+
+    struct mwGetBuffer *buf = mwGetBuffer_wrap(mwStorageUnit_asOpaque(item));
+    struct mwSametimeList *list = mwSametimeList_new();
+    mwSametimeList_get(buf, list);
+
+    GList *gl, *glf, *cl, *clf;
+
+    Kopete::ContactList *contactlist = Kopete::ContactList::self();
+
+    for (glf = gl = mwSametimeList_getGroups(list); gl; gl = gl->next) {
+        struct mwSametimeGroup *stgroup = (struct mwSametimeGroup *)gl->data;
+
+        Kopete::Group *group =
+            contactlist->findGroup(mwSametimeGroup_getName(stgroup));
+        group->setPluginData(account->protocol(), "alias",
+                mwSametimeGroup_getAlias(stgroup));
+
+        for (clf = cl = mwSametimeGroup_getUsers(stgroup); cl; cl = cl->next) {
+            struct mwSametimeUser *stuser = (struct mwSametimeUser *)cl->data;
+
+            MeanwhileContact *contact = static_cast<MeanwhileContact *>
+                (account->contacts()[mwSametimeUser_getUser(stuser)]);
+
+            if (contact != 0L)
+                continue;
+
+            account->addContact(mwSametimeUser_getUser(stuser),
+                    mwSametimeUser_getAlias(stuser), group,
+                    Kopete::Account::ChangeKABC);
+        }
+        g_list_free(clf);
+    }
+    g_list_free(glf);
+
+    mwSametimeList_free(list);
+}
+
+#if 0
+MEANWHILE_HOOK_CONFERENCE(conference_invite,
+        (struct mwConference *conf, struct mwLoginInfo *inviter,
+         const char *invite),
+        (conf, inviter, invite))
+{
+    HERE;
+    QString message;
+
+    message.sprintf("%s has invited you to a conference called \"%s\"\n"
+        "However, this version of the meanwhile plugin does "
+        "not support conferences, so the invitiation has been declined.",
+        inviter->user_id, invite);
+
+    mwConference_reject(conf, ERR_SUCCESS,
+            "Sorry, my client doesn't support conferences!");
+    KMessageBox::queuedMessageBox(0, KMessageBox::Sorry , message,
+            i18n("Meanwhile Plugin: Conference invitation"),
+            KMessageBox::Notify);
+}
+#endif
+#include "meanwhilesession.moc"
diff -urN kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilesession.h kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilesession.h
--- kdenetwork-3.4.3.orig/kopete/protocols/meanwhile/meanwhilesession.h	1970-01-01 08:00:00.000000000 +0800
+++ kdenetwork-3.4.3/kopete/protocols/meanwhile/meanwhilesession.h	2005-12-21 17:09:21.000000000 +0800
@@ -0,0 +1,341 @@
+/*
+    meanwhilesession.h - interface to the 'C' meanwhile session
+
+    Copyright (c) 2005      by Jeremy Kerr <jk@ozlabs.org>
+
+    *************************************************************************
+    *                                                                       *
+    * 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.                                   *
+    *                                                                       *
+    *************************************************************************
+*/
+#ifndef MEANWHILESESSION_H
+#define MEANWHILESESSION_H
+
+#include "meanwhileaccount.h"
+#include "meanwhilecontact.h"
+#include <kextendedsocket.h>
+
+#include <mw_session.h>
+#include <mw_service.h>
+#include <mw_srvc_aware.h>
+#include <mw_srvc_im.h>
+#include <mw_srvc_resolve.h>
+
+/**
+ * A class to handle libmeanwhile session management.
+ */
+class MeanwhileSession : public QObject
+{
+    Q_OBJECT
+
+public:
+    /**
+     * Create a session. By default, the session is not connected - you will
+     * need to call login() to initiate the connection process.
+     * @param account The account that the connection is for
+     */
+    MeanwhileSession(MeanwhileAccount *account);
+
+    /**
+     * Destroy the session
+     */
+    ~MeanwhileSession();
+
+    /**
+     * Connect to the server. This will open a socket and start login. Note that
+     * the connection process is ascychronous - a loginDone() signal will be
+     * emitted when sucessfully logged in.
+     */
+    void connect(QString host, int port, QString account, QString password);
+
+    /**
+     * Disconnect from the server.
+     */
+    void disconnect();
+
+    /**
+     * Set our (the local contact's) online status. The internalStatus of the
+     * state argument will be used to define the state message we send - it
+     * should be one of the Status enum fields (and not Offline)
+     * @param state the new state of the local user
+     * @param msg a custom message to use, if required
+     */
+    void setStatus(Kopete::OnlineStatus status,
+            const QString msg = QString::null);
+
+    /**
+     * Add a single contact to be registered for status updates
+     * @param contact The contact to register
+     */
+    void addContact(const Kopete::Contact *contact);
+
+    /**
+     * Add a list of contacts to be registered for status updates
+     * @param contact The list of contacts to register
+     */
+    void addContacts(const QDict<Kopete::Contact>& contacts);
+
+    /**
+     * Send a message (with recipient specified).
+     * @param message The message to send
+     * @return non-zero if  the message could be sent
+     */
+    int sendMessage(Kopete::Message &message);
+
+    /**
+     * Send a typing notification to a contact
+     * @param contact  The contact to notify
+     * @param isTyping If true, the typing notification is set
+     */
+    void sendTyping(MeanwhileContact *contact, bool isTyping);
+
+    /**
+     * Determine if the session is connected to the server
+     * @return true if the session is connected
+     */
+    bool isConnected();
+
+    /**
+     * Determine if the session is in the process of connecting to the server
+     * @return true if the session is connecting
+     */
+    bool isConnecting();
+
+signals:
+    /**
+     * Emitted when the status of the connection changes
+     * @param status The new status of the session
+     */
+    void sessionStateChange(Kopete::OnlineStatus status);
+
+    /**
+     * Emitted when a notification is received from the server, or other
+     * out-of-band data (eg, the password is incorrect).
+     * @param mesgString A description of the notification
+     */
+    void serverNotification(const QString &mesgString);
+
+private:
+    /** Main libmeanwhile session object */
+    struct mwSession *session;
+
+    /** Session handler */
+    struct mwSessionHandler sessionHandler;
+
+    /** Aware service */
+    struct mwServiceAware *awareService;
+
+    /** Aware handler */
+    struct mwAwareHandler awareHandler;
+
+    /** Aware List Handler */
+    struct mwAwareListHandler awareListHandler;
+
+    /** The aware list */
+    struct mwAwareList *awareList;
+
+    /** Aware service */
+    struct mwSer