Code

manually merging the INKBOARD_PEDRO branch into trunk
authordaleharvey <daleharvey@users.sourceforge.net>
Fri, 23 Jun 2006 13:15:16 +0000 (13:15 +0000)
committerdaleharvey <daleharvey@users.sourceforge.net>
Fri, 23 Jun 2006 13:15:16 +0000 (13:15 +0000)
84 files changed:
configure.ac
mkinstalldirs
pedro.ini [new file with mode: 0644]
src/Makefile.am
src/Makefile_insert
src/desktop.cpp
src/document.cpp
src/document.h
src/file.cpp
src/jabber_whiteboard/Makefile_insert
src/jabber_whiteboard/buddy-list-manager.cpp [deleted file]
src/jabber_whiteboard/buddy-list-manager.h [deleted file]
src/jabber_whiteboard/callbacks.cpp [deleted file]
src/jabber_whiteboard/callbacks.h [deleted file]
src/jabber_whiteboard/chat-handler.cpp [deleted file]
src/jabber_whiteboard/chat-handler.h [deleted file]
src/jabber_whiteboard/connection-establishment.cpp [deleted file]
src/jabber_whiteboard/defines.h
src/jabber_whiteboard/deserializer.cpp [deleted file]
src/jabber_whiteboard/deserializer.h [deleted file]
src/jabber_whiteboard/empty.cpp
src/jabber_whiteboard/error-codes.h [deleted file]
src/jabber_whiteboard/inkboard-document.cpp [new file with mode: 0644]
src/jabber_whiteboard/inkboard-document.h [new file with mode: 0644]
src/jabber_whiteboard/inkboard-session.cpp [new file with mode: 0644]
src/jabber_whiteboard/inkboard-session.h [new file with mode: 0644]
src/jabber_whiteboard/internal-constants.cpp
src/jabber_whiteboard/internal-constants.h
src/jabber_whiteboard/invitation-confirm-dialog.cpp
src/jabber_whiteboard/invitation-confirm-dialog.h
src/jabber_whiteboard/invitation-handlers.cpp [new file with mode: 0644]
src/jabber_whiteboard/jabber-handlers.cpp [deleted file]
src/jabber_whiteboard/jabber-handlers.h [deleted file]
src/jabber_whiteboard/keynode.cpp [new file with mode: 0644]
src/jabber_whiteboard/keynode.h [new file with mode: 0644]
src/jabber_whiteboard/message-aggregator.cpp
src/jabber_whiteboard/message-aggregator.h
src/jabber_whiteboard/message-contexts.cpp [deleted file]
src/jabber_whiteboard/message-contexts.h [deleted file]
src/jabber_whiteboard/message-handler.cpp [deleted file]
src/jabber_whiteboard/message-handler.h [deleted file]
src/jabber_whiteboard/message-node.h
src/jabber_whiteboard/message-processors.cpp [deleted file]
src/jabber_whiteboard/message-processors.h [deleted file]
src/jabber_whiteboard/message-queue.cpp
src/jabber_whiteboard/message-queue.h
src/jabber_whiteboard/message-tags.cpp
src/jabber_whiteboard/message-tags.h
src/jabber_whiteboard/message-utilities.cpp
src/jabber_whiteboard/message-utilities.h
src/jabber_whiteboard/message-verifier.h [new file with mode: 0644]
src/jabber_whiteboard/new-inkboard-document.cpp [new file with mode: 0644]
src/jabber_whiteboard/new-inkboard-document.h [new file with mode: 0644]
src/jabber_whiteboard/node-tracker-event-tracker.cpp [deleted file]
src/jabber_whiteboard/node-tracker-event-tracker.h [deleted file]
src/jabber_whiteboard/node-tracker-observer.h [deleted file]
src/jabber_whiteboard/node-tracker.cpp
src/jabber_whiteboard/node-tracker.h
src/jabber_whiteboard/node-utilities.cpp
src/jabber_whiteboard/node-utilities.h
src/jabber_whiteboard/pedrodom.cpp [deleted file]
src/jabber_whiteboard/pedrodom.h [deleted file]
src/jabber_whiteboard/pedroxmpp.cpp [deleted file]
src/jabber_whiteboard/pedroxmpp.h [deleted file]
src/jabber_whiteboard/serializer.cpp [deleted file]
src/jabber_whiteboard/serializer.h [deleted file]
src/jabber_whiteboard/session-file-player.cpp [deleted file]
src/jabber_whiteboard/session-file-player.h [deleted file]
src/jabber_whiteboard/session-file-selector.cpp
src/jabber_whiteboard/session-file-selector.h
src/jabber_whiteboard/session-file.cpp [deleted file]
src/jabber_whiteboard/session-file.h [deleted file]
src/jabber_whiteboard/session-manager.cpp
src/jabber_whiteboard/session-manager.h
src/jabber_whiteboard/tracker-node.h
src/jabber_whiteboard/typedefs.h
src/jabber_whiteboard/undo-stack-observer.cpp [deleted file]
src/jabber_whiteboard/undo-stack-observer.h [deleted file]
src/menus-skeleton.h
src/ui/dialog/Makefile_insert
src/ui/dialog/dialog-manager.cpp
src/ui/view/edit-widget.cpp
src/verbs.cpp
src/verbs.h

index 8ababdbbbd7d1ab02f560abfca9336d0124c533d..e83e54676ed53cfba601b9dfd3a4daa9119b2a9d 100644 (file)
@@ -464,29 +464,33 @@ dnl Inkboard dependency checking
 dnl ******************************
 
 with_inkboard="no"
+with_inkboard_ssl="no"
 
-AC_MSG_CHECKING(for loudmouth-1.0+)
+INKBOARD_CFLAGS=""
 
 AC_ARG_ENABLE(inkboard,
                AS_HELP_STRING([--enable-inkboard], [enable Inkboard online whiteboard facility (disabled by default)]),
        with_inkboard=$enableval,with_inkboard=no)
 
 if test "x$with_inkboard" = "xyes"; then
-       PKG_CHECK_MODULES(LIBLOUDMOUTH, loudmouth-1.0, loudmouth_ok=yes, loudmouth_ok=no)
-       if test "x$loudmouth_ok" = "xyes"; then
                with_inkboard="yes"
                AC_DEFINE(WITH_INKBOARD,1,[Build in Inkboard support])
-       else
-               with_inkboard="no"
-       fi
+               
+               dnl Test for OpenSSL
+               PKG_CHECK_MODULES(INKBOARD, openssl, with_inkboard_ssl=yes, with_inkboard_ssl=no)
+               if test "x$with_inkboard_ssl" = "xyes"; then
+                       dnl OpenSSL found; enable SSL support in Pedro
+                       INKBOARD_CFLAGS="$INKBOARD_CFLAGS -DHAVE_SSL"
+                       AC_DEFINE(WITH_INKBOARD_SSL,1,[Build in SSL support for Inkboard])
+               fi
 else
        with_inkboard="no"
 fi
 
 AC_MSG_RESULT($with_inkboard)
 AM_CONDITIONAL(WITH_INKBOARD, test "x$with_inkboard" = "xyes")
-AC_SUBST(LIBLOUDMOUTH_CFLAGS)
-AC_SUBST(LIBLOUDMOUTH_LIBS)
+AC_SUBST(INKBOARD_LIBS)
+AC_SUBST(INKBOARD_CFLAGS)
 
 dnl ******************************
 dnl   Unconditional dependencies
@@ -801,6 +805,7 @@ src/libnr/makefile
 src/libnrtype/makefile
 src/libavoid/makefile
 src/livarot/makefile
+src/pedro/makefile
 src/jabber_whiteboard/makefile
 src/removeoverlap/makefile
 src/svg/makefile
@@ -862,4 +867,5 @@ Configuration:
         Use relocation support:   ${enable_binreloc}
        Enable LittleCms:         ${enable_lcms}
        Enable Inkboard:          ${with_inkboard}
+       Enable SSL in Inkboard:   ${with_inkboard_ssl}
 "
index d2d5f21b611235316317197d3a32c2dff5897a6f..259dbfcd35789bd0f087803d193cfd924f9a5f34 100755 (executable)
@@ -1,21 +1,33 @@
 #! /bin/sh
 # mkinstalldirs --- make directory hierarchy
-# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+
+scriptversion=2005-06-29.22
+
+# Original author: Noah Friedman <friedman@prep.ai.mit.edu>
 # Created: 1993-05-16
-# Public domain
+# Public domain.
+#
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
 
 errstatus=0
-dirmode=""
+dirmode=
 
 usage="\
-Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
+Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
+
+Create each directory DIR (with mode MODE, if specified), including all
+leading file name components.
+
+Report bugs to <bug-automake@gnu.org>."
 
 # process command line arguments
 while test $# -gt 0 ; do
   case $1 in
     -h | --help | --h*)         # -h for help
-      echo "$usage" 1>&2
-      exit 0
+      echo "$usage"
+      exit $?
       ;;
     -m)                         # -m PERM arg
       shift
@@ -23,6 +35,10 @@ while test $# -gt 0 ; do
       dirmode=$1
       shift
       ;;
+    --version)
+      echo "$0 $scriptversion"
+      exit $?
+      ;;
     --)                         # stop option processing
       shift
       break
@@ -50,30 +66,58 @@ case $# in
   0) exit 0 ;;
 esac
 
+# Solaris 8's mkdir -p isn't thread-safe.  If you mkdir -p a/b and
+# mkdir -p a/c at the same time, both will detect that a is missing,
+# one will create a, then the other will try to create a and die with
+# a "File exists" error.  This is a problem when calling mkinstalldirs
+# from a parallel make.  We use --version in the probe to restrict
+# ourselves to GNU mkdir, which is thread-safe.
 case $dirmode in
   '')
-    if mkdir -p -- . 2>/dev/null; then
+    if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
       echo "mkdir -p -- $*"
       exec mkdir -p -- "$@"
+    else
+      # On NextStep and OpenStep, the `mkdir' command does not
+      # recognize any option.  It will interpret all options as
+      # directories to create, and then abort because `.' already
+      # exists.
+      test -d ./-p && rmdir ./-p
+      test -d ./--version && rmdir ./--version
     fi
     ;;
   *)
-    if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+    if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
+       test ! -d ./--version; then
       echo "mkdir -m $dirmode -p -- $*"
       exec mkdir -m "$dirmode" -p -- "$@"
+    else
+      # Clean up after NextStep and OpenStep mkdir.
+      for d in ./-m ./-p ./--version "./$dirmode";
+      do
+        test -d $d && rmdir $d
+      done
     fi
     ;;
 esac
 
 for file
 do
-  set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+  case $file in
+    /*) pathcomp=/ ;;
+    *)  pathcomp= ;;
+  esac
+  oIFS=$IFS
+  IFS=/
+  set fnord $file
   shift
+  IFS=$oIFS
 
-  pathcomp=
   for d
   do
-    pathcomp="$pathcomp$d"
+    test "x$d" = x && continue
+
+    pathcomp=$pathcomp$d
     case $pathcomp in
       -*) pathcomp=./$pathcomp ;;
     esac
@@ -84,21 +128,21 @@ do
       mkdir "$pathcomp" || lasterr=$?
 
       if test ! -d "$pathcomp"; then
-       errstatus=$lasterr
+       errstatus=$lasterr
       else
-       if test ! -z "$dirmode"; then
+       if test ! -z "$dirmode"; then
          echo "chmod $dirmode $pathcomp"
-         lasterr=""
-         chmod "$dirmode" "$pathcomp" || lasterr=$?
+         lasterr=
+         chmod "$dirmode" "$pathcomp" || lasterr=$?
 
-         if test ! -z "$lasterr"; then
-           errstatus=$lasterr
-         fi
-       fi
+         if test ! -z "$lasterr"; then
+           errstatus=$lasterr
+         fi
+       fi
       fi
     fi
 
-    pathcomp="$pathcomp/"
+    pathcomp=$pathcomp/
   done
 done
 
@@ -107,5 +151,8 @@ exit $errstatus
 # Local Variables:
 # mode: shell-script
 # sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
 # End:
-# mkinstalldirs ends here
diff --git a/pedro.ini b/pedro.ini
new file mode 100644 (file)
index 0000000..ce832b4
--- /dev/null
+++ b/pedro.ini
@@ -0,0 +1,15 @@
+<pedro>
+    <muc>
+        <group>inkscape</group>
+        <host>conference.gristle.org</host>
+        <nick></nick>
+        <password></password>
+    </muc>
+    <account>
+        <name>Dale</name>
+        <host>gristle.org</host>
+        <port>5222</port>
+        <username>Dale</username>
+        <password>hail99</password>
+    </account>
+</pedro>
index 9b284e27d356fa49373ddde9f1c84ab7a88c8d07..090b4c683e3d9d27005b3bfe70ac64cc16b360c8 100644 (file)
@@ -18,7 +18,7 @@ INCLUDES =    \
        $(FREETYPE_CFLAGS)      \
        $(GNOME_PRINT_CFLAGS)   \
        $(GNOME_VFS_CFLAGS)     \
-       $(LIBLOUDMOUTH_CFLAGS) \
+       $(INKBOARD_CFLAGS) \
        $(XFT_CFLAGS)   \
        -DPOTRACE=\"potrace\"   \
        $(INKSCAPE_CFLAGS) \
@@ -36,6 +36,7 @@ include extension/script/Makefile_insert
 include helper/Makefile_insert
 include inkjar/Makefile_insert
 include io/Makefile_insert
+include pedro/Makefile_insert
 include jabber_whiteboard/Makefile_insert
 include libcroco/Makefile_insert
 include libnr/Makefile_insert
@@ -64,6 +65,7 @@ noinst_LIBRARIES =    \
        libinkpre.a     \
        application/libinkapp.a \
        dialogs/libspdialogs.a  \
+       pedro/libpedro.a \
        jabber_whiteboard/libjabber_whiteboard.a \
        display/libspdisplay.a  \
        dom/libdom.a    \
@@ -126,6 +128,7 @@ EXTRA_DIST =        \
        io/makefile.in  \
        io/crystalegg.xml       \
        io/doc2html.xsl         \
+       pedro/makefile.in       \
        jabber_whiteboard/makefile.in   \
        libcroco/makefile.in    \
        libnr/makefile.in       \
index f6c591d831546b22a565ce7b2598df9bce2eb8c8..c3182f3cc1115309ddb096514a8b7bd12e251891 100644 (file)
@@ -262,6 +262,7 @@ inkscape_private_libs =     \
        ui/dialog/libuidialog.a \
        dialogs/libspdialogs.a  \
        jabber_whiteboard/libjabber_whiteboard.a \
+       pedro/libpedro.a        \
        trace/libtrace.a        \
        svg/libspsvg.a          \
        widgets/libspwidgets.a  \
@@ -300,7 +301,8 @@ all_libs =                  \
        $(win32ldflags)         \
        $(PERL_LIBS)            \
        $(PYTHON_LIBS)  \
-       $(LIBLOUDMOUTH_LIBS) 
+       $(LIBLOUDMOUTH_LIBS) \
+       $(INKBOARD_LIBS)
 
 desktop.$(OBJEXT): helper/sp-marshal.h
 document.$(OBJEXT): helper/sp-marshal.h inkscape_version.h
index 7d99043421fb2272c7bdd05221481cf7c1206d2b..49a43bc37b53e98bdfbb7064fe0c7d53cd649aaa 100644 (file)
 #include "message-context.h"
 #include "layer-manager.h"
 
-#ifdef WITH_INKBOARD
-#include "jabber_whiteboard/session-manager.h"
-#endif
-
 namespace Inkscape { namespace XML { class Node; }}
 
 // Callback declarations
@@ -245,14 +241,6 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas)
     /* Ugly hack */
     _namedview_modified (namedview, SP_OBJECT_MODIFIED_FLAG, this);
 
-       /* Construct SessionManager
-        *
-        * SessionManager construction needs to be done after document connection
-        */
-#ifdef WITH_INKBOARD
-       _whiteboard_session_manager = new Inkscape::Whiteboard::SessionManager(this);
-#endif
-
 /* Set up notification of rebuilding the document, this allows
        for saving object related settings in the document. */
     _reconstruction_start_connection =
@@ -325,12 +313,6 @@ void SPDesktop::destroy()
         drawing = NULL;
     }
 
-#ifdef WITH_INKBOARD
-       if (_whiteboard_session_manager) {
-               delete _whiteboard_session_manager;
-       }
-#endif
-
     delete _guides_message_context;
     _guides_message_context = NULL;
 
index e42f6c8cb57029c2b55e4225e76582c0b50c596e..cf03f4188391a87adb218d3c5744c6b5736f6eff 100644 (file)
@@ -207,7 +207,7 @@ void SPDocument::reset_key (void *dummy)
     actionkey = NULL;
 }
 
-static SPDocument *
+SPDocument *
 sp_document_create(Inkscape::XML::Document *rdoc,
                    gchar const *uri,
                    gchar const *base,
index 4d293e981479a12f1fa68c0b7533621aef8bbd77..9739b69719baca6dbc9a4c38e76c87387b1e67cc 100644 (file)
@@ -135,6 +135,9 @@ SPDocument *sp_document_new_dummy();
 SPDocument *sp_document_ref (SPDocument *doc);
 SPDocument *sp_document_unref (SPDocument *doc);
 
+
+SPDocument *sp_document_create(Inkscape::XML::Document *rdoc, gchar const *uri, gchar const *base, gchar const *name, unsigned int keepalive);
+
 /*
  * Access methods
  */
index 5c236da82aade712cd236b5dc18831455a495f65..679c28801c5a6a40a5e8f2ce918e7a9012bd28d6 100644 (file)
@@ -204,9 +204,6 @@ sp_file_open(gchar const *uri, Inkscape::Extension::Extension *key, bool add_to_
         // resize the window to match the document properties
         // (this may be redundant for new windows... if so, move to the "virgin"
         //  section above)
-#ifdef WITH_INKBOARD
-               desktop->whiteboard_session_manager()->setDesktop(desktop);
-#endif
         sp_namedview_window_from_document(desktop);
 
         if (add_to_recent) {
index 2603f9c67d4d6a3cb80c7003865394c0346717bb..c510b34a0df0e7b1521573a9f2219400cb625033 100644 (file)
@@ -9,59 +9,34 @@ jabber_whiteboard/clean:
        rm -f jabber_whiteboard/libjabber_whiteboard.a $(jabber_whiteboard_libjabber_whiteboard_a_OBJECTS)
 
 jabber_whiteboard_SOURCES = \
-       jabber_whiteboard/buddy-list-manager.cpp \
-       jabber_whiteboard/buddy-list-manager.h \
-       jabber_whiteboard/callbacks.cpp \
-       jabber_whiteboard/callbacks.h \
-       jabber_whiteboard/chat-handler.cpp \
-       jabber_whiteboard/chat-handler.h \
-       jabber_whiteboard/connection-establishment.cpp \
        jabber_whiteboard/defines.h \
-       jabber_whiteboard/deserializer.cpp \
-       jabber_whiteboard/deserializer.h \
-       jabber_whiteboard/error-codes.h \
+       jabber_whiteboard/empty.cpp \
+       jabber_whiteboard/keynode.cpp \
+       jabber_whiteboard/keynode.h \
        jabber_whiteboard/internal-constants.cpp \
        jabber_whiteboard/internal-constants.h \
-       jabber_whiteboard/invitation-confirm-dialog.cpp \
-       jabber_whiteboard/invitation-confirm-dialog.h \
-       jabber_whiteboard/jabber-handlers.cpp \
-       jabber_whiteboard/jabber-handlers.h \
        jabber_whiteboard/message-aggregator.cpp \
        jabber_whiteboard/message-aggregator.h \
-       jabber_whiteboard/message-contexts.cpp \
-       jabber_whiteboard/message-contexts.h \
-       jabber_whiteboard/message-handler.cpp \
-       jabber_whiteboard/message-handler.h \
        jabber_whiteboard/message-node.h \
-       jabber_whiteboard/message-processors.cpp \
-       jabber_whiteboard/message-processors.h \
        jabber_whiteboard/message-queue.cpp \
        jabber_whiteboard/message-queue.h \
        jabber_whiteboard/message-tags.cpp \
        jabber_whiteboard/message-tags.h \
        jabber_whiteboard/message-utilities.cpp \
        jabber_whiteboard/message-utilities.h \
-       jabber_whiteboard/node-tracker.cpp \
-       jabber_whiteboard/node-tracker-event-tracker.cpp \
-       jabber_whiteboard/node-tracker-event-tracker.h \
-       jabber_whiteboard/node-tracker.h \
-       jabber_whiteboard/node-tracker-observer.h \
-       jabber_whiteboard/node-utilities.cpp \
-       jabber_whiteboard/node-utilities.h \
-       jabber_whiteboard/serializer.cpp \
-       jabber_whiteboard/serializer.h \
-       jabber_whiteboard/session-file.cpp \
-       jabber_whiteboard/session-file.h \
-       jabber_whiteboard/session-file-player.cpp \
-       jabber_whiteboard/session-file-player.h \
+       jabber_whiteboard/new-inkboard-document.cpp \
+       jabber_whiteboard/new-inkboard-document.h \
+       jabber_whiteboard/inkboard-document.cpp \
+       jabber_whiteboard/inkboard-document.h \
+       jabber_whiteboard/invitation-confirm-dialog.cpp \
+       jabber_whiteboard/invitation-confirm-dialog.h \
+       jabber_whiteboard/invitation-handlers.cpp \
        jabber_whiteboard/session-file-selector.cpp \
        jabber_whiteboard/session-file-selector.h \
        jabber_whiteboard/session-manager.cpp \
        jabber_whiteboard/session-manager.h \
        jabber_whiteboard/tracker-node.h \
-       jabber_whiteboard/typedefs.h \
-       jabber_whiteboard/undo-stack-observer.cpp \
-       jabber_whiteboard/undo-stack-observer.h
+       jabber_whiteboard/typedefs.h 
 
 
 if WITH_INKBOARD
diff --git a/src/jabber_whiteboard/buddy-list-manager.cpp b/src/jabber_whiteboard/buddy-list-manager.cpp
deleted file mode 100644 (file)
index 4cce230..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * Whiteboard session manager
- * Buddy list management facility
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-
-#include <sigc++/sigc++.h>
-#include <set>
-
-#include "jabber_whiteboard/typedefs.h"
-#include "jabber_whiteboard/buddy-list-manager.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-BuddyListManager::BuddyListManager() { }
-BuddyListManager::~BuddyListManager() { }
-
-void
-BuddyListManager::addInsertListener(BuddyListListener listener)
-{
-       this->_sig_insert.connect(listener);
-}
-
-void
-BuddyListManager::addEraseListener(BuddyListListener listener)
-{
-       this->_sig_erase.connect(listener);
-}
-
-void
-BuddyListManager::insert(std::string& jid)
-{
-       this->_bl.insert(jid);
-       this->_sig_insert.emit(jid);
-}
-
-void
-BuddyListManager::erase(std::string& jid)
-{
-       this->_bl.erase(jid);
-       this->_sig_erase.emit(jid);
-}
-
-BuddyList::iterator
-BuddyListManager::begin()
-{
-       return this->_bl.begin();
-}
-
-BuddyList::iterator
-BuddyListManager::end()
-{
-       return this->_bl.end();
-}
-
-BuddyList&
-BuddyListManager::getList()
-{
-       return this->_bl;
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/buddy-list-manager.h b/src/jabber_whiteboard/buddy-list-manager.h
deleted file mode 100644 (file)
index fcd0bb6..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Whiteboard session manager
- * Buddy list management facility
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_BUDDYLIST_MANAGER_H__
-#define __WHITEBOARD_BUDDYLIST_MANAGER_H__
-
-#include <string>
-#include <sigc++/sigc++.h>
-#include "jabber_whiteboard/typedefs.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-class BuddyListManager {
-public:
-       BuddyListManager();
-       ~BuddyListManager();
-       void insert(std::string& jid);
-       void erase(std::string& jid);
-       BuddyList::iterator begin();
-       BuddyList::iterator end();
-
-       void addInsertListener(BuddyListListener listener);
-       void addEraseListener(BuddyListListener listener);
-
-       BuddyList& getList();
-private:
-       BuddyList _bl;
-       BuddyListSignal _sig_insert;
-       BuddyListSignal _sig_erase;
-
-};
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/callbacks.cpp b/src/jabber_whiteboard/callbacks.cpp
deleted file mode 100644 (file)
index 31f5366..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * Whiteboard session manager
- * Message dispatch devices and timeout triggers
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-extern "C" {
-#include <loudmouth/loudmouth.h>
-}
-
-#include <glibmm/i18n.h>
-
-#include "message-stack.h"
-#include "document.h"
-#include "desktop-handles.h"
-
-#include "jabber_whiteboard/undo-stack-observer.h"
-#include "jabber_whiteboard/jabber-handlers.h"
-#include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/typedefs.h"
-#include "jabber_whiteboard/session-manager.h"
-#include "jabber_whiteboard/message-queue.h"
-#include "jabber_whiteboard/message-handler.h"
-#include "jabber_whiteboard/message-node.h"
-#include "jabber_whiteboard/callbacks.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-Callbacks::Callbacks(SessionManager* sm) : _sm(sm) 
-{
-       this->_sd = this->_sm->session_data;
-}
-
-Callbacks::~Callbacks() 
-{
-}
-
-bool
-Callbacks::dispatchSendQueue()
-{
-       // If we're not in a whiteboard session, don't dispatch anything
-       if (!(this->_sd->status[IN_WHITEBOARD])) {
-               return false;
-       }
-
-       // If the connection is not open, inform the user that an error has occurred
-       // and stop the queue
-       LmConnectionState state = lm_connection_get_state(this->_sd->connection);
-
-       if (state != LM_CONNECTION_STATE_OPEN && state != LM_CONNECTION_STATE_AUTHENTICATED) {
-               sp_desktop_message_stack(this->_sm->desktop())->flash(Inkscape::INFORMATION_MESSAGE, _("Jabber connection lost."));
-               return false;
-       }
-
-       // If there's nothing to send, don't do anything
-       if (this->_sd->send_queue->empty()) {
-               return true;
-       }
-
-       // otherwise, send out the first change
-       MessageNode* first = this->_sd->send_queue->first();
-
-       sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::NORMAL_MESSAGE,
-                                                     ngettext("Sending message; %u message remaining in send queue.",
-                                                              "Sending message; %u messages remaining in send queue.",
-                                                              this->_sd->send_queue->size()),
-                                                     this->_sd->send_queue->size());
-
-       if (this->_sd->send_queue->empty()) {
-               sp_desktop_message_stack(this->_sm->desktop())->flash(Inkscape::NORMAL_MESSAGE, _("Receive queue empty."));
-       }
-
-       switch (first->type()) {
-               case CHANGE_REPEATABLE:
-               case CHANGE_NOT_REPEATABLE:
-               case CHANGE_COMMIT:
-               case DOCUMENT_BEGIN:
-               case DOCUMENT_END:
-                       this->_sm->sendMessage(first->type(), first->sequence(), first->message(), first->recipient().c_str(), first->chatroom());
-                       break;
-               default:
-                       g_warning("MessageNode with unknown change type found in send queue; discarding message.  This may lead to desynchronization!");
-                       break;
-       }
-
-       this->_sd->send_queue->popFront();
-
-       return true;
-}
-
-bool
-Callbacks::dispatchReceiveQueue()
-{
-       CommitsQueue& rcq = this->_sd->recipients_committed_queue;
-       // See if we have any commits submitted. 
-       if (!rcq.empty()) {
-               // Pick the first one off the queue.
-               ReceivedCommitEvent& committer = rcq.front();
-
-               // Find the commit event sender's receive queue.
-               ReceiveMessageQueue* rmq = this->_sd->receive_queues[committer];
-
-               if (rmq != NULL) {
-                       if (!rmq->empty()) {
-                               // Get the first message off the sender's receive queue.
-                               MessageNode* msg = rmq->first();
-
-                               // There are a few message change types that demand special processing;
-                               // handle them here.
-                               //
-                               // TODO: clean this up.  This should be a simple dispatching routine,
-                               // and should not be performing operations like it's doing right now.
-                               // These really should go into connection-establishment.cpp
-                               // (although that should only happen after SessionManager itself
-                               // is cleaned up).
-                               switch(msg->type()) {
-                                       case CHANGE_COMMIT:
-                                               rcq.pop_front();
-                                               break;
-                                       case DOCUMENT_BEGIN:
-                                               if (this->_sm->session_data->status[WAITING_TO_SYNC_TO_CHAT]) {
-                                                       this->_sm->session_data->status.set(WAITING_TO_SYNC_TO_CHAT, 0);
-                                                       this->_sm->session_data->status.set(SYNCHRONIZING_WITH_CHAT, 1);
-                                               }
-                                               break;
-                                       case DOCUMENT_END:
-                                               rcq.pop_front();
-                                               if (this->_sm->session_data->status[SYNCHRONIZING_WITH_CHAT]) {
-                                                       this->_sm->sendMessage(CONNECTED_SIGNAL, 0, "", this->_sm->session_data->recipient, true);
-                                                       this->_sm->session_data->status.set(SYNCHRONIZING_WITH_CHAT, 0);
-                                                       this->_sm->session_data->status.set(IN_CHATROOM, 1);
-                                               } else {
-                                                       this->_sm->sendMessage(CONNECTED_SIGNAL, 0, "", msg->sender().c_str(), false);
-                                               }
-                                               break;
-                                       case CHANGE_REPEATABLE:
-                                       case CHANGE_NOT_REPEATABLE:
-                                       default:
-                                               break;
-                               }
-                               
-
-                               // Pass the message to the received change handler.
-                               this->_sm->receiveChange(msg->message());
-                               sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::NORMAL_MESSAGE,
-                                                                             ngettext("Receiving change; %u change left to process.",
-                                                                                      "Receiving change; %u changes left to process.",
-                                                                                      rmq->size()),
-                                                                             rmq->size());
-
-                               
-                               // Register this message as the latest message received from this
-                               // sender.
-                               rmq->setLatestProcessedPacket(msg->sequence());
-
-                               // Pop this message off the receive queue.
-                               rmq->popFront();
-                               return true;
-                       } else {
-                               // This really shouldn't happen.
-                               // If we have a commit request from a valid sender, there should
-                               // be something in the receive queue to process.  However, 
-                               // if a client is buggy or has managed to trick us into accepting
-                               // a commit, we should handle the event gracefully.
-                               g_warning("Processing commit, but no changes to commit were found; ignoring commit event.");
-
-                               // Remove this sender from the commit list.  If they want to commit
-                               // later, they can.
-                               rcq.pop_front();
-                               return true;
-                       }
-               } else {
-                       // If the receive queue returned is NULL, then we don't know about
-                       // this sender.  Remove the sender from the commit list.
-                       g_warning("Attempting to process commit from unknown sender; ignoring.");
-                       rcq.pop_front();
-                       return true;
-               }
-       } else {
-               return true;
-       }
-}
-
-}
-
-}
-
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/callbacks.h b/src/jabber_whiteboard/callbacks.h
deleted file mode 100644 (file)
index 7a41a40..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Whiteboard session manager
- * Message dispatch devices and timeout triggers
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_CALLBACKS_H__
-#define __WHITEBOARD_CALLBACKS_H__
-
-#include <glibmm.h>
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-class SessionManager;
-class SessionData;
-
-/**
- * Callback methods used in timers to dispatch MessageNodes from message queues.
- */
-class Callbacks {
-public:
-       /**
-        * Constructor.
-        *
-        * \param sm The SessionManager to associate with.
-        */
-       Callbacks(SessionManager* sm);
-       ~Callbacks();
-
-       /**
-        * Dispatch a message from the send queue to the associated SessionManager object.
-        *
-        * The SessionManager object handles the task of actually sending out a Jabber message.
-        *
-        * \see Inkscape::Whiteboard::SessionManager::sendMessage
-        * \return Whether or not this callback should be called again by the timer routine.
-        */
-       bool dispatchSendQueue();
-
-       /**
-        * Dispatch a message from the receive queue to the associated SessionManager object.
-        *
-        * The SessionManager object handles the task of actually processing a Jabber message.
-        *
-        * \see Inkscape::Whiteboard::SessionManager::receiveChange
-        * \return Whether or not this callback should be called again by the timer routine.
-        */
-       bool dispatchReceiveQueue();
-
-private:
-       SessionManager* _sm;
-       SessionData* _sd;
-};
-
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/chat-handler.cpp b/src/jabber_whiteboard/chat-handler.cpp
deleted file mode 100644 (file)
index 0ba733a..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/**
- * Whiteboard session manager
- * Chatroom message handler
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <glibmm/i18n.h>
-
-//#include <boost/lexical_cast.hpp>
-
-#include "message-stack.h"
-#include "desktop-handles.h"
-#include "document.h"
-
-#include "util/ucompose.hpp"
-
-#include "xml/node.h"
-
-#include "jabber_whiteboard/typedefs.h"
-#include "jabber_whiteboard/message-utilities.h"
-#include "jabber_whiteboard/message-queue.h"
-#include "jabber_whiteboard/jabber-handlers.h"
-#include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/session-manager.h"
-#include "jabber_whiteboard/node-tracker.h"
-#include "jabber_whiteboard/chat-handler.h"
-#include "jabber_whiteboard/error-codes.h"
-
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-ChatMessageHandler::ChatMessageHandler(SessionManager* sm) : _sm(sm)
-{ 
-
-}
-
-ChatMessageHandler::~ChatMessageHandler() 
-{
-
-}
-
-LmHandlerResult
-ChatMessageHandler::parse(LmMessage* message)
-{
-       // Retrieve the message type
-       LmMessageType mtype = lm_message_get_type(message);
-
-       // Retrieve root node of message
-       LmMessageNode* root = lm_message_get_node(message);
-       if (root == NULL) {
-               g_warning("Received a chat message with NULL root node; discarding.");
-               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-       }
-
-       LmMessageSubType msubtype;
-
-
-       msubtype = lm_message_get_sub_type(message);
-
-       switch (mtype) {
-               case LM_MESSAGE_TYPE_MESSAGE:
-                       switch(msubtype) {
-                               case LM_MESSAGE_SUB_TYPE_ERROR:
-                               {
-                                       LmMessageNode* error = lm_message_node_get_child(root, "error");
-                                       if (error != NULL) {
-                                               this->_handleError(lm_message_node_get_attribute(error, "code"));
-                                       }
-                                       break;
-                               }
-                               case LM_MESSAGE_SUB_TYPE_GROUPCHAT:
-                               {
-                                       // FIXME: We should be checking to see if we're in a room in the presence stanzas as indicated in
-                                       // <http://www.jabber.org/jeps/jep-0045.html#enter-pres> but current versions of mu-conference
-                                       // don't broadcast presence in the correct order.
-                                       //
-                                       // Therefore we need to use some sort of hacked-up method to make this work.  We listen for 
-                                       // the sentinel value in a groupchat message -- currently it is '[username] INKBOARD-JOINED' --
-                                       // and begin processing that way.
-
-                                       //LmMessageNode* body = lm_message_node_get_child(root, "body");
-                                       //if (body != NULL) {
-                                               //gchar const* val = lm_message_node_get_value(body);
-                        //g_warning("hey - %s",val);                                   
-                        //if (strcmp(val, String::ucompose("%1 entered the room.", this->_sm->session_data->chat_handle).c_str()) == 0) {
-                                               //      return this->_finishConnection(); break;
-                                               //} else {
-                                                       return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-                                                       break;
-                                               //}
-                                       //} else {
-                                               return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-                                               break;
-                                       //}
-                               }
-                                                                                               
-                               default:
-                                       return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-                                       break;
-                       }
-                       break;
-               case LM_MESSAGE_TYPE_PRESENCE:
-                       // Retrieve the subtype.
-                       switch (msubtype) {
-                               case LM_MESSAGE_SUB_TYPE_ERROR:
-                               {
-                                       g_warning("Could not connect to chatroom");
-                                       // Extract error type
-                                       LmMessageNode* error = lm_message_node_get_child(root, "error");
-                                       if (error != NULL) {
-                                               this->_handleError(lm_message_node_get_attribute(error, "code"));
-                                       }
-                                       // Reset status bits
-                                       this->_sm->session_data->status.set(CONNECTING_TO_CHAT, 0);
-                                       this->_sm->session_data->recipient = "";
-                                       this->_sm->session_data->chat_handle = "";
-
-                                       return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-                                       break;
-                               }
-
-                               case LM_MESSAGE_SUB_TYPE_AVAILABLE: 
-                               {
-                                       // Extract the handle
-                                       // (see JEP-0045, section 6.3.3 - <http://www.jabber.org/jeps/jep-0045.html#enter-pres>)
-                                       Glib::ustring sender = lm_message_node_get_attribute(root, MESSAGE_FROM);
-                                       Glib::ustring chatter = sender.substr(sender.find_last_of('/') + 1, sender.length());
-                                       if (chatter != this->_sm->session_data->chat_handle) {
-                                               this->_sm->session_data->chatters.insert(g_strdup(chatter.data()));
-                                               // Make a receive queue for this chatter
-                                               this->_sm->session_data->receive_queues[sender.raw()] = new ReceiveMessageQueue(this->_sm);
-                                               
-                                       } else {
-                        return this->_finishConnection(); break;
-                                               //g_warning("hmm, who is chatting %s",chatter);
-                                               // If the presence message is from ourselves, then we know that we 
-                                               // have successfully entered the chatroom _and_ have received the entire room roster,
-                                               // and can therefore decide whether we need to synchronize with the rest of the room.
-                                               // (see JEP-0045, section 6.3.3 - <http://www.jabber.org/jeps/jep-0045.html#enter-pres>)
-                                       }
-                                       return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-                               }
-
-                               case LM_MESSAGE_SUB_TYPE_UNAVAILABLE:
-                               {
-                                       Glib::ustring sender = lm_message_node_get_attribute(root, MESSAGE_FROM);
-                                       Glib::ustring chatter = sender.substr(sender.find_last_of('/') + 1, sender.length());
-                                       this->_sm->session_data->chatters.erase(chatter.data());
-
-                                       // Delete the message queue used by this sender
-                                       this->_sm->session_data->receive_queues.erase(sender.raw());
-
-                                       sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::INFORMATION_MESSAGE, _("<b>%s</b> has left the chatroom."), sender.c_str());
-                               }
-
-                               default:
-                                       // no idea what this message is; discard it
-                                       return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-                                       break;
-                       }
-                       break;
-               default:
-                       break;
-       }
-
-       return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-LmHandlerResult
-ChatMessageHandler::_finishConnection()
-{
-       if (this->_sm->session_data->status[CONNECTING_TO_CHAT]) {
-               this->_sm->session_data->status.set(CONNECTING_TO_CHAT, 0);
-
-               if (this->_sm->session_data->chatters.empty()) {
-                       // We are the only one in the chatroom, so there is no
-                       // need for synchronization
-                       this->_sm->session_data->status.set(IN_CHATROOM, 1);
-
-                       // Populate node tracker
-                       KeyToNodeMap newids;
-                       NodeToKeyMap newnodes;
-                       NewChildObjectMessageList newchildren;
-
-                       XML::Node* root = this->_sm->document()->rroot;
-
-                       this->_sm->setupInkscapeInterface();
-                       this->_sm->setupCommitListener();
-
-                       for ( Inkscape::XML::Node *child = root->firstChild() ; child != NULL ; child = child->next() ) {
-                               MessageUtilities::newObjectMessage(NULL, newids, newnodes, newchildren, this->_sm->node_tracker(), child, true);
-                       }
-
-                       this->_sm->node_tracker()->put(newids, newnodes);
-       //              this->_sm->node_tracker()->dump();
-
-               } else {
-                       this->_sm->session_data->status.set(WAITING_TO_SYNC_TO_CHAT, 1);
-                       // Send synchronization request to chatroom
-                       this->_sm->sendMessage(CHATROOM_SYNCHRONIZE_REQUEST, 0, "", this->_sm->session_data->recipient, true);
-               }
-       }
-       return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-void
-ChatMessageHandler::_handleError(char const* errcode)
-{
-//     try {
-       unsigned int code = atoi(errcode);
-
-//             unsigned int code = boost::lexical_cast< unsigned int >(errcode);
-
-       Glib::ustring buf;
-       switch (code) {
-               case ErrorCodes::CHAT_HANDLE_IN_USE:
-                       buf = String::ucompose(_("Nickname %1 is already in use.  Please choose a different nickname."), this->_sm->session_data->chat_handle);
-                       this->_sm->connectionError(buf);
-                       break;
-               case ErrorCodes::SERVER_CONNECT_FAILED:
-                       buf = _("An error was encountered while attempting to connect to the server.");
-                       this->_sm->connectionError(buf);
-                       break;
-               default:
-                       break;
-       }
-//     } catch (boost::bad_lexical_cast&) {
-
-//     }
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/chat-handler.h b/src/jabber_whiteboard/chat-handler.h
deleted file mode 100644 (file)
index f87c814..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * Whiteboard session manager
- * Chatroom message handler
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_CHAT_HANDLER_H__
-#define __WHITEBOARD_CHAT_HANDLER_H__
-
-extern "C" {
-#include <loudmouth/loudmouth.h>
-}
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-class SessionManager;
-
-
-// TODO: find some way to better integrate this with the rest of the message
-// handling framework (i.e. message-processors.cpp, message-handler.cpp,
-// message-contexts.cpp)
-class ChatMessageHandler {
-public:
-       ChatMessageHandler(SessionManager* sm);
-       ~ChatMessageHandler();
-
-       LmHandlerResult parse(LmMessage* message);
-
-private:
-       LmHandlerResult _finishConnection();
-       void _handleError(char const* errcode);
-
-       SessionManager* _sm;    
-
-       // noncopyable, nonassignable
-       ChatMessageHandler(ChatMessageHandler&);
-       void operator=(ChatMessageHandler&);
-};
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/connection-establishment.cpp b/src/jabber_whiteboard/connection-establishment.cpp
deleted file mode 100644 (file)
index d33d6d6..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-/**
- * Whiteboard session manager
- * Methods for establishing connections and notifying the user of events
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "util/ucompose.hpp"
-#include <glibmm/i18n.h>
-#include <gtkmm/dialog.h>
-#include <gtkmm/messagedialog.h>
-
-#include "desktop.h"
-#include "file.h"
-#include "document.h"
-
-#include "prefs-utils.h"
-
-#include "xml/repr.h"
-
-#include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/typedefs.h"
-#include "jabber_whiteboard/node-tracker.h"
-#include "jabber_whiteboard/chat-handler.h"
-#include "jabber_whiteboard/message-queue.h"
-#include "jabber_whiteboard/session-manager.h"
-#include "jabber_whiteboard/invitation-confirm-dialog.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-void
-SessionManager::sendRequestToUser(std::string const& recipientJID)
-{
-       /*
-       Glib::ustring doccopy;
-       if (document != NULL) {
-               doccopy = *document;
-       }
-       */
-       this->session_data->status.set(WAITING_FOR_INVITE_RESPONSE, 1);
-       this->sendMessage(CONNECT_REQUEST_USER, 0, "", recipientJID.c_str(), false);
-}
-
-void
-SessionManager::sendRequestToChatroom(Glib::ustring const& server, Glib::ustring const& chatroom, Glib::ustring const& handle, Glib::ustring const& password)
-{
-       // We do not yet use the Basic MUC Protocol for connection establishment etc
-       // <http://www.jabber.org/jeps/jep-0045.html>.  The protocol we use is the
-       // old GroupChat system; extension to MUC is TODO
-       
-       // Compose room@service/nick string for "to" field
-       Glib::ustring dest = String::ucompose("%1@%2/%3", chatroom, server, handle);
-       LmMessage* presence_req = lm_message_new(dest.data(), LM_MESSAGE_TYPE_PRESENCE);
-
-       // Add 'from' attribute
-       LmMessageNode* preq_root = lm_message_get_node(presence_req);
-
-       lm_message_node_set_attribute(preq_root, "from", this->session_data->jid.c_str());
-       
-       // Add <x xmlns='http://jabber.org/protocol/muc/' />
-       // (Not anymore: we don't speak it! -- yipdw)
-       LmMessageNode* xmlns_node = lm_message_node_add_child(preq_root, "x", "");
-       lm_message_node_set_attribute(xmlns_node, "xmlns", "http://jabber.org/protocol/muc/");
-       
-       // If a password was supplied, add it to xmlns_node
-       if (password != NULL) {
-               lm_message_node_add_child(xmlns_node, "password", password.c_str());
-       }
-
-       // Create chat message handler and node tracker
-       if (!this->_myChatHandler) {
-               this->_myChatHandler = new ChatMessageHandler(this);
-       }
-
-       // Flag ourselves as connecting to a chatroom (but not yet connected)
-       this->session_data->status.set(CONNECTING_TO_CHAT, 1);
-       // Send the message
-       GError *error = NULL;
-       if (!lm_connection_send(this->session_data->connection, presence_req, &error)) {
-               g_error("Presence message could not be sent to %s: %s", dest.data(), error->message);
-               this->session_data->status.set(CONNECTING_TO_CHAT, 0);
-       }
-
-       this->session_data->chat_handle = handle;
-       this->session_data->chat_server = server;
-       this->session_data->chat_name = chatroom;
-
-       prefs_set_string_attribute("whiteboard.room", "name", chatroom.c_str());
-       prefs_set_string_attribute("whiteboard.room", "server", server.c_str());
-       //Commented out because you can use whiteboard.server.username
-       //prefs_set_string_attribute("whiteboard.room", "handle", handle.c_str());
-       //store password here?
-
-
-       this->setRecipient(String::ucompose("%1@%2", chatroom, server).data());
-
-       lm_message_unref(presence_req);
-}
-
-void 
-SessionManager::sendConnectRequestResponse(char const* recipientJID, gboolean accepted_request)
-{
-       if (accepted_request == TRUE) {
-               this->setRecipient(recipientJID);
-               this->session_data->status.set(IN_WHITEBOARD, 1);
-       }
-
-       this->sendMessage(CONNECT_REQUEST_RESPONSE_USER, accepted_request, "", recipientJID, false);
-}
-
-// When this method is invoked, it means that the user has received an invitation from another peer
-// to engage in a whiteboard session (i.e. 1:1 communication).  The user may accept or reject this invitation.
-void
-SessionManager::receiveConnectRequest(gchar const* requesterJID)
-{
-       int x, y;
-       Gdk::ModifierType mt;
-       Gdk::Display::get_default()->get_pointer(x, y, mt);
-
-       if (mt & GDK_BUTTON1_MASK) {
-               // Attach a polling timeout
-               this->_notify_incoming_request = Glib::signal_timeout().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &SessionManager::_pollReceiveConnectRequest), requesterJID), 50);
-               return;
-       }
-
-       if (this->session_data->status[WAITING_FOR_INVITE_RESPONSE]) {
-               // Whoops.  Someone tried to invite us while we were inviting someone else 
-               // (maybe it was the someone we were trying to invite, maybe it was someone else).
-               //
-               // Our response is to reject the second request, as we can only handle one
-               // invitation at a time.  Also, we notify the user (who is waiting for an invitation 
-               // response) of the rejection event.
-               this->sendMessage(CONNECT_REQUEST_REFUSED_BY_PEER, 0, "", requesterJID, false);
-
-               Glib::ustring primary = "<span weight=\"bold\" size=\"larger\">";
-
-               // TRANSLATORS: This string is used to inform an Inkboard user that the following
-               // scenario has occurred:
-               // 1.  Alice invites Bob to an Inkboard session.
-               // 2.  While Alice's invitation is en route, Bob invites Alice to an Inkboard session.
-               //
-               // Or, we might have the following scenario:
-               // 1.  Alice invites Bob to an Inkboard session.
-               // 2.  While Alice is waiting for Bob's response, Carol sends Alice an invitation.
-               //
-               // In the current implementation, we can only handle one invitation at a time,
-               // so we reject all others.  
-               //
-               // This is a fix for bug #1352522.  Probably not the friendliest, but it's about
-               // the best we can do without changing the protocol.
-               primary += _("<b>An invitation conflict has occurred.</b>");
-               primary += "</span>\n\n";
-
-               // TRANSLATORS: %1 is the JID of the user who sent us the invitation request.
-               primary += String::ucompose(_("The Jabber user <b>%1</b> attempted to invite you to a whiteboard session while you were waiting on an invitation response.\n\nThe invitation from <b>%1</b> has been rejected."), requesterJID); 
-
-               Gtk::MessageDialog dialog(primary, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, false);
-               dialog.run();
-               return;
-       }
-
-       if (this->session_data->status[IN_WHITEBOARD]) {
-               this->sendMessage(ALREADY_IN_SESSION, 0, "", requesterJID, false);
-               return;
-       }
-
-       // Check to see if the user made any modifications to this document.  If so, 
-       // we want to give them the option of (1) letting us clear their document or (2)
-       // opening a new, blank document for the whiteboard session.
-       Glib::ustring primary = "<span weight=\"bold\" size=\"larger\">" + String::ucompose(_("<b>%1</b> has invited you to a whiteboard session."), requesterJID) + "</span>\n\n";
-       Glib::ustring title = String::ucompose(_("Incoming whiteboard invitation from %1"), requesterJID);
-
-       if (sp_document_repr_root(this->_myDoc)->attribute("sodipodi:modified") == NULL) {
-               primary += String::ucompose(_("Do you wish to accept <b>%1</b>'s whiteboard session invitation?"), requesterJID);
-       } else {
-               primary += String::ucompose(_("Would you like to accept %1's invitation in a new document window?\nAccepting the invitation in your current window will discard unsaved changes."), requesterJID);
-       }
-
-       // Construct confirmation dialog
-       InvitationConfirmDialog dialog(primary);
-       
-       dialog.add_button(_("Accept invitation"), ACCEPT_INVITATION);
-       dialog.add_button(_("Decline invitation"), DECLINE_INVITATION);
-       dialog.add_button(_("Accept invitation in new document window"), ACCEPT_INVITATION_IN_NEW_WINDOW);
-
-       bool undecided = true;
-       InvitationResponses resp = static_cast< InvitationResponses >(dialog.run());
-
-       while(undecided) {
-               if (resp == ACCEPT_INVITATION) {
-                       undecided = false;
-                       this->clearDocument();
-               
-                       // Create a receive queue for the initiator of this request
-                       this->session_data->receive_queues[requesterJID] = new ReceiveMessageQueue(this);
-                       
-                       this->setupInkscapeInterface();
-                       if (dialog.useSessionFile()) {
-                               this->session_data->sessionFile = dialog.getSessionFilePath();
-                               this->_tryToStartLog();
-                       }
-                       this->sendConnectRequestResponse(requesterJID, TRUE);
-
-               } else if (resp == ACCEPT_INVITATION_IN_NEW_WINDOW) {
-                       SPDesktop* newdesktop = sp_file_new_default();
-                       if (newdesktop != NULL) {
-                               undecided = false;
-
-                               // Swap desktops around
-
-                               // Destroy the new desktop's session manager and add this one in
-                               delete newdesktop->_whiteboard_session_manager;
-                               newdesktop->_whiteboard_session_manager = this;
-
-                               // Assign a new session manager to our old desktop
-                               this->_myDesktop->_whiteboard_session_manager = new SessionManager(this->_myDesktop);
-
-                               // Reset our desktop and document pointers
-                               this->setDesktop(newdesktop);
-
-                               // Prepare document and send acceptance notification
-                               this->session_data->receive_queues[requesterJID] = new ReceiveMessageQueue(this);
-                               this->clearDocument();
-                               this->setupInkscapeInterface();
-                               if (dialog.useSessionFile()) {
-                                       this->session_data->sessionFile = dialog.getSessionFilePath();
-                                       this->_tryToStartLog();
-                               }
-                               this->sendConnectRequestResponse(requesterJID, TRUE);
-
-                       } else {
-                               // We could not create a new desktop; ask the user if she or he wants to 
-                               // replace the current document and accept the invitation, or reject the invitation.
-                               // TRANSLATORS: %1 is a userid here
-                               Glib::ustring msg = "<span weight=\"bold\" size=\"larger\">" + String::ucompose(_("A new document window could not be opened for a whiteboard session with <b>%1</b>"), requesterJID) + ".</span>\n\nWould you like to accept the whiteboard connection in the active document or refuse the invitation?";
-                               InvitationConfirmDialog replace_dialog(msg);
-                               dialog.add_button(_("Accept invitation"), ACCEPT_INVITATION);
-                               dialog.add_button(_("Decline invitation"), DECLINE_INVITATION);
-                               resp = static_cast< InvitationResponses >(dialog.run());
-                       }
-               } else {
-                       undecided = false;
-                       this->sendMessage(CONNECT_REQUEST_REFUSED_BY_PEER, 0, "", requesterJID, false);
-               }
-       }
-}
-
-// When this method is invoked, it means that the other peer
-// has accepted our request.
-void
-SessionManager::receiveConnectRequestResponse(InvitationResponses response, std::string& sender)
-{
-       this->session_data->status.set(WAITING_FOR_INVITE_RESPONSE, 0);
-
-       switch(response) {
-               case ACCEPT_INVITATION:
-                       {
-
-                       // Create a receive queue for the other peer.
-                       this->session_data->receive_queues[sender] = new ReceiveMessageQueue(this);
-                               
-                       KeyToNodeMap newids;
-                       NodeToKeyMap newnodes;
-                       this->_myTracker = new XMLNodeTracker(this);
-                       this->setupInkscapeInterface();
-                       this->_tryToStartLog();
-                       this->resendDocument(this->session_data->recipient, newids, newnodes);
-                       this->_myTracker->put(newids, newnodes);
-//                     this->_myTracker->dump();
-                       this->setupCommitListener();
-                       break;
-                       }
-
-               case DECLINE_INVITATION:
-                       {
-                       // TRANSLATORS: %1 is the peer whom refused our invitation.
-                       Glib::ustring primary = String::ucompose(_("<span weight=\"bold\" size=\"larger\">The user <b>%1</b> has refused your whiteboard invitation.</span>\n\n"), sender);
-                       
-                       // TRANSLATORS: %1 is the peer whom refused our invitation, %2 is our Jabber identity.
-                       Glib::ustring secondary = String::ucompose(_("You are still connected to a Jabber server as <b>%2</b>, and may send an invitation to <b>%1</b> again, or you may send an invitation to a different user."), sender, this->session_data->jid);
-
-                       Gtk::MessageDialog dialog(primary + secondary, true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, false);
-                       dialog.run();
-                       break;
-
-                       }
-
-               case PEER_ALREADY_IN_SESSION:
-                       {
-                       // TRANSLATORS: %1 is the peer whom we tried to contact, but is already in a whiteboard session.
-                       Glib::ustring primary = String::ucompose(_("<span weight=\"bold\" size=\"larger\">The user <b>%1</b> is already in a whiteboard session.</span>\n\n"), sender);
-
-                       // TRANSLATORS: %1 is the peer whom we tried to contact, but is already in a whiteboard session.
-                       Glib::ustring secondary = String::ucompose(_("You are still connected to a Jabber server as <b>%1</b>, and may send an invitation to a different user."), sender);
-                       Gtk::MessageDialog dialog(primary + secondary, true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, false);
-                       dialog.run();
-
-                       break;
-                       }
-               default:
-                       break;
-       }
-}
-
-void
-SessionManager::receiveConnectRequestResponseChat(gchar const* recipient)
-{
-       // When responding to connection request responses in chatrooms,
-       // the responding user is already established in the whiteboard session.
-       // Therefore we do not need to perform any setup of observers or dispatchers; the requesting user
-       // will do that.
-
-       KeyToNodeMap newids;
-       NodeToKeyMap newnodes;
-       this->resendDocument(recipient, newids, newnodes);
-}
-
-bool
-SessionManager::_pollReceiveConnectRequest(Glib::ustring const recipientJID)
-{
-       int x, y;
-       Gdk::ModifierType mt;
-       Gdk::Display::get_default()->get_pointer(x, y, mt);
-
-       if (mt & GDK_BUTTON1_MASK) {
-               return true;
-       } else {
-               this->receiveConnectRequest(recipientJID.c_str());
-               return false;
-       }
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 3fc3c0e456c47714441249c7d47abf3c2cd1a1ac..afed3338f654bf08ff7d1e194557ba8d5020441d 100644 (file)
@@ -10,8 +10,8 @@
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
-#ifndef __WHITEBOARD_DEFINES_H__
-#define __WHITEBOARD_DEFINES_H__
+#ifndef __INKSCAPE_WHITEBOARD_DEFINES_H__
+#define __INKSCAPE_WHITEBOARD_DEFINES_H__
 
 #include "jabber_whiteboard/message-tags.h"
 #include "jabber_whiteboard/internal-constants.h"
@@ -31,10 +31,10 @@ enum MessageType {
        DOCUMENT_BEGIN = 4,
        DOCUMENT_END = 5,
     // 1-1 connections
-    CONNECT_REQUEST_USER = 6,
+        CONNECT_REQUEST_USER = 6,
        CONNECT_REQUEST_RESPONSE_USER = 7, 
     // chat connections
-    CONNECT_REQUEST_RESPONSE_CHAT = 8,
+CONNECT_REQUEST_RESPONSE_CHAT = 8,
        // chatroom document synchronization
        CHATROOM_SYNCHRONIZE_REQUEST = 9, 
        CHATROOM_SYNCHRONIZE_RESPONSE = 10,
@@ -58,9 +58,9 @@ enum MessageType {
 // Responses to whiteboard invitations
 enum InvitationResponses {
        ACCEPT_INVITATION,
-       ACCEPT_INVITATION_IN_NEW_WINDOW,
        DECLINE_INVITATION,
-       PEER_ALREADY_IN_SESSION
+       PEER_ALREADY_IN_SESSION,
+       UNSUPPORTED_PROTOCOL
 };
 
 // Message handler modes
diff --git a/src/jabber_whiteboard/deserializer.cpp b/src/jabber_whiteboard/deserializer.cpp
deleted file mode 100644 (file)
index 0e20712..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-/**
- * Inkboard message -> XML::Event* deserializer
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "xml/log-builder.h"
-#include "xml/event.h"
-#include "xml/node.h"
-#include "xml/repr.h"
-
-#include "util/share.h"
-
-#include "gc-anchored.h"
-
-#include "jabber_whiteboard/message-utilities.h"
-#include "jabber_whiteboard/typedefs.h"
-#include "jabber_whiteboard/node-utilities.h"
-#include "jabber_whiteboard/node-tracker.h"
-#include "jabber_whiteboard/deserializer.h"
-#include <glibmm.h>
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-void
-Deserializer::deserializeEventAdd(Glib::ustring const& msg)
-{
-       // 1.  Extract required attributes: parent, child, node name, and node type.
-       // If any of these cannot be found, return.
-       std::string parent, child, prev;
-       Glib::ustring name, type;
-
-       struct Node buf;
-
-       buf.tag = MESSAGE_PARENT;
-       if (!MessageUtilities::findTag(buf, msg)) {
-               return;
-       }
-       parent = buf.data.c_str();
-
-       buf.tag = MESSAGE_CHILD;
-       if (!MessageUtilities::findTag(buf, msg)) {
-               return;
-       }
-       child = buf.data.c_str();
-
-       KeyToNodeMap::iterator i = this->_newnodes.find(child);
-       if (i != this->_newnodes.end()) {
-               if (this->_node_action_tracker.getAction(i->second) == NODE_ADD) {
-                       return;
-               }
-       }
-
-       buf.tag = MESSAGE_NAME;
-       if (!MessageUtilities::findTag(buf, msg)) {
-               return;
-       } else {
-               name = buf.data;
-       }
-
-       buf.tag = MESSAGE_NODETYPE;
-       if (!MessageUtilities::findTag(buf, msg)) {
-               return;
-       } else {
-               type = buf.data;
-       }
-
-       // 2.  Extract optional attributes: the node previous to the new child node.
-       buf.tag = MESSAGE_REF;
-       if (MessageUtilities::findTag(buf, msg)) {
-               prev = buf.data.c_str();
-       }
-
-       // 3. Check if the received child node is a special node.  If it is, and we are already 
-       // tracking it, then we should not add the node.
-       if (this->_xnt->isSpecialNode(name)) {
-               if (this->_xnt->isTracking(this->_xnt->getSpecialNodeKeyFromName(name))) {
-                       return;
-               }
-       }
-
-       // 4.  Look up the parent node.  If we cannot find it, return.
-       XML::Node* parentRepr = this->_getNodeByID(parent);
-       if (parentRepr == NULL) {
-               g_warning("Cannot find parent node identified by %s", parent.c_str());
-               return; 
-       }
-
-       // 5.  Look up the node previous to the child, if it exists.
-       // If we cannot find it, we may be in a change conflict situation.
-       // In that case, just append the node.
-       XML::Node* prevRepr = NULL;
-       if (!prev.empty()) {
-               prevRepr = this->_getNodeByID(prev);
-               if (prevRepr == NULL) {
-                       g_warning("Prev node %s could not be found; appending incoming node.  Document may not be synchronized.", prev.c_str());
-                       prevRepr = parentRepr->lastChild();
-               }
-       }
-
-       if (prevRepr) {
-               if (prevRepr->parent() != parentRepr) {
-                       if (this->_parent_child_map[prevRepr] != parentRepr) {
-                               g_warning("ref mismatch on node %s: child=%s ref=%p parent=%p ref->parent()=%p", prev.c_str(), child.c_str(), prevRepr, parentRepr, prevRepr->parent());
-                               g_warning("parent_child_map[%p (%s)] = %p (%s)", prevRepr, this->_xnt->get(*prevRepr).c_str(), this->_parent_child_map[prevRepr], this->_xnt->get(*(this->_parent_child_map[prevRepr])).c_str());
-                               return;
-                       }
-               }
-       }
-
-       XML::Node* childRepr = NULL;
-       
-       // 6.  Create the child node.
-
-       switch (NodeUtilities::stringToNodeType(type)) {
-               case XML::TEXT_NODE:
-                       buf.tag = MESSAGE_CONTENT;
-                       if (!MessageUtilities::findTag(buf, msg)) {
-                               childRepr = sp_repr_new_text("");
-                       } else {
-                               childRepr = sp_repr_new_text(buf.data.c_str());
-                       }
-                       break;
-               case XML::DOCUMENT_NODE:
-                       // TODO
-               case XML::COMMENT_NODE:
-                       buf.tag = MESSAGE_CONTENT;
-                       if (!MessageUtilities::findTag(buf, msg)) {
-                               childRepr = sp_repr_new_comment("");
-                       } else {
-                               childRepr = sp_repr_new_comment(buf.data.c_str()); 
-                       }
-                       break;
-               case XML::ELEMENT_NODE: 
-               default:
-                       childRepr = sp_repr_new(name.data());
-                       break;
-       }
-
-
-       this->_actions.push_back(SerializedEventNodeAction(KeyNodePair(child, childRepr), NODE_ADD));
-       this->_newnodes[child] = childRepr;
-       this->_newkeys[childRepr] = child;
-
-
-       // 8.  Deserialize the event.
-       this->_builder.addChild(*parentRepr, *childRepr, prevRepr);
-       this->_parent_child_map.erase(childRepr);
-       this->_parent_child_map[childRepr] = parentRepr;
-       this->_addOneEvent(this->_builder.detach());
-       Inkscape::GC::release(childRepr);
-}
-
-void
-Deserializer::deserializeEventDel(Glib::ustring const& msg)
-{
-       // 1.  Extract required attributes: parent, child.  If we do not know these,
-       // return.
-       std::string parent, child, prev;
-
-       struct Node buf;
-
-       buf.tag = MESSAGE_PARENT;
-       if (!MessageUtilities::findTag(buf, msg)) {
-               return;
-       }
-       parent = buf.data.c_str();
-
-       buf.tag = MESSAGE_CHILD;
-       if (!MessageUtilities::findTag(buf, msg)) {
-               return;
-       }
-       child = buf.data.c_str();
-
-       KeyToNodeMap::iterator i = this->_newnodes.find(child);
-       if (i != this->_newnodes.end()) {
-               if (this->_node_action_tracker.getAction(i->second) == NODE_REMOVE) {
-                       return;
-               }
-       }
-
-       // 2.  Extract optional attributes: previous node.
-       buf.tag = MESSAGE_REF;
-       if (MessageUtilities::findTag(buf, msg)) {
-               prev = buf.data.c_str(); 
-       }
-
-       // 3.  Retrieve nodes.  If we cannot find all nodes involved, return.
-       XML::Node* parentRepr = this->_getNodeByID(parent);
-       XML::Node* childRepr = this->_getNodeByID(child);
-       XML::Node* prevRepr = NULL;
-       if (!prev.empty()) {
-               prevRepr = this->_getNodeByID(prev);
-               if (prevRepr == NULL) {
-                       return;
-               }
-       }
-
-       // 4.  Deserialize the event.
-       if (parentRepr && childRepr) {
-               if (childRepr->parent() == parentRepr || this->_parent_child_map[childRepr] == parentRepr) {
-//                     this->_actions.push_back(SerializedEventNodeAction(KeyNodePair(child, childRepr), NODE_REMOVE));
-                       this->_builder.removeChild(*parentRepr, *childRepr, prevRepr);
-                       this->_parent_child_map.erase(childRepr);
-                       this->_addOneEvent(this->_builder.detach());
-
-                       // 5.  Mark the removed node and all its children for removal from the tracker.
-                       this->_recursiveMarkForRemoval(childRepr);
-               } else {
-                       g_warning("child->parent() == parent mismatch on child=%s (%p), parent=%s: parent=%p child->parent()=%p", child.c_str(), childRepr, parent.c_str(), parentRepr, childRepr->parent());
-                       g_warning("parent_child_map[%p] = %p", childRepr, this->_parent_child_map[childRepr]);
-               }
-       } else {
-               g_warning("Missing parentRepr and childRepr: parent=%p, child=%p", parentRepr, childRepr);
-       }
-}
-
-void
-Deserializer::deserializeEventChgOrder(Glib::ustring const& msg)
-{
-       // 1.  Extract required attributes: node ID, parent ID, new previous node ID.
-       // If we do not know these, return.
-       std::string id, parentid, oldprevid, newprevid;
-       Node buf;
-
-       buf.tag = MESSAGE_ID;
-       if (MessageUtilities::findTag(buf, msg)) {
-               id = buf.data.raw();
-       } else {
-               return;
-       }
-
-       buf.tag = MESSAGE_PARENT;
-       if (MessageUtilities::findTag(buf, msg)) {
-               parentid = buf.data.raw();
-       } else {
-               return;
-       }
-
-       // 2.  Extract optional attributes: old previous node, new previous node.
-       buf.tag = MESSAGE_OLDVAL;
-       if (MessageUtilities::findTag(buf, msg)) {
-               oldprevid = buf.data.raw();
-       }
-
-       buf.tag = MESSAGE_NEWVAL;
-       if (MessageUtilities::findTag(buf, msg)) {
-               newprevid = buf.data.raw();
-       } else {
-               return;
-       }
-
-       // 3.  Find the identified nodes.  If we do not know about the parent and child, return.
-       XML::Node* node = this->_getNodeByID(id);
-       XML::Node* parent = this->_getNodeByID(parentid);
-       XML::Node* oldprev = NULL;
-       XML::Node* newprev = NULL;
-       if (!oldprevid.empty()) {
-               oldprev = this->_getNodeByID(oldprevid);
-       }
-
-       if (!newprevid.empty()) {
-               newprev = this->_getNodeByID(newprevid);
-       }
-
-       if (parent && node) {
-               // 4.  Deserialize the event.
-               this->_builder.setChildOrder(*parent, *node, oldprev, newprev);
-               this->_addOneEvent(this->_builder.detach());
-       } else {
-               return;
-       }
-}
-
-void
-Deserializer::deserializeEventChgContent(Glib::ustring const& msg)
-{
-       // 1.  Extract required attributes: node ID.  If we do not know these, return.
-       std::string id;
-       Util::ptr_shared<char> oldval, newval;
-       Node buf;
-
-       buf.tag = MESSAGE_ID;
-       if (!MessageUtilities::findTag(buf, msg)) {
-               return;
-       } else {
-               id = buf.data.raw();
-       }
-
-       // 2.  Extract optional attributes: old value, new value.
-       buf.tag = MESSAGE_OLDVAL;
-       if (MessageUtilities::findTag(buf, msg)) {
-               oldval = Util::share_string(buf.data.c_str());
-       } else {
-               oldval = Util::share_static_string("");
-       }
-
-       buf.tag = MESSAGE_NEWVAL;
-       if (MessageUtilities::findTag(buf, msg)) {
-               newval = Util::share_string(buf.data.c_str());
-       } else {
-               newval = Util::share_static_string("");
-       }
-
-       // 3.  Find the node identified by the ID.  If we cannot find it, return.
-       XML::Node* node = this->_getNodeByID(id);
-       if (node == NULL) {
-               return;
-       }
-
-       // 4.  Deserialize the event.
-       this->_builder.setContent(*node, oldval, newval);
-       this->_addOneEvent(this->_builder.detach());
-}
-
-void
-Deserializer::deserializeEventChgAttr(Glib::ustring const& msg)
-{
-       // 1.  Extract required attributes: node ID, attribute key.  If we do not know these,
-       // return.
-
-       struct Node buf;
-       buf.tag = MESSAGE_ID;
-       if (!MessageUtilities::findTag(buf, msg)) {
-               return;
-       }
-
-       std::string id = buf.data.data();
-
-       buf.tag = MESSAGE_KEY;
-       if (!MessageUtilities::findTag(buf, msg)) {
-               return;
-       }
-
-       Glib::ustring key = buf.data;
-
-       // 2.  Extract optional attributes: new value.  If we do not find it in the message,
-       // assume there is no new value.
-       buf.tag = MESSAGE_NEWVAL;
-       Util::ptr_shared<char> newval;
-       if (MessageUtilities::findTag(buf, msg)) {
-               newval = Util::share_string(buf.data.c_str());
-       } else {
-               newval = Util::share_static_string("");
-       }
-
-       // 3.  Extract optional attributes: old value.  If we do not find it in the message,
-       // assume that there is no old value.
-       buf.tag = MESSAGE_OLDVAL;
-       Util::ptr_shared<char> oldval;
-       if (MessageUtilities::findTag(buf, msg)) {
-               oldval = Util::share_string(buf.data.c_str());
-       } else {
-               oldval = Util::share_static_string("");
-       }
-
-       // 4.  Look up this node in the local node database and external tracker.
-       // If it cannot be found, return.
-       XML::Node* node = this->_getNodeByID(id);
-       if (node == NULL) {
-               g_warning("Could not find node %s on which to change attribute", id.c_str());
-               return;
-       }
-
-       // 5.  If this node is in the actions queue and is marked as "new", we need to apply
-       // _all_ received attributes to it _before_ adding it to the document tree.
-       if (this->_newnodes.find(id) != this->_newnodes.end()) {
-               node->setAttribute(key.c_str(), newval.pointer());      
-       }
-
-       // 6.  Deserialize the event.
-       this->_builder.setAttribute(*node, g_quark_from_string(key.c_str()), oldval, newval);
-       this->_updated.insert(node);
-       this->_addOneEvent(this->_builder.detach());
-}
-
-void 
-Deserializer::_recursiveMarkForRemoval(XML::Node* node)
-{
-       if (node != NULL) {
-               NodeToKeyMap::iterator i = this->_newkeys.find(node);
-               if (i == this->_newkeys.end()) {
-                       std::string id = this->_xnt->get(*node);
-                       if (!id.empty()) {
-                               this->_actions.push_back(SerializedEventNodeAction(KeyNodePair(id, node), NODE_REMOVE));
-                       }
-               } else {
-                       this->_actions.push_back(SerializedEventNodeAction(KeyNodePair((*i).second, node), NODE_REMOVE));
-               }
-
-               for (XML::Node* child = node->firstChild(); child; child = child->next()) {
-                       this->_recursiveMarkForRemoval(child);
-               }
-       }
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/deserializer.h b/src/jabber_whiteboard/deserializer.h
deleted file mode 100644 (file)
index 715ca4c..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/**
- * Inkboard message -> XML::Event* deserializer
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_MESSAGE_DESERIALIZER_H__
-#define __WHITEBOARD_MESSAGE_DESERIALIZER_H__
-
-#include "xml/log-builder.h"
-#include "xml/event.h"
-
-#include "jabber_whiteboard/node-tracker-event-tracker.h"
-#include "jabber_whiteboard/node-tracker.h"
-#include "jabber_whiteboard/typedefs.h"
-
-#include <functional>
-#include <algorithm>
-#include <glibmm.h>
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-/**
- * A stateful XML::Event deserializer.
- *
- * The Deserializer class is meant to deserialize XML::Events serialized by 
- * Inkscape::Whiteboard::Serializer or a serializer that serializes
- * XML::Events into the same format.
- *
- * Usage is as follows:
- * <ol>
- *     <li>For each serialized event called, call the appropriate deserialization method.</li>
- *     <li>Detach the deserialized event.</li>
- * </ol>
- *
- * The deserializer does not actually modify any aspect of the document or node-tracking systems.
- * Methods are provided to provide the information necessary to perform the modifications outside
- * of the deserializer.
- */
-class Deserializer {
-public:
-       /**
-        * Constructor.
-        *
-        * \param xnt The XMLNodeTracker that a Deserializer should use for retrieving 
-        * XML::Nodes based on string keys.
-        */
-       Deserializer(XMLNodeTracker* xnt) : _xnt(xnt)
-       {
-               this->clearEventLog();
-       }
-
-       ~Deserializer() { }
-
-       /**
-        * Deserialize a node add event.
-        *
-        * \see XML::EventAdd
-        * \param msg The message that describes the event.
-        */
-       void deserializeEventAdd(Glib::ustring const& msg);
-
-       /**
-        * Deserialize a node remove event.
-        *
-        * \see XML::EventDel
-        * \param msg The message that describes the event.
-        */
-       void deserializeEventDel(Glib::ustring const& msg);
-
-       /**
-        * Deserialize a node order change event.
-        *
-        * \see XML::EventChgOrder
-        * \param msg The message that describes the event.
-        */
-       void deserializeEventChgOrder(Glib::ustring const& msg);
-
-       /**
-        * Deserialize a node content change event.
-        *
-        * \see XML::EventChgContent
-        * \param msg The message that describes the event.
-        */
-       void deserializeEventChgContent(Glib::ustring const& msg);
-
-       /**
-        * Deserialize a node attribute change event.
-        *
-        * \see XML::EventChgAttr
-        * \param msg The message that describes the event.
-        */
-       void deserializeEventChgAttr(Glib::ustring const& msg);
-
-       /**
-        * Retrieve the deserialized event log.
-        * This method does <b>not</b> clear the internal event log kept by the deserializer.
-        * To do that, use detachEventLog.
-        *
-        * \return The deserialized event log.
-        */
-       XML::Event* getEventLog()
-       {
-               return this->_log;
-       }
-
-       /**
-        * Retrieve the deserialized event log and clear the internal event log kept by the deserializer.
-        *
-        * \return The deserialized event log.
-        */
-       XML::Event* detachEventLog()
-       {
-               XML::Event* ret = this->_log;
-               this->clearEventLog();
-               return ret;
-       }
-
-       /**
-        * Clear the internal event log.
-        */
-       void clearEventLog()
-       {
-               g_log(NULL, G_LOG_LEVEL_DEBUG, "Clearing event log");
-               this->_log = NULL;
-       }
-
-       /**
-        * Retrieve a list of node entry actions (add node entry, remove node entry)
-        * that need to be performed on the XMLNodeTracker.
-        *
-        * Because this method returns a reference to a list, it is not safe for use 
-        * across multiple invocations of this Deserializer.
-        *
-        * \return A reference to a list of node entry actions generated while deserializing.
-        */
-       KeyToNodeActionList& getNodeTrackerActions()
-       {
-               return this->_actions;
-       }
-
-       /**
-        * Retrieve a list of node entry actions (add node entry, remove node entry)
-        * that need to be performed on the XMLNodeTracker.
-        *
-        * \return A list of node entry actions generated while deserializing.
-        */
-       KeyToNodeActionList getNodeTrackerActionsCopy()
-       {
-               return this->_actions;
-       }
-
-       /**
-        * Retrieve a set of nodes for which an EventChgAttr was deserialized.
-        *
-        * For some actions (i.e. text tool) it is necessary to call updateRepr() on
-        * the updated nodes.  This method provides the information required to perform
-        * that action.
-        *
-        * Because this method returns a reference to a set, it is not safe for use 
-        * across multiple invocations of this Deserializer.
-        *
-        * \return A reference to a set of nodes for which an EventChgAttr was deserialized.
-        */
-       AttributesUpdatedSet& getUpdatedAttributeNodeSet()
-       {
-               return this->_updated;
-       }
-
-       /**
-        * Retrieve a set of nodes for which an EventChgAttr was deserialized.
-        *
-        * For some actions (i.e. text tool) it is necessary to call updateRepr() on
-        * the updated nodes.  This method provides the information required to perform
-        * that action.
-        *
-        * \return A set of nodes for which an EventChgAttr was deserialized.
-        */
-       AttributesUpdatedSet getUpdatedAttributeNodeSetCopy()
-       {
-               return this->_updated;
-       }
-
-       /**
-        * Clear all internal node buffers.
-        */
-       void clearNodeBuffers()
-       {
-               g_log(NULL, G_LOG_LEVEL_DEBUG, "Clearing deserializer node buffers");
-               this->_newnodes.clear();
-               this->_actions.clear();
-               this->_newkeys.clear();
-               this->_parent_child_map.clear();
-               this->_updated.clear();
-       }
-
-       /**
-        * Clear all internal state.
-        */
-       void reset() 
-       {
-               this->clearEventLog();
-               this->clearNodeBuffers();
-       }
-
-private:
-       XML::Node* _getNodeByID(std::string const& id)
-       {
-               KeyToNodeMap::iterator i = this->_newnodes.find(id);
-               if (i != this->_newnodes.end()) {
-                       return const_cast< XML::Node* >(i->second);
-               } else {
-                       if (this->_xnt->isTracking(id)) {
-                               return this->_xnt->get(id);
-                       } else {
-                               return NULL;
-                       }
-               }
-       }
-
-       void _addOneEvent(XML::Event* event)
-       {
-               if (this->_log == NULL) {
-                       this->_log = event;
-               } else {
-                       event->next = this->_log;
-                       this->_log = event;
-               }
-       }
-
-       void _recursiveMarkForRemoval(XML::Node* node);
-
-       // internal states with accessors:
-       
-       // node tracker actions (add node, remove node)
-       KeyToNodeActionList _actions;
-
-       // nodes that have had their attributes updated
-       AttributesUpdatedSet _updated;
-
-       // the deserialized event log
-       XML::Event* _log;
-
-
-       // for internal use:
-       
-       // These maps only store information on a single node.  That's fine, though;
-       // all we care about is the ability to do key <-> node association.  The NodeTrackerEventTracker
-       // and KeyToNodeActionList keep track of the actual actions we need to perform 
-       // on the node tracker.
-       NodeToKeyMap _newkeys;
-       KeyToNodeMap _newnodes;
-       NodeTrackerEventTracker _node_action_tracker;
-
-       typedef std::map< XML::Node*, XML::Node* > _pc_map_type;
-       _pc_map_type _parent_child_map;
-
-       XMLNodeTracker* _xnt;
-
-       XML::LogBuilder _builder;
-};
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 0fed24e45461ec63f319ebd1586dd12729f0024b..2f20405d6186a34a2d2ae1cb7d64def6df6a4015 100644 (file)
@@ -1,14 +1 @@
-/// Some archivers don't seem to like creating an archive without being
-/// given any members to archive.  This file acts as a placeholder
-
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// empty file to generate a null object file; needed by some archiver tools
diff --git a/src/jabber_whiteboard/error-codes.h b/src/jabber_whiteboard/error-codes.h
deleted file mode 100644 (file)
index e5c6268..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * Whiteboard session manager
- * Error codes
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_JABBER_ERROR_CODES_H__
-#define __WHITEBOARD_JABBER_ERROR_CODES_H__
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-namespace ErrorCodes {
-
-static unsigned int const SERVER_CONNECT_FAILED = 502;
-static unsigned int const CHAT_HANDLE_IN_USE = 409;
-
-}
-
-}
-
-}
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/inkboard-document.cpp b/src/jabber_whiteboard/inkboard-document.cpp
new file mode 100644 (file)
index 0000000..a3881af
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * Inkscape::Whiteboard::InkboardDocument - Inkboard document implementation
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ *
+ * Copyright (c) 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <glibmm.h>
+
+#include "jabber_whiteboard/inkboard-document.h"
+
+#include "xml/simple-session.h"
+#include "jabber_whiteboard/inkboard-session.h"
+
+#include "jabber_whiteboard/session-manager.h"
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+InkboardDocument::InkboardDocument(int code, SessionType type, Glib::ustring const& to) :
+       XML::SimpleNode(code), _type(type), _recipient(to)
+{
+       _initBindings();
+}
+
+void
+InkboardDocument::_initBindings()
+{
+       _bindDocument(*this);
+       _bindLogger(*(new XML::SimpleSession()));
+}
+
+void
+InkboardDocument::setRecipient(Glib::ustring const& val)
+{
+       this->_recipient = val;
+}
+
+Glib::ustring 
+InkboardDocument::getRecipient() const
+{
+       return this->_recipient;
+}
+
+void
+InkboardDocument::startSessionNegotiation()
+{
+       SessionManager& sm = SessionManager::instance();
+        switch (_type) {
+            case INKBOARD_MUC:
+                sm.sendGroup(_recipient, CHATROOM_SYNCHRONIZE_REQUEST, " ");
+                break;
+            case INKBOARD_PRIVATE:
+            default:
+                sm.send(_recipient, CONNECT_REQUEST_USER, " ");
+                break;
+        }
+}
+
+void
+InkboardDocument::terminateSession()
+{
+
+}
+
+void
+InkboardDocument::processInkboardEvent(MessageType mtype, unsigned int seqnum, Glib::ustring const& data)
+{
+    g_log(NULL, G_LOG_LEVEL_DEBUG, "Processing Inkboard event: mtype=%d seqnum=%d data=%s\n", mtype, seqnum, data.c_str());
+}
+
+}
+
+}
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/inkboard-document.h b/src/jabber_whiteboard/inkboard-document.h
new file mode 100644 (file)
index 0000000..0c147d3
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * Inkscape::Whiteboard::InkboardDocument - Inkboard document implementation
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ *
+ * Copyright (c) 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef __INKSCAPE_WHITEBOARD_INKBOARDDOCUMENT_H__
+#define __INKSCAPE_WHITEBOARD_INKBOARDDOCUMENT_H__
+
+#include <glibmm.h>
+
+#include "xml/document.h"
+#include "xml/simple-node.h"
+
+#include "jabber_whiteboard/keynode.h"
+#include "jabber_whiteboard/session-manager.h"
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+class InkboardDocument : public XML::SimpleNode, public XML::Document {
+public:
+       explicit InkboardDocument(int code, SessionType type, Glib::ustring const& to);
+
+       XML::NodeType type() const
+       {
+               return Inkscape::XML::DOCUMENT_NODE;
+       }
+
+       void setRecipient(Glib::ustring const& val);
+       Glib::ustring getRecipient() const;
+
+    void startSessionNegotiation();
+    void terminateSession();
+    void processInkboardEvent(MessageType mtype, unsigned int seqnum, Glib::ustring const& data);
+
+protected:
+       /**
+        * Copy constructor.
+        * 
+        * \param orig Instance to copy.
+        */
+       InkboardDocument(InkboardDocument const& orig) :
+               XML::Node(), XML::SimpleNode(orig), XML::Document(), _recipient(orig._recipient)
+       {
+               _initBindings();
+       }
+
+       XML::SimpleNode* _duplicate() const
+       {
+               return new InkboardDocument(*this);
+       }
+
+private:
+       void _initBindings();
+
+    SessionType _type;
+       Glib::ustring _recipient;
+
+    KeyNodeTable _tracker;
+};
+
+}
+
+}
+
+#endif
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/inkboard-session.cpp b/src/jabber_whiteboard/inkboard-session.cpp
new file mode 100644 (file)
index 0000000..e6ff67f
--- /dev/null
@@ -0,0 +1,128 @@
+/**
+ * Inkscape::Whiteboard::InkboardSession - Whiteboard implementation of XML::Session
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ *
+ * Copyright (c) 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm.h>
+#include <glib/gmessages.h>
+#include <glib/gquark.h>
+
+#include "jabber_whiteboard/inkboard-session.h"
+
+#include "xml/node.h"
+#include "xml/event.h"
+#include "xml/element-node.h"
+#include "xml/text-node.h"
+#include "xml/comment-node.h"
+
+#include "util/share.h"
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+using XML::Node;
+
+void
+InkboardSession::beginTransaction()
+{
+       g_assert(!_in_transaction);
+       _in_transaction = true;
+}
+
+void
+InkboardSession::rollback()
+{
+       g_assert(_in_transaction);
+       _in_transaction = false;
+}
+
+void 
+InkboardSession::commit()
+{
+       g_assert(_in_transaction);
+       _in_transaction = false;
+}
+
+XML::Event*
+InkboardSession::commitUndoable()
+{
+       g_assert(_in_transaction);
+       _in_transaction = false;
+       return NULL;
+}
+
+XML::Node*
+InkboardSession::createElementNode(char const* name)
+{
+       g_log(NULL, G_LOG_LEVEL_DEBUG, "InkboardSession::createElementNode");
+       return new XML::ElementNode(g_quark_from_string(name));
+}
+
+XML::Node*
+InkboardSession::createTextNode(char const* content)
+{
+       g_log(NULL, G_LOG_LEVEL_DEBUG, "InkboardSession::createTextNode");
+    return new XML::TextNode(Util::share_string(content));
+}
+
+XML::Node*
+InkboardSession::createCommentNode(char const* content)
+{
+       g_log(NULL, G_LOG_LEVEL_DEBUG, "InkboardSession::createCommentNode");
+    return new XML::CommentNode(Util::share_string(content));
+}
+
+
+void InkboardSession::notifyChildAdded(Node &parent,
+                                     Node &child,
+                                     Node *prev)
+{
+    if (_in_transaction) {
+
+    }
+}
+
+void InkboardSession::notifyChildRemoved(Node &parent,
+                                       Node &child,
+                                       Node *prev)
+{
+    if (_in_transaction) {
+    }
+}
+
+void InkboardSession::notifyChildOrderChanged(Node &parent,
+                                            Node &child,
+                                            Node *old_prev,
+                                            Node *new_prev)
+{
+    if (_in_transaction) {
+    }
+}
+
+void InkboardSession::notifyContentChanged(Node &node,
+                                         Util::SharedCStringPtr old_content,
+                                         Util::SharedCStringPtr new_content)
+{
+    if (_in_transaction) {
+    }
+}
+
+void InkboardSession::notifyAttributeChanged(Node &node,
+                                           GQuark name,
+                                           Util::SharedCStringPtr old_value,
+                                           Util::SharedCStringPtr new_value)
+{
+    if (_in_transaction) {
+    }
+}
+
+}
+
+}
diff --git a/src/jabber_whiteboard/inkboard-session.h b/src/jabber_whiteboard/inkboard-session.h
new file mode 100644 (file)
index 0000000..7ac5e4a
--- /dev/null
@@ -0,0 +1,121 @@
+/**
+ * Inkscape::Whiteboard::InkboardSession - Whiteboard implementation of XML::Session interface
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ *
+ * Copyright (c) 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef __INKSCAPE_WHITEBOARD_SESSION_H__
+#define __INKSCAPE_WHITEBOARD_SESSION_H__
+
+#include <glibmm.h>
+#include <bitset>
+
+#include "pedro/pedroxmpp.h"
+#include "jabber_whiteboard/internal-constants.h"
+
+#include "xml/simple-session.h"
+#include "util/share.h"
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+class InkboardSession : public GC::Managed<>,
+                                               public XML::Session,
+                                               public XML::TransactionLogger
+{
+public:
+       InkboardSession() : _in_transaction(false) { }
+       InkboardSession(Glib::ustring const& name) : _in_transaction(false), _name(name) { }
+       virtual ~InkboardSession() { }
+    
+    /**
+     * Returns the name of this session.
+        * \return The name of this session.
+     */
+    virtual Glib::ustring getName() const
+        { return _name; }
+        
+    /**
+     * Sets the name of this session.
+        *
+        * \param val The name to use.
+     */
+    virtual void setName(const Glib::ustring &val)
+        { _name = val; }
+
+       /**
+        * Returns status attributes of this session.
+        *
+        * \return Status of this session.
+        */
+       virtual std::bitset< NUM_FLAGS > const& getStatus() const
+       {
+               return status;
+       }
+
+       //
+       // XML::TransactionLogger methods
+       //
+       Session& session()
+       {
+               return *this;
+       }
+
+       // 
+       // XML::Session methods
+       // 
+       bool inTransaction() 
+       {
+               return _in_transaction;
+       }
+
+       void beginTransaction();
+       void rollback();
+       void commit();
+
+       XML::Event* commitUndoable();
+
+       XML::Node* createElementNode(char const* name);
+       XML::Node* createTextNode(char const* content);
+       XML::Node* createCommentNode(char const* content);
+
+       //
+       // XML::NodeObserver methods
+       // (inherited from XML::TransactionLogger)
+       //
+    void notifyChildAdded(Inkscape::XML::Node &parent, Inkscape::XML::Node &child, Inkscape::XML::Node *prev);
+
+    void notifyChildRemoved(Inkscape::XML::Node &parent, Inkscape::XML::Node &child, Inkscape::XML::Node *prev);
+
+    void notifyChildOrderChanged(Inkscape::XML::Node &parent, Inkscape::XML::Node &child,
+                                 Inkscape::XML::Node *old_prev, Inkscape::XML::Node *new_prev);
+
+    void notifyContentChanged(Inkscape::XML::Node &node,
+                              Util::ptr_shared<char> old_content,
+                              Util::ptr_shared<char> new_content);
+
+    void notifyAttributeChanged(Inkscape::XML::Node &node, GQuark name,
+                                Util::ptr_shared<char> old_value,
+                                Util::ptr_shared<char> new_value);
+
+private:
+    InkboardSession(InkboardSession const &); // no copy
+    void operator=(InkboardSession const &); // no assign
+
+       bool _in_transaction;
+
+    std::bitset< NUM_FLAGS > status;
+       Glib::ustring _name;
+};
+
+}
+
+}
+
+#endif
index 4956a402c54ab7cfe9cc2756117cf46425816c3b..44355c8a0f32920bdb3874aa067e5d75e048d86c 100644 (file)
@@ -68,9 +68,9 @@ int const SEND_TIMEOUT = 35;
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index 5a14737beefc760bed9563f7f08dcd3d8cabfadd..737eacdc7d9b25a52e22aa6c998933d3fa0fa8c5 100644 (file)
@@ -65,6 +65,7 @@ extern int const PLAYING_SESSION_FILE;
 // accomodate Inkscape, not the other way around...
 // Dispatch interval (in milliseconds)
 extern int const SEND_TIMEOUT;
+
 }
 
 }
@@ -75,9 +76,9 @@ extern int const SEND_TIMEOUT;
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index 8590abab8bf7901a35a99aa2740b9f56b28e1851..77fd75fcd740e7ede8450c3ce682196bc9932806 100644 (file)
@@ -10,6 +10,8 @@
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
+#include <gtkmm.h>
+#include <glibmm.h>
 #include <glibmm/i18n.h>
 
 #include "invitation-confirm-dialog.h"
index 42cea9b560d0ef874f23384cf93ffabecc17f9a8..b73a0e3bc563a3fee00378c4177a0e6782154cd1 100644 (file)
 #ifndef __WHITEBOARD_INVITATION_CONFIRM_DIALOG_H__
 #define __WHITEBOARD_INVITATION_CONFIRM_DIALOG_H__
 
-#include <gtkmm/messagedialog.h>
-#include <gtkmm/checkbutton.h>
-#include <gtkmm/entry.h>
-
-#include "jabber_whiteboard/session-file-selector.h"
+#include <gtkmm.h>
+#include <glibmm.h>
 
+#include "session-file-selector.h"
 
 namespace Inkscape {
 
diff --git a/src/jabber_whiteboard/invitation-handlers.cpp b/src/jabber_whiteboard/invitation-handlers.cpp
new file mode 100644 (file)
index 0000000..124b951
--- /dev/null
@@ -0,0 +1,150 @@
+/**
+ * Whiteboard session manager - invitation handling methods
+ *
+ * Authors: 
+ * David Yip <yipdw@rose-hulman.edu>
+ * Bob Jamison (Pedro port)
+ *
+ * Copyright (c) 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm.h>
+#include <glibmm/i18n.h>
+
+#include "util/ucompose.hpp"
+
+#include "document.h"
+#include "desktop-handles.h"
+
+#include "jabber_whiteboard/inkboard-document.h"
+#include "jabber_whiteboard/session-manager.h"
+#include "jabber_whiteboard/invitation-confirm-dialog.h"
+
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+bool
+SessionManager::_checkInvitationQueue()
+{
+       int x, y;
+       Gdk::ModifierType mt;
+       Gdk::Display::get_default()->get_pointer(x, y, mt);
+       if (mt & GDK_BUTTON1_MASK) {
+               // The user is currently busy with an action.  Defer invitation processing 
+               // until the user is free.
+               return true;
+       }
+
+       if (_pending_invitations.size() > 0) {
+               // There's an invitation to process; process it.
+               Glib::ustring from = _pending_invitations.front();
+
+               Glib::ustring primary = "<span weight=\"bold\" size=\"larger\">" + String::ucompose(_("<b>%1</b> has invited you to a whiteboard session."), from) + "</span>\n\n";
+               primary += String::ucompose(_("Do you wish to accept <b>%1</b>'s whiteboard session invitation?"), from);
+
+               InvitationConfirmDialog dialog(primary);
+               
+               dialog.add_button(_("Accept invitation"), ACCEPT_INVITATION);
+               dialog.add_button(_("Decline invitation"), DECLINE_INVITATION);
+
+               InvitationResponses resp = static_cast< InvitationResponses >(dialog.run());
+
+               switch (resp) {
+                       case ACCEPT_INVITATION:
+                       {
+                               SPDesktop* dt = createInkboardDesktop(from, INKBOARD_PRIVATE);
+                               InkboardDocument* idoc = dynamic_cast< InkboardDocument* >(sp_desktop_document(dt)->rdoc);
+                               send(from, CONNECT_REQUEST_RESPONSE_USER, " ");
+                               break;
+                       }
+                       case DECLINE_INVITATION:
+                       {
+                               break;
+                       }
+                       default:
+                               send(from, CONNECT_REQUEST_REFUSED_BY_PEER, " ");
+                               break;
+               }
+
+               _pending_invitations.pop_front();
+       }
+
+       return true;
+}
+
+
+bool
+SessionManager::_checkInvitationResponseQueue()
+{
+       int x, y;
+       Gdk::ModifierType mt;
+       Gdk::Display::get_default()->get_pointer(x, y, mt);
+       if (mt & GDK_BUTTON1_MASK) {
+               // The user is currently busy with an action.  Defer invitation response processing 
+               // until the user is free.
+               return true;
+       }
+
+       if (_invitation_responses.size() > 0) {
+               Invitation_response_type response = _invitation_responses.front();
+
+               switch (response.second) {
+                       case ACCEPT_INVITATION:
+                       {
+                               break;
+                       }
+                       case DECLINE_INVITATION:
+                       {
+                               Glib::ustring primary = String::ucompose(_("<span weight=\"bold\" size=\"larger\">The user <b>%1</b> has refused your whiteboard invitation.</span>\n\n"), response.first);
+
+                               // TRANSLATORS: %1 is the peer whom refused our invitation, %2 is our Jabber identity.
+                               Glib::ustring secondary = String::ucompose(_("You are still connected to a Jabber server as <b>%2</b>, and may send an invitation to <b>%1</b> again, or you may send an invitation to a different user."), response.first, this->getClient().getJid());
+
+                               Gtk::MessageDialog dialog(primary + secondary, true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, false);
+                               dialog.run();
+                               terminateInkboardSession(response.first);
+                               break;
+                       }
+                       case PEER_ALREADY_IN_SESSION:
+                               break;
+
+                       case UNSUPPORTED_PROTOCOL:
+                       {
+                               Glib::ustring primary = String::ucompose(_("<span weight=\"bold\" size=\"larger\">The user <b>%1</b> is using an incompatible version of Inkboard.</span>\n\n"), response.first);
+
+                               // TRANSLATORS: %1 is the peer whom refused our invitation, %2 is our Jabber identity.
+                               Glib::ustring secondary = String::ucompose(_("Inkscape cannot connect to <b>%1</b>.\n\nYou are still connected to a Jabber server as <b>%2</b>."), response.first, this->getClient().getJid());
+
+                               Gtk::MessageDialog dialog(primary + secondary, true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, false);
+                               dialog.run();
+                               terminateInkboardSession(response.first);
+                               break;
+                       }
+                       default:
+                               break;
+               }
+
+               _invitation_responses.pop_front();
+       }
+
+       return true;
+}
+
+}
+
+}
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/jabber-handlers.cpp b/src/jabber_whiteboard/jabber-handlers.cpp
deleted file mode 100644 (file)
index 3089780..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Whiteboard session manager
- * C-style Loudmouth callbacks
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/jabber-handlers.h"
-#include "jabber_whiteboard/message-handler.h"
-#include "jabber_whiteboard/session-manager.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-LmHandlerResult
-default_handler(LmMessageHandler* handler, LmConnection* connection, LmMessage* message, gpointer user_data)
-{
-       MessageHandler* mh = reinterpret_cast< MessageHandler* >(user_data);
-       return mh->handle(message, DEFAULT);
-}
-
-
-LmHandlerResult
-presence_handler(LmMessageHandler* handler, LmConnection* connection, LmMessage* message, gpointer user_data)
-{
-       MessageHandler* mh = reinterpret_cast< MessageHandler* >(user_data);
-       return mh->handle(message, PRESENCE);
-}
-
-
-LmHandlerResult
-stream_error_handler(LmMessageHandler* handler, LmConnection* connection, LmMessage* message, gpointer user_data)
-{
-       MessageHandler* mh = reinterpret_cast< MessageHandler* >(user_data);
-       return mh->handle(message, ERROR);
-}
-
-LmSSLResponse
-ssl_error_handler(LmSSL* ssl, LmSSLStatus status, gpointer user_data)
-{
-       SessionManager* sm = reinterpret_cast< SessionManager* >(user_data);
-       return sm->handleSSLError(ssl, status);
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/jabber-handlers.h b/src/jabber_whiteboard/jabber-handlers.h
deleted file mode 100644 (file)
index 2eec08c..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Whiteboard session manager
- * C-style Loudmouth callbacks
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_LOUDMOUTH_CALLBACKS__
-#define __WHITEBOARD_LOUDMOUTH_CALLBACKS__
-
-extern "C" {
-#include <loudmouth/loudmouth.h>
-}
-
-#include <glib.h>
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-/**
- * C-style callback for Loudmouth to handle received presence messages.
- *
- * \param handler The LmMessageHandler handling this event.
- * \param connection The LmConnection with which the LmMessageHandler is associated.
- * \param message The Jabber message received that triggered this handler.
- * \param user_data A pointer to an instance of Inkscape::Whiteboard::MessageHandler, which performs
- * the real message processing work.
- */
-LmHandlerResult presence_handler(LmMessageHandler* handler, LmConnection* connection, LmMessage* message, gpointer user_data);
-
-/**
- * C-style callback for Loudmouth to handle received messages.
- *
- * This handler handles messages that are not presence or error messages.
- *
- * \param handler The LmMessageHandler handling this event.
- * \param connection The LmConnection with which the LmMessageHandler is associated.
- * \param message The Jabber message received that triggered this handler.
- * \param user_data A pointer to an instance of Inkscape::Whiteboard::MessageHandler, which performs
- * the real message processing work.
- */
-LmHandlerResult default_handler(LmMessageHandler* handler, LmConnection* connection, LmMessage* message, gpointer user_data);
-
-/**
- * C-style callback for Loudmouth to handle received error messages.
- *
- * \param handler The LmMessageHandler handling this event.
- * \param connection The LmConnection with which the LmMessageHandler is associated.
- * \param message The Jabber message received that triggered this handler.
- * \param user_data A pointer to an instance of Inkscape::Whiteboard::MessageHandler, which performs
- * the real message processing work.
- */
-LmHandlerResult stream_error_handler(LmMessageHandler* handler, LmConnection* connection, LmMessage* message, gpointer user_data);
-
-/**
- * C-style callback for Loudmouth to handle SSL errors.
- * 
- * \param ssl The SSL data structure used by Loudmouth.
- * \param status The error code representing the error that occurred.
- * \param user_data A pointer to the SessionManager instance handling associated with the connection attempt that 
- * threw the SSL error.
- */
-LmSSLResponse ssl_error_handler(LmSSL* ssl, LmSSLStatus status, gpointer user_data);
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/keynode.cpp b/src/jabber_whiteboard/keynode.cpp
new file mode 100644 (file)
index 0000000..d9af43f
--- /dev/null
@@ -0,0 +1,128 @@
+/**
+ * Inkscape::Whiteboard::KeyNodeTable - structure for lookup of values from keys
+ * and vice versa
+ *
+ * Authors:
+ * Bob Jamison
+ *
+ * Copyright (c) 2005 Authors
+ */
+#include "keynode.h"
+
+
+namespace Inkscape
+{
+namespace Whiteboard
+{
+
+
+
+void KeyNodeTable::clear()
+{
+    items.clear();
+}
+
+void KeyNodeTable::append(const KeyNodeTable &other)
+{
+    for (unsigned int i = 0; i<other.size() ; i++)
+        {
+        KeyNodePair pair = other.item(i);
+        put(pair);
+        }
+}
+
+void KeyNodeTable::put(const KeyNodePair &pair)
+{
+    put(pair.key, pair.node);
+}
+
+void KeyNodeTable::put(const Glib::ustring &key, const XML::Node *node)
+{
+    //delete existing
+    std::vector<KeyNodePair>::iterator iter;
+    for (iter = items.begin() ; iter != items.end() ; )
+        {
+        if (key == iter->key || node == iter->node)
+            iter = items.erase(iter);
+        else
+            iter++;
+        }
+        
+    //add new
+    KeyNodePair pair(key, node);
+    items.push_back(pair);
+}
+
+XML::Node * KeyNodeTable::get(const Glib::ustring &key) const
+{
+    std::vector<KeyNodePair>::const_iterator iter;
+    for (iter = items.begin() ; iter != items.end() ; iter++)
+        {
+        if (key == iter->key)
+            return iter->node;
+        }
+    return NULL;
+}
+
+
+void KeyNodeTable::remove(const Glib::ustring &key)
+{
+    std::vector<KeyNodePair>::iterator iter;
+    for (iter = items.begin() ; iter != items.end() ; )
+        {
+        if (key == iter->key)
+            iter = items.erase(iter);
+        else
+            iter++;
+        }
+}
+
+
+Glib::ustring KeyNodeTable::get(XML::Node *node) const
+{
+    std::vector<KeyNodePair>::const_iterator iter;
+    for (iter = items.begin() ; iter != items.end() ; iter++)
+        {
+        if (node == iter->node)
+            return iter->key;
+        }
+    return "";
+}
+
+
+void KeyNodeTable::remove(XML::Node *node)
+{
+    std::vector<KeyNodePair>::iterator iter;
+    for (iter = items.begin() ; iter != items.end() ; )
+        {
+        if (node == iter->node)
+            iter = items.erase(iter);
+        else
+            iter++;
+        }
+}
+
+unsigned int KeyNodeTable::size() const
+{
+    return items.size();
+}
+
+
+KeyNodePair KeyNodeTable::item(unsigned int index) const
+{
+    if (index>=items.size())
+        {
+        KeyNodePair pair("", NULL);
+        return pair;
+        }
+    return items[index];
+}
+
+
+
+} // namespace Whiteboard
+
+} // namespace Inkscape
+//#########################################################################
+//# E N D    O F    F I L E
+//#########################################################################
diff --git a/src/jabber_whiteboard/keynode.h b/src/jabber_whiteboard/keynode.h
new file mode 100644 (file)
index 0000000..a224b7c
--- /dev/null
@@ -0,0 +1,95 @@
+/**
+ * Inkscape::Whiteboard::KeyNodeTable - structure for lookup of values from keys
+ * and vice versa
+ *
+ * Authors:
+ * Bob Jamison
+ *
+ * Copyright (c) 2005 Authors
+ */
+#ifndef __KEY_NODE_H__
+#define __KEY_NODE_H__
+
+#include <glibmm.h>
+
+#include <vector>
+
+#include "xml/node.h"
+
+
+namespace Inkscape
+{
+namespace Whiteboard
+{
+
+
+class KeyNodePair
+{
+public:
+   KeyNodePair(const Glib::ustring &keyArg, const XML::Node *nodeArg)
+       {
+       key  = keyArg; 
+       node = (XML::Node *)nodeArg;
+       }
+   KeyNodePair(const KeyNodePair &other)
+       {
+       key  = other.key; 
+       node = other.node;
+       }
+   virtual ~KeyNodePair()
+       {}
+   Glib::ustring key;
+   XML::Node *node;
+};
+
+class KeyNodeTable
+{
+public:
+
+    KeyNodeTable()
+        {}
+    
+    KeyNodeTable(const KeyNodeTable &other)
+        {
+        items = other.items;
+        }
+        
+    virtual ~KeyNodeTable()
+        {}
+        
+    virtual void clear();
+        
+    virtual void append(const KeyNodeTable &other);
+
+    virtual void put(const KeyNodePair &pair);
+    
+    virtual void put(const Glib::ustring &key, const XML::Node *node);
+    
+    virtual XML::Node * get(const Glib::ustring &key) const;
+    
+    virtual void remove(const Glib::ustring &key);
+
+    virtual Glib::ustring get(XML::Node *node) const;
+    
+    virtual void remove(XML::Node *node);
+
+    virtual unsigned int size() const;
+    
+    virtual KeyNodePair item(unsigned int index) const;
+
+private:
+
+    std::vector<KeyNodePair> items;
+
+};
+
+
+
+} // namespace Whiteboard
+
+} // namespace Inkscape
+
+
+#endif /* __KEY_NODE_H__ */
+
+
index 2077dcc6dc2436617567cd0cbd65174aa84897e3..7d4ee4b3f4cd4357b12b284e8d732aa75f4b7509 100644 (file)
@@ -56,9 +56,9 @@ MessageAggregator::addOne(Glib::ustring const& msg)
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index 56cd8e3da5c722424e4e8ca07e2e1a1e153d14ea..505e65f121a9926e592f14899969645068790cae 100644 (file)
@@ -73,8 +73,9 @@ public:
        /**
         * Return the aggregate message.
         *
-        * Because this method returns a reference to a string, it is not safe for use 
-        * across multiple invocations of this Deserializer.
+        * Because this method returns a reference to a string, it is not safe to assume
+         * that its contents will remain untouched across two calls to this MessageAggregator.
+         * If you require that guarantee, make a copy.
         *
         * \return A reference to the aggregate message.
         */
@@ -127,9 +128,9 @@ private:
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/jabber_whiteboard/message-contexts.cpp b/src/jabber_whiteboard/message-contexts.cpp
deleted file mode 100644 (file)
index 70983ba..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/**
- * Whiteboard session manager
- * Inkboard message context definitions
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/message-contexts.h"
-
-#include <bitset>
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-void
-initialize_received_message_contexts(MessageContextMap& mcm)
-{
-
-       // Each Inkboard message has a context of validity according to an Inkboard 
-       // client's state.  That is, certain messages should be acknowledged and processed
-       // in some states, whereas other messages should not.
-       // For instance, a whiteboard invitation should be acknowledged if an Inkboard
-       // client is not in a whiteboard session, but should be refused if said client
-       // _is_ in a whiteboard session.
-
-       // Only the flags that are required to be set must be set; all flags, by default,
-       // are zero.  Explicit definition doesn't hurt, though.
-
-       // The general format of message context creation and registration is
-       // std::bitset< NUM_FLAGS > m_
-       // m_.set( );
-       // m_.set( );
-       // mcm[ ] = m_;
-
-
-       // Begin
-
-       // Special bitsets
-       std::bitset< NUM_FLAGS > all_contexts;
-       all_contexts.flip();
-
-       // Messages: CHANGE_NOT_REPEATABLE, CHANGE_REPEATABLE, DUMMY_CHANGE, CHANGE_COMMIT
-       std::bitset< NUM_FLAGS > m1;
-       m1.set(LOGGED_IN);
-       m1.set(IN_WHITEBOARD);
-       m1.set(IN_CHATROOM);
-       m1.set(SYNCHRONIZING_WITH_CHAT);
-       mcm[CHANGE_NOT_REPEATABLE] = m1;
-       mcm[CHANGE_REPEATABLE] = m1;
-       mcm[DUMMY_CHANGE] = m1;
-       mcm[CHANGE_COMMIT] = m1;
-
-       // Messages: DOCUMENT_BEGIN, DOCUMENT_END
-       std::bitset< NUM_FLAGS > m4;
-       m4.set(LOGGED_IN);
-       m4.set(IN_WHITEBOARD);
-       m4.set(SYNCHRONIZING_WITH_CHAT);
-       mcm[DOCUMENT_BEGIN] = m4;
-       mcm[DOCUMENT_END] = m4;
-
-       // Message: CONNECT_REQUEST_USER
-       std::bitset< NUM_FLAGS > m5;
-       m5.set(LOGGED_IN);
-
-       // We should still _accept_ CONNECT_REQUEST_USER messages even if we're already
-       // waiting for a response.  It is up to the higher-level handler (i.e. the connection
-       // request handler) to properly handle it.
-       m5.set(WAITING_FOR_INVITE_RESPONSE);
-       mcm[CONNECT_REQUEST_USER] = m5;
-
-       // Message: CONNECT_REQUEST_RESPONSE_USER
-       std::bitset< NUM_FLAGS > m6;
-       m6.set(LOGGED_IN);
-       m6.set(WAITING_FOR_INVITE_RESPONSE);
-       mcm[CONNECT_REQUEST_RESPONSE_USER] = m6;
-
-       // Message: CHATROOM_SYNCHRONIZE_REQUEST
-       std::bitset< NUM_FLAGS > m7;
-       m7.set(LOGGED_IN);
-       m7.set(IN_CHATROOM);
-       m7.set(IN_WHITEBOARD);
-       mcm[CHATROOM_SYNCHRONIZE_REQUEST] = m7;
-
-       // Message: CHATROOM_SYNCHRONIZE_RESPONSE
-       std::bitset< NUM_FLAGS > m8;
-       m8.set(LOGGED_IN);
-       m8.set(WAITING_TO_SYNC_TO_CHAT);
-       mcm[CHATROOM_SYNCHRONIZE_RESPONSE] = m8;
-       
-       // Message: CONNECT_REQUEST_RESPONSE_CHAT
-       std::bitset< NUM_FLAGS > m9;
-       m9.set(LOGGED_IN);
-       m9.set(IN_CHATROOM);
-       m9.set(IN_WHITEBOARD);
-       mcm[CONNECT_REQUEST_RESPONSE_CHAT] = m9;
-
-       // Message: CONNECTED_SIGNAL
-       mcm[CONNECTED_SIGNAL] = all_contexts;
-
-       // Message: DISCONNECTED_FROM_USER_SIGNAL
-       std::bitset< NUM_FLAGS > m11;
-       m11.set(LOGGED_IN);
-       m11.set(IN_WHITEBOARD);
-       mcm[DISCONNECTED_FROM_USER_SIGNAL] = m11;
-
-       // Messages: CONNECT_REQUEST_REFUSED_BY_PEER, ALREADY_IN_SESSION
-       std::bitset< NUM_FLAGS > m12;
-       m12.set(LOGGED_IN);
-       m12.set(WAITING_FOR_INVITE_RESPONSE);
-       mcm[CONNECT_REQUEST_REFUSED_BY_PEER] = m12;
-       mcm[ALREADY_IN_SESSION] = m12;
-
-       // Message: UNSUPPORTED_PROTOCOL_VERSION
-       std::bitset< NUM_FLAGS > m14;
-       m14.set(LOGGED_IN);
-       mcm[UNSUPPORTED_PROTOCOL_VERSION] = m14;
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/message-contexts.h b/src/jabber_whiteboard/message-contexts.h
deleted file mode 100644 (file)
index 49653c6..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Whiteboard session manager
- * Inkboard message context definitions
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_MESSAGE_CONTEXTS_H__
-#define __WHITEBOARD_MESSAGE_CONTEXTS_H__
-
-#include "jabber_whiteboard/typedefs.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-void initialize_received_message_contexts(MessageContextMap& mcm);
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/message-handler.cpp b/src/jabber_whiteboard/message-handler.cpp
deleted file mode 100644 (file)
index 9551a8e..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/**
- * Whiteboard session manager
- * Jabber received message handling
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- * Steven Montgomery, Jonas Collaros (original C version)
- *
- * Copyright (c) 2004-2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-extern "C" {
-#include <loudmouth/loudmouth.h>
-}
-
-#include <glibmm.h>
-#include <glibmm/i18n.h>
-#include <glib.h>
-#include <map>
-
-#include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/typedefs.h"
-#include "jabber_whiteboard/message-processors.h"
-#include "jabber_whiteboard/message-handler.h"
-#include "jabber_whiteboard/session-manager.h"
-#include "jabber_whiteboard/chat-handler.h"
-#include "jabber_whiteboard/buddy-list-manager.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-bool message_contexts_initialized = false;
-MessageContextMap _received_message_contexts;
-
-MessageHandler::MessageHandler(SessionManager* sm) : _sm(sm)
-{
-       if (message_contexts_initialized == false) {
-//             this->_initializeContexts();
-               MessageHandler::_initializeContexts();
-       }
-       this->_initializeProcessors();
-}
-
-MessageHandler::~MessageHandler()
-{
-       this->_destructProcessors();
-}
-
-LmHandlerResult
-MessageHandler::handle(LmMessage* message, HandlerMode mode)
-{
-       if (this->_isValidMessage(message)) {
-               switch(mode) {
-                       case DEFAULT:
-                               return this->_default(message);
-                       case PRESENCE:
-                               return this->_presence(message);
-                       case ERROR:
-                               return this->_error(message);
-                       default:
-                               g_warning("Jabber message handler was asked to process a message of an unhandled type; discarding message.");
-                               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-               }
-       } else {
-               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-       }
-}
-
-bool
-MessageHandler::_hasValidReceiveContext(LmMessage* message)
-{
-       MessageType type = this->_getType(message);
-       std::bitset< NUM_FLAGS >& status = this->_sm->session_data->status;
-
-       std::string s1 = status.to_string< char, std::char_traits< char >, std::allocator< char > >();
-
-
-       if (type == UNKNOWN) {
-               // unknown types never have a valid receive context
-               return false;
-       } else {
-               std::bitset< NUM_FLAGS >& recvcontext = _received_message_contexts[type];
-               
-               // TODO: remove this debug block
-               if ((status & recvcontext).to_ulong() < status.to_ulong()) {
-                       g_warning("Received message in incorrect context; discarding message.");
-
-                       std::string s2 = recvcontext.to_string< char, std::char_traits< char >, std::allocator< char > >();
-
-                       g_warning("current context=%s required context=%s (msgtype %s)", s1.c_str(), s2.c_str(), MessageHandler::ink_type_to_string(type));
-               }
-
-               return ((status & recvcontext).to_ulong() >= status.to_ulong());
-       }
-}
-
-bool
-MessageHandler::_isValidMessage(LmMessage* message)
-{
-       // Global sanity checks
-       LmMessageNode* root;
-       LmMessageNode* protocolver;
-       LmMessageNode* offline;
-       LmMessageType mtype;
-       LmMessageSubType msubtype;
-       gchar const* tmp;
-
-       Glib::ustring sender;
-
-       
-       // 0.  The message must have a root node.
-       root = lm_message_get_node(message);
-       if (root == NULL) {
-               g_warning("Check 0 failed (message has no root node)");
-               return false;
-       }
-       
-
-       // 1.  The message must be of LM_MESSAGE_TYPE_MESSAGE to continue the sanity checks.
-       // If it is not, check to see if it is either
-       // a presence message or an error message.  If it is either of these, then automatically
-       // consider it sane.  
-       //
-       // FIXME:
-       // (That is probably a dangerous assumption.  We should probably at least validate
-       // the source for error messages.)
-       // 
-       // We do not handle IQ stanzas or STREAM messages (yet), and we certainly don't
-       // handle unknowns.
-       
-       mtype = lm_message_get_type(message);
-       switch(mtype) {
-               case LM_MESSAGE_TYPE_PRESENCE:
-               case LM_MESSAGE_TYPE_STREAM_ERROR:
-                       return true;
-               case LM_MESSAGE_TYPE_IQ:
-               case LM_MESSAGE_TYPE_STREAM:
-               case LM_MESSAGE_TYPE_UNKNOWN:
-                       g_warning("Check 1 failed (Loudmouth reported type IQ, STREAM, or UNKNOWN)");
-                       return false;
-               case LM_MESSAGE_TYPE_MESSAGE:
-                       break;
-       }
-       
-       // 2.  The message must contain the JID of the sender.
-       tmp = lm_message_node_get_attribute(root, MESSAGE_FROM);
-
-       if (tmp == NULL) {
-               g_warning("Check 2 failed (no sender attribute present)");
-               return false;
-       } else {
-               sender = tmp;
-       }
-
-       // 3.  We do not yet handle messages from offline storage, so ensure that this is not
-       // such a message.
-       offline = lm_message_node_get_child(root, "x");
-       if (offline != NULL) {
-               gchar const* val = lm_message_node_get_value(offline);
-               if (val != NULL) {
-                       if (strcmp(val, "Offline Storage") == 0) {
-                               return false;
-                       }
-               }
-       }
-
-
-       // 4.  If this is a regular chat message...
-       msubtype = lm_message_get_sub_type(message);
-
-       if (msubtype == LM_MESSAGE_SUB_TYPE_CHAT) {
-               // 4a.  A protocol version node must be present.
-               protocolver = lm_message_node_get_child(root, MESSAGE_PROTOCOL_VER);
-               if (protocolver == NULL) {
-                       g_warning("Check 4a failed (no protocol attribute in chat message)");
-                       return false;
-               } else {
-                       tmp = lm_message_node_get_value(protocolver);
-                       if (tmp == NULL) {
-                               g_warning("Check 4a failed (no protocol attribute in chat message)");
-                               return false;
-                       }
-               }
-
-               // 5a.  The protocol version must be supported.
-               if (atoi(tmp) > HIGHEST_SUPPORTED) {
-                       g_warning("Check 5a failed (received a message with protocol version %s, but version %s is not supported)", tmp, tmp);
-                       return false;
-               }
-
-       // ...otherwise, if this is a groupchat message, we may not have a protocol version 
-       // (since it may be communication from the Jabber server).  In this case, we have a
-       // different set of sanity checks.
-       } else if (msubtype == LM_MESSAGE_SUB_TYPE_GROUPCHAT) {
-               // 4b.
-               // In a chatroom situation, we need to ensure that we don't process messages that
-               // originated from us.
-               int cutoff = sender.find_last_of('/') + 1;
-               if (sender.substr(cutoff, sender.length()) == this->_sm->session_data->chat_handle) {
-                       return false;
-               }
-               // TODO: 6b.  If the message is NOT from the Jabber server, then check the protocol version.
-       }
-
-       // If all tests pass, then the message is at least valid.  
-       // Correct context has not yet been established, however; that is the job of the default handler
-       // and hasValidReceiveContext.
-
-       return true;
-}
-
-MessageType
-MessageHandler::_getType(LmMessage* message)
-{
-       LmMessageNode* root;
-       LmMessageNode* typenode;
-
-       root = lm_message_get_node(message);
-       if (root != NULL) {
-               typenode = lm_message_node_get_child(root, MESSAGE_TYPE);
-               if (typenode != NULL) {
-                       return static_cast< MessageType >(atoi(lm_message_node_get_value(typenode)));
-               }
-       }
-       return UNKNOWN;
-}
-
-JabberMessage
-MessageHandler::_extractData(LmMessage* message)
-{
-
-       JabberMessage jm(message);
-       LmMessageNode* root;
-       LmMessageNode* sequence;
-       LmMessageNode* body;
-       gchar const* tmp;
-
-       root = lm_message_get_node(message);
-
-       if (root != NULL) {
-               sequence = lm_message_node_get_child(root, MESSAGE_SEQNUM);
-               body = lm_message_node_get_child(root, MESSAGE_BODY);
-
-               jm.sender = lm_message_node_get_attribute(root, MESSAGE_FROM);
-
-               if (sequence) {
-                       tmp = lm_message_node_get_value(sequence);
-                       if (tmp != NULL) {
-                               jm.sequence = atoi(tmp);
-                       }
-               }
-
-               if (body) {
-                       tmp = lm_message_node_get_value(body);
-                       if (tmp != NULL) {
-                               jm.body = tmp;
-                       }
-               }
-
-       } else {
-               jm.sequence = 0;
-               jm.sender = "";
-               jm.body = "";
-       }
-
-       return jm;
-}
-       
-LmHandlerResult
-MessageHandler::_default(LmMessage* message)
-{
-       std::bitset< NUM_FLAGS >& status = this->_sm->session_data->status;
-
-       // Pass groupchat messages with no Inkboard type off to the chat message handler
-       if (this->_getType(message) == UNKNOWN) {
-               if (lm_message_get_sub_type(message) == LM_MESSAGE_SUB_TYPE_GROUPCHAT) {
-                       if (status[IN_CHATROOM] || status[CONNECTING_TO_CHAT]) {
-                               return this->_sm->chat_handler()->parse(message);
-                       }
-               } else {
-                       return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-               }
-       }
-       
-       if (this->_hasValidReceiveContext(message)) {
-               // Extract message data
-               JabberMessage msg = this->_extractData(message);
-               MessageType type = this->_getType(message);
-
-               // Call message handler and return instruction value to Loudmouth
-
-               return (*this->_received_message_processors[type])(type, msg);
-       } else {
-               g_warning("Default message handler received message in invalid receive context; discarding message.");
-               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-       }
-}
-
-LmHandlerResult
-MessageHandler::_presence(LmMessage* message)
-{
-       LmMessageNode* root;
-       LmMessageSubType msubtype;
-       gchar const* tmp;
-       std::string sender;
-
-       SessionData* sd = this->_sm->session_data;
-       std::bitset< NUM_FLAGS >& status = this->_sm->session_data->status;
-
-       root = lm_message_get_node(message);
-       if (root == NULL) {
-               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-       }
-
-       tmp = lm_message_node_get_attribute(root, MESSAGE_FROM);
-       if (tmp == NULL) {
-               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-       } else {
-               sender = tmp;
-       }
-
-       msubtype = lm_message_get_sub_type(message);
-       if (status[CONNECTING_TO_CHAT] || status[IN_CHATROOM]) {
-               this->_sm->chat_handler()->parse(message);
-       } else {
-               switch(msubtype) {
-                       case LM_MESSAGE_SUB_TYPE_UNAVAILABLE:
-                               // remove buddy from online roster
-                               sd->buddyList.erase(sender);
-
-                               // if this buddy is in a 1-1 session with us, we need to exit
-                               // the whiteboard
-                               if (status[IN_WHITEBOARD] && !(status[IN_CHATROOM]) && strcasecmp(sender.c_str(), sd->recipient) == 0) {
-                                       status.set(IN_WHITEBOARD, 0);
-                                       this->_sm->userDisconnectedFromWhiteboard(sender);
-                                       this->_sm->closeSession();
-                               }
-                               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-                               
-                       case LM_MESSAGE_SUB_TYPE_AVAILABLE:
-                               // we don't want to insert an entry into a buddy list
-                               // if it's our own presence
-                               if (sender != this->_sm->session_data->jid.c_str()) {
-                                       sd->buddyList.insert(sender);
-                               }
-                               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-                       default:
-                               break;
-               }
-       }
-       return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-LmHandlerResult
-MessageHandler::_error(LmMessage* message)
-{
-       LmMessageNode* root;
-       LmMessageSubType msubtype;
-
-       root = lm_message_get_node(message);
-       if (root != NULL) {
-               msubtype = lm_message_get_sub_type(message);
-               if (msubtype == LM_MESSAGE_SUB_TYPE_ERROR) {
-                       gchar* error = g_strdup(lm_message_node_get_value(root));
-                       g_warning(error);
-
-                       // TODO: more robust error handling code
-                       this->_sm->disconnectFromDocument();
-                       this->_sm->disconnectFromServer();
-                       this->_sm->connectionError(error);
-               }
-       }
-
-       return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-void
-MessageHandler::_initializeContexts()
-{
-       initialize_received_message_contexts(_received_message_contexts);       
-       message_contexts_initialized = true;
-}
-
-void
-MessageHandler::_initializeProcessors()
-{
-       initialize_received_message_processors(this->_sm, this->_received_message_processors);  
-}
-
-void
-MessageHandler::_destructProcessors()
-{
-       destroy_received_message_processors(this->_received_message_processors);
-}
-
-
-char const*
-MessageHandler::ink_type_to_string(gint ink_type) {
-       switch(ink_type) {
-               case Inkscape::Whiteboard::CHANGE_NOT_REPEATABLE:
-                       return "CHANGE_NOT_REPEATABLE";
-               case Inkscape::Whiteboard::CHANGE_REPEATABLE:
-                       return "CHANGE_REPEATABLE";
-               case Inkscape::Whiteboard::DUMMY_CHANGE:
-                       return "DUMMY_CHANGE";
-               case Inkscape::Whiteboard::CHANGE_COMMIT:
-                       return "CHANGE_COMMIT";
-               case Inkscape::Whiteboard::CONNECT_REQUEST_USER:
-                       return "CONNECT_REQUEST_USER";
-               case Inkscape::Whiteboard::CONNECT_REQUEST_RESPONSE_USER:
-                       return "CONNECT_REQUEST_RESPONSE_USER";
-               case Inkscape::Whiteboard::CONNECT_REQUEST_RESPONSE_CHAT:
-                       return "CONNECT_REQUEST_RESPONSE_CHAT";
-               case Inkscape::Whiteboard::DOCUMENT_SENDER_REQUEST:
-                       return "DOCUMENT_SENDER_REQUEST";
-               case Inkscape::Whiteboard::DOCUMENT_SENDER_REQUEST_RESPONSE:
-                       return "DOCUMENT_SENDER_REQUEST_RESPONSE";
-               case Inkscape::Whiteboard::DOCUMENT_REQUEST:
-                       return "DOCUMENT_REQUEST";
-               case Inkscape::Whiteboard::DOCUMENT_BEGIN:
-                       return "DOCUMENT_BEGIN";
-               case Inkscape::Whiteboard::DOCUMENT_END:
-                       return "DOCUMENT_END";
-               case Inkscape::Whiteboard::CONNECTED_SIGNAL:
-                       return "CONNECTED_SIGNAL";
-               case Inkscape::Whiteboard::DISCONNECTED_FROM_USER_SIGNAL:
-                       return "DISCONNECTED_FROM_USER_SIGNAL";
-               case Inkscape::Whiteboard::CONNECT_REQUEST_REFUSED_BY_PEER:
-                       return "CONNECT_REQUEST_REFUSED_BY_PEER";
-               case Inkscape::Whiteboard::UNSUPPORTED_PROTOCOL_VERSION:
-                       return "UNSUPPORTED_PROTOCOL_VERSION";
-               case Inkscape::Whiteboard::CHATROOM_SYNCHRONIZE_REQUEST:
-                       return "CHATROOM_SYNCHRONIZE_REQUEST";
-               case Inkscape::Whiteboard::CHATROOM_SYNCHRONIZE_RESPONSE:
-                       return "CHATROOM_SYNCHRONIZE_RESPONSE";
-               case Inkscape::Whiteboard::ALREADY_IN_SESSION:
-                       return "ALREADY_IN_SESSION";
-               default:
-                       return "UNKNOWN";
-       }
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/message-handler.h b/src/jabber_whiteboard/message-handler.h
deleted file mode 100644 (file)
index 700665f..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * Whiteboard session manager
- * Jabber message handling
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- * Steven Montgomery, Jonas Collaros (original C version)
- *
- * Copyright (c) 2004-2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_MESSAGE_HANDLER_H__
-#define __WHITEBOARD_MESSAGE_HANDLER_H__
-
-extern "C" {
-#include <loudmouth/loudmouth.h>
-}
-
-#include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/typedefs.h"
-#include "jabber_whiteboard/message-contexts.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-struct JabberMessage;
-class SessionManager;
-
-/**
- * Handles received Jabber messages.
- */
-class MessageHandler {
-public:
-       MessageHandler(SessionManager* sm);
-       ~MessageHandler();
-       LmHandlerResult handle(LmMessage* message, HandlerMode mode);   
-       
-       bool _hasValidReceiveContext(LmMessage* message);
-
-       static char const* ink_type_to_string(gint ink_type);
-
-private:
-       static void _initializeContexts();
-
-       void _initializeProcessors();
-       void _destructProcessors();
-
-       // Utilities
-       bool _isValidMessage(LmMessage* message);
-       MessageType _getType(LmMessage* message);
-       struct JabberMessage _extractData(LmMessage* message);
-
-
-       // Individual message handlers
-       LmHandlerResult _default(LmMessage* message);
-       LmHandlerResult _error(LmMessage* message);
-       LmHandlerResult _presence(LmMessage* message);
-       
-       // Message processors map
-//     MessageContextMap _received_message_contexts;
-       MessageProcessorMap _received_message_processors;
-
-       SessionManager* _sm;
-
-       // noncopyable, nonassignable
-       MessageHandler(MessageHandler const&);
-       MessageHandler& operator=(MessageHandler const&);
-};
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 5e1b6a67411e8a66396ca11f9be6b37a5585c1c9..a9ed84e6fa726faac693001791ceee7719152234 100644 (file)
@@ -126,9 +126,9 @@ private:
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/jabber_whiteboard/message-processors.cpp b/src/jabber_whiteboard/message-processors.cpp
deleted file mode 100644 (file)
index f44224c..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-/**
- * Whiteboard session manager
- * Jabber received message processors
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-extern "C" {
-#include <loudmouth/loudmouth.h>
-}
-
-#include <glibmm/i18n.h>
-
-#include "xml/session.h"
-#include "xml/document.h"
-
-#include "desktop-handles.h"
-#include "document.h"
-#include "message-stack.h"
-
-#include "jabber_whiteboard/undo-stack-observer.h"
-#include "jabber_whiteboard/session-manager.h"
-#include "jabber_whiteboard/message-node.h"
-#include "jabber_whiteboard/message-queue.h"
-#include "jabber_whiteboard/message-processors.h"
-#include "jabber_whiteboard/typedefs.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-// Message processors are here!
-
-// TODO: Remove unnecessary status checks from processors --
-// we do all of that in MessageHandler::_hasValidReceiveContext
-
-// *********************************************************************
-// ChangeHandler begin
-// *********************************************************************
-
-/**
- * MessageProcessor for document change and event commit messages.
- */
-struct ChangeHandler : public MessageProcessor {
-public:
-       ~ChangeHandler()
-       {
-
-       }
-
-       ChangeHandler(SessionManager* sm) : MessageProcessor(sm)
-       {
-
-       }
-
-       LmHandlerResult
-       operator()(MessageType mode, JabberMessage& p)
-       {
-               MessageNode* msgNode;
-               bool chatroom = this->_sm->session_data->status[IN_CHATROOM];
-
-               ReceiveMessageQueue* rmq = this->_sm->session_data->receive_queues[p.sender];
-
-               if (rmq != NULL) {
-                       switch (mode) {
-                               case CHANGE_REPEATABLE:
-                               case CHANGE_NOT_REPEATABLE:
-                               case DOCUMENT_BEGIN:
-                                       msgNode = new MessageNode(p.sequence, p.sender, "", p.body, mode, false, chatroom);
-                                       rmq->insert(msgNode);
-                                       Inkscape::GC::release(msgNode);
-                                       break;
-                               case DOCUMENT_END:
-                                       this->_sm->session_data->recipients_committed_queue.push_back(p.sender);
-                                       msgNode = new MessageNode(p.sequence, p.sender, "", p.body, mode, false, chatroom);
-                                       rmq->insert(msgNode);
-                                       Inkscape::GC::release(msgNode);
-                                       break;
-                               case CHANGE_COMMIT:
-                                       this->_sm->session_data->recipients_committed_queue.push_back(p.sender);
-                                       msgNode = new MessageNode(p.sequence, p.sender, "", p.body, CHANGE_COMMIT, false, chatroom);
-                                       rmq->insert(msgNode);
-                                       Inkscape::GC::release(msgNode);
-                                       break;
-                               case DUMMY_CHANGE:
-                               default:
-                                       break;
-                       }
-               } else {
-                       g_warning("Received message from unknown sender %s", p.sender.c_str());
-               }
-               
-               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-       }
-};
-// *********************************************************************
-// ChangeHandler end
-// *********************************************************************
-
-
-// *********************************************************************
-// ConnectRequestHandler begin
-// *********************************************************************
-/**
- * MessageProcessor for connection request messages.
- */
-struct ConnectRequestHandler : public MessageProcessor {
-public:
-       ~ConnectRequestHandler()
-       {
-
-       }
-
-       ConnectRequestHandler(SessionManager* sm) : MessageProcessor(sm) 
-       {
-
-       }
-
-       LmHandlerResult 
-       operator()(MessageType mode, JabberMessage& m)
-       {
-               std::bitset< NUM_FLAGS >& status = this->_sm->session_data->status;
-               switch(mode) {
-                       case CONNECT_REQUEST_USER:
-                               this->_sm->receiveConnectRequest(m.sender.c_str());
-                               break;
-                       case CONNECT_REQUEST_RESPONSE_USER:
-                               if (m.sequence == 0) {
-                                       this->_sm->receiveConnectRequestResponse(DECLINE_INVITATION, m.sender);
-                               } else { // FIXME: this has got to be buggy...
-                                       this->_sm->setRecipient(m.sender.c_str());
-                                       this->_sm->receiveConnectRequestResponse(ACCEPT_INVITATION, m.sender);
-                               }
-                               break;
-                       case Inkscape::Whiteboard::CONNECTED_SIGNAL:
-                               if (!status[IN_CHATROOM] && !status[CONNECTING_TO_CHAT] && !status[SYNCHRONIZING_WITH_CHAT] && !status[WAITING_TO_SYNC_TO_CHAT]) {
-                                       this->_sm->userConnectedToWhiteboard(m.sender.c_str());
-                                       this->_sm->setRecipient(m.sender.c_str());
-                               } else {
-                                       sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::INFORMATION_MESSAGE, _("<b>%s</b> has joined the chatroom."), m.sender.c_str());
-                               }
-                               break;
-                       default:
-                               break;
-               }
-               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-       }
-};
-// *********************************************************************
-// ConnectRequestHandler end
-// *********************************************************************
-
-
-
-
-// *********************************************************************
-// ConnectErrorHandler begin
-// *********************************************************************
-/**
- * MessageProcessor for connection error messages.  
- */
-struct ConnectErrorHandler : public MessageProcessor {
-public:
-       ~ConnectErrorHandler()
-       {
-
-       }
-
-       ConnectErrorHandler(SessionManager* sm) : MessageProcessor(sm) 
-       {
-
-       }
-
-       LmHandlerResult 
-       operator()(MessageType mode, JabberMessage& m)
-       {
-               switch(mode) {
-                       case CONNECT_REQUEST_REFUSED_BY_PEER:
-                               if (this->_sm->session_data->status[WAITING_FOR_INVITE_RESPONSE]) {
-                                       this->_sm->receiveConnectRequestResponse(DECLINE_INVITATION, m.sender);
-                               }
-                               break;
-                       case Inkscape::Whiteboard::ALREADY_IN_SESSION:
-                               if (this->_sm->session_data->status[WAITING_FOR_INVITE_RESPONSE]) {
-                                       this->_sm->receiveConnectRequestResponse(PEER_ALREADY_IN_SESSION, m.sender);
-                               }
-                               break;
-                       case Inkscape::Whiteboard::DISCONNECTED_FROM_USER_SIGNAL:
-                               if (!this->_sm->session_data->status[IN_CHATROOM]) {
-                                       this->_sm->closeSession();
-                                       this->_sm->userDisconnectedFromWhiteboard(m.sender.c_str());
-                               }
-                               break;
-                       default:
-                               break;
-               }
-               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-       }
-};
-// *********************************************************************
-// ConnectErrorHandler end
-// *********************************************************************
-
-
-
-
-// *********************************************************************
-// ChatSynchronizeHandler begin
-// *********************************************************************
-/**
- * MessageProcessor for messages specific to chatroom synchronization.
- */
-struct ChatSynchronizeHandler : public MessageProcessor {
-public:
-       ~ChatSynchronizeHandler()
-       {
-
-       }
-
-       ChatSynchronizeHandler(SessionManager* sm) : MessageProcessor(sm) 
-       {
-
-       }
-
-       LmHandlerResult 
-       operator()(MessageType mode, JabberMessage& m)
-       {
-               switch(mode) {
-                       case CONNECT_REQUEST_RESPONSE_CHAT:
-                               this->_sm->receiveConnectRequestResponseChat(m.sender.c_str());
-                               break;
-                       case CHATROOM_SYNCHRONIZE_REQUEST:
-                               if (this->_sm->session_data->status[IN_CHATROOM] && this->_sm->session_data->status[IN_WHITEBOARD]) {
-                                       // Send response.  Everyone in the chatroom will do this,
-                                       // but the client will accept only one response.
-                                       // The response is sent privately to the client
-                                       // <http://www.jabber.org/jeps/jep-0045.html#privatemessage>
-                                       this->_sm->sendMessage(CHATROOM_SYNCHRONIZE_RESPONSE, this->_sm->session_data->sequence_number, "", m.sender.c_str(), false);
-                               }
-                               break;
-                       case CHATROOM_SYNCHRONIZE_RESPONSE:
-                               if (m.sequence != 0) {
-                                       // Set sequence number
-                                       this->_sm->session_data->sequence_number = m.sequence;
-
-                                       // Set status flags
-                                       this->_sm->session_data->status.set(WAITING_TO_SYNC_TO_CHAT, 0);
-                                       this->_sm->session_data->status.set(SYNCHRONIZING_WITH_CHAT, 1);
-
-                                       // Send document synchronization request
-                                       this->_sm->clearDocument();
-                                       this->_sm->setupInkscapeInterface();
-                                       this->_sm->sendMessage(CONNECT_REQUEST_RESPONSE_CHAT, m.sequence, "", m.sender.c_str(), false);
-                               } else {
-                                       this->_sm->sendMessage(CHATROOM_SYNCHRONIZE_REQUEST, 0, "", this->_sm->session_data->recipient, true);
-                               }
-                               break;
-                       default:
-                               break;
-               }
-               return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-       }
-};
-// *********************************************************************
-// ChatSynchronizeHandler end
-// *********************************************************************
-
-
-
-
-// *********************************************************************
-// Initializer
-// *********************************************************************
-void
-initialize_received_message_processors(SessionManager* sm, MessageProcessorMap& mpm)
-{
-       MessageProcessor* ch = new ChangeHandler(sm);
-       MessageProcessor* crh = new ConnectRequestHandler(sm);
-       MessageProcessor* ceh = new ConnectErrorHandler(sm);
-       MessageProcessor* csh = new ChatSynchronizeHandler(sm);
-
-       mpm[CHANGE_REPEATABLE] = ch;
-       mpm[CHANGE_NOT_REPEATABLE] = ch;
-       mpm[DUMMY_CHANGE] = ch;
-       mpm[CHANGE_COMMIT] = ch;
-       mpm[DOCUMENT_BEGIN] = ch;
-       mpm[DOCUMENT_END] = ch;
-
-       mpm[CONNECT_REQUEST_USER] = crh;
-       mpm[CONNECT_REQUEST_RESPONSE_USER] = crh;
-       mpm[CONNECTED_SIGNAL] = crh;
-
-       mpm[CONNECT_REQUEST_REFUSED_BY_PEER] = ceh;
-       mpm[ALREADY_IN_SESSION] = ceh;
-       mpm[DISCONNECTED_FROM_USER_SIGNAL] = ceh;
-
-       mpm[CONNECT_REQUEST_RESPONSE_CHAT] = csh;
-       mpm[CHATROOM_SYNCHRONIZE_REQUEST] = csh;
-       mpm[CHATROOM_SYNCHRONIZE_RESPONSE] = csh;
-}
-
-/*
- * This function is provided solely for convenience and style.  You can, of course,
- * delete every MessageProcessor in the map with your own loop.
- */
-void
-destroy_received_message_processors(MessageProcessorMap& mpm)
-{
-       mpm.clear();
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/message-processors.h b/src/jabber_whiteboard/message-processors.h
deleted file mode 100644 (file)
index 8b08874..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * Whiteboard session manager
- * Jabber received message processors
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_MESSAGE_PROCESSORS_H__
-#define __WHITEBOARD_MESSAGE_PROCESSORS_H__
-
-#include "jabber_whiteboard/typedefs.h"
-
-#include "gc-managed.h"
-#include "gc-finalized.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-class SessionManager;
-
-// Processor forward declarations
-struct ChangeHandler;
-struct DocumentSignalHandler;
-struct ConnectRequestHandler;
-struct ConnectErrorHandler;
-struct ChatSynchronizeHandler;
-
-/**
- * Encapsulates a pointer to an LmMessage along with additional information,
- * such as the message's sequence number, its sender, and its body.
- *
- * All of the above data members can be extracted directly from the LmMessage;
- * they are provided for convenience.
- */
-struct JabberMessage {
-public:
-       /**
-        * Constructor.
-        *
-        * The constructor attaches a reference to the LmMessage to prevent Loudmouth from
-        * freeing the message.
-        */
-       JabberMessage(LmMessage* m) : message(m), sequence(0)
-       {       
-               lm_message_ref(this->message);
-       }
-
-       /**
-        * Destructor.
-        *
-        * The destructor deletes a reference to the LmMessage, which, assuming all other
-        * references have been deleted, will allow Loudmouth to free the LmMessage object.
-        */
-       ~JabberMessage() 
-       {
-               lm_message_unref(this->message);
-       }
-
-
-        // TODO: Hide, or, better, remove this.  There's no real reason why it should be here,
-        // and it allows for the possibility of reference count-induced memory leaks.
-       /**
-        * Pointer to original Loudmouth message object.
-        */
-       LmMessage* message;
-       
-       /**
-        * Sequence number of this message.
-        */
-       unsigned int sequence;
-       
-       /**
-        * The JID of this message's sender.
-        */
-       std::string sender;
-
-       /**
-        * The body of this message.
-        */
-       Glib::ustring body;
-
-private:
-       // noncopyable, nonassignable (for now, anyway...)
-//     JabberMessage(JabberMessage const&);
-//     JabberMessage& operator=(JabberMessage const&);
-};
-
-/**
- * A MessageProcessor is a functor that is associated with one or more Inkboard message types.
- * When an Inkboard client receives an Inkboard message, it passes it to the appropriate
- * MessageProcessor.
- */
-struct MessageProcessor : public GC::Managed<>, public GC::Finalized {
-public:
-       virtual ~MessageProcessor() 
-       {
-
-       }
-
-       /**
-        * Functor action operator.
-        *
-        * \param mode The type of the message being processed.
-        * \param m A reference to the JabberMessage encapsulating the received Jabber message.
-        */
-       virtual LmHandlerResult operator()(MessageType mode, JabberMessage& m) = 0;
-
-       /**
-        * Constructor.
-        *
-        * \param sm The SessionManager with which a MessageProcessor instance is associated.
-        */
-       MessageProcessor(SessionManager* sm) : _sm(sm) { }
-protected:
-       /**
-        * Pointer to the associated SessionManager object.
-        */
-       SessionManager *_sm;
-
-private:
-       // noncopyable, nonassignable
-       MessageProcessor(MessageProcessor const&);
-       MessageProcessor& operator=(MessageProcessor const&);
-};
-
-/*
-struct ProcessorShell : public GC::Managed<>, public std::binary_function< MessageType, JabberMessage, LmHandlerResult > {
-public:
-       ProcessorShell(MessageProcessor* mpm) : _mpm(mpm) { }
-
-       LmHandlerResult operator()(MessageType type, JabberMessage msg)
-       {
-               return (*this->_mpm)(type, msg);
-       }
-private:
-       MessageProcessor* _mpm;
-};
-*/
-
-/**
- * Initialize the message -> MessageProcessor map.
- *
- * \param sm The SessionManager with which all created MessageProcessors should be associated with.
- * \param mpm Reference to the MessageProcessorMap to initialize.
- */
-void initialize_received_message_processors(SessionManager* sm, MessageProcessorMap& mpm);
-
-/**
- * Clean up the message -> MessageProcessor map.
- *
- * \param mpm Reference to the MessageProcessorMap to clean up.
- */
-void destroy_received_message_processors(MessageProcessorMap& mpm);
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 4bd1e9ab1304b5d58825688490f9b3049e71fc4e..b2c5d28d464fe28b24b3abf5f5f3b5b47dccb7eb 100644 (file)
@@ -22,117 +22,117 @@ namespace Inkscape {
 
 namespace Whiteboard {
 
-MessageQueue::MessageQueue(SessionManager* sm) : _sm(sm)
-{
-
-}
-
-MessageQueue::~MessageQueue()
-{
-
-}
+//###################################
+//# MESSAGE QUEUE
+//###################################
 
 MessageNode*
 MessageQueue::first()
 {
-       return this->_queue.front();
+    return _queue.front();
 }
 
 void
 MessageQueue::popFront()
 {
-       this->_queue.pop_front();
-//     g_log(NULL, G_LOG_LEVEL_DEBUG, "Removed element, queue size (for %s): %u", this->_sm->session_data->jid, this->_queue.size());
+     _queue.pop_front();
+    //g_log(NULL, G_LOG_LEVEL_DEBUG,
+    // "Removed element, queue size (for %s): %u", 
+    //lm_connection_get_jid(this->_sm->session_data->connection), this->_queue.size());
 }
 
 unsigned int
 MessageQueue::size()
 {
-       return this->_queue.size();
+    return _queue.size();
 }
 
 bool
 MessageQueue::empty()
 {
-       return this->_queue.empty();
+    return _queue.empty();
 }
 
 void
 MessageQueue::clear()
 {
-       this->_queue.clear();
+    _queue.clear();
 }
 
-ReceiveMessageQueue::ReceiveMessageQueue(SessionManager* sm) : MessageQueue(sm), _latest(0)
-{
 
-}
 
+//###################################
+//# RECEIVE MESSAGE QUEUE
+//###################################
 void
 ReceiveMessageQueue::insert(MessageNode* msg)
 {
-       // Check to see if the incoming message has a sequence number
-       // lower than the sequence number of the latest message processed
-       // by this message's sender.  If it does, drop the message and produce
-       // a warning.
-       if (msg->sequence() < this->_latest) {
-               g_warning("Received late message (message sequence number is %u, but latest processed message had sequence number %u).  Discarding message; session may be desynchronized.", msg->sequence(), this->_latest);
-               return;
-       }
-
-       // Otherwise, it is safe to insert this message.
-//     Inkscape::GC::anchor(msg);
-       this->_queue.push_back(msg);
-       sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::NORMAL_MESSAGE,
-                                                     ngettext("%u change in receive queue.",
-                                                              "%u changes in receive queue.",
-                                                              this->_queue.size()),
-                                                     this->_queue.size());
-//     g_log(NULL, G_LOG_LEVEL_DEBUG, "Receive queue size (for %s): %u", this->_sm->session_data->jid, this->_queue.size());
+    // Check to see if the incoming message has a sequence number
+    // lower than the sequence number of the latest message processed
+    // by this message's sender.  If it does, drop the message and produce
+    // a warning.
+    if (msg->sequence() < _latest) {
+        g_warning(_("Received late message (message sequence number is %u, but latest processed message had sequence number %u).  Discarding message; session may be desynchronized."), msg->sequence(), this->_latest);
+        return;
+    }
+
+    // Otherwise, it is safe to insert this message.
+    //Inkscape::GC::anchor(msg);
+    _queue.push_back(msg);
+       /*
+    SP_DT_MSGSTACK(_sm->getDesktop())->flashF(
+              Inkscape::NORMAL_MESSAGE, 
+              _("%u changes queued in receive queue."),
+              _queue.size());
+       */
+    //g_log(NULL, G_LOG_LEVEL_DEBUG, "Receive queue size (for %s): %u",
+    // lm_connection_get_jid(this->_sm->session_data->connection), this->_queue.size());
 }
 
 void
 ReceiveMessageQueue::insertDeferred(MessageNode* msg)
 {
-       this->_deferred.push_back(msg);
+    _deferred.push_back(msg);
 }
 
 void
 ReceiveMessageQueue::setLatestProcessedPacket(unsigned int seq)
 {
-       this->_latest = seq;
+     _latest = seq;
 }
 
-SendMessageQueue::SendMessageQueue(SessionManager* sm) : MessageQueue(sm)
-{
-
-}
 
+//###################################
+//# SEND MESSAGE QUEUE
+//###################################
 void
 SendMessageQueue::insert(MessageNode* msg)
 {
-//     Inkscape::GC::anchor(msg);
-       this->_queue.push_back(msg);
-       sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::NORMAL_MESSAGE,
-                                                     ngettext("%u change in send queue.",
-                                                              "%u changes in send queue.",
-                                                              this->_queue.size()),
-                                                     this->_queue.size());
-//     g_log(NULL, G_LOG_LEVEL_DEBUG, "Send queue size (for %s): %u",  this->_sm->session_data->jid, this->_queue.size());
+    //Inkscape::GC::anchor(msg);
+    _queue.push_back(msg);
+       /*
+    SP_DT_MSGSTACK(_sm->getDesktop())->flashF(
+            Inkscape::NORMAL_MESSAGE, 
+            _("%u changes queued in send queue."),
+            _queue.size());
+       */
+    //g_log(NULL, G_LOG_LEVEL_DEBUG, "Send queue size (for %s): %u",
+    //  lm_connection_get_jid(this->_sm->session_data->connection),
+    //this->_queue.size());
 }
 
-}
+}  // namespace Whiteboard
 
-}
+}  // namespace Inkscape
 
 
 /*
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index e607ed81be1d7d10cff5e3c4db3dd005723fd2be..700a53bae6427f29b7a5a1956d47ee799211b730 100644 (file)
@@ -16,7 +16,6 @@
 #include <map>
 
 #include "gc-alloc.h"
-
 #include "gc-managed.h"
 
 #include "util/list-container.h"
@@ -25,7 +24,6 @@ namespace Inkscape {
 
 namespace Whiteboard {
 
-class SessionManager;
 class MessageNode;
 
 /// Definition of the basic message node queue
@@ -50,37 +48,40 @@ public:
         *
         * \param sm The SessionManager to associate this MessageQueue with. 
         */
-       MessageQueue(SessionManager *sm);
-       virtual ~MessageQueue();
+       MessageQueue() { }
+       virtual ~MessageQueue()
+       {
+               this->_queue.clear();
+       }
 
        /**
         * Retrieve the MessageNode at the front of the queue.
         */
-       MessageNode* first();
+       virtual MessageNode* first();
 
        /**
         * Remove the element at the front of the queue. 
         */
-       void popFront();
+       virtual void popFront();
 
        /**
         * Get the size of the queue.
         *
         * \return The size of the queue.
         */
-       unsigned int size();
+       virtual unsigned int size();
 
        /**
         * Returns whether or not the queue is empty.
         *
         * \return Whether or not the queue is empty.
         */
-       bool empty();
+       virtual bool empty();
 
        /**
         * Clear the queue.
         */
-       void clear();
+       virtual void clear();
 
        /**
         * The insertion method.  The insertion procedure must be defined
@@ -95,11 +96,6 @@ protected:
         * Implementation of the queue.
         */
        MessageQueueBuffer _queue;
-
-       /**
-        * Pointer to SessionManager.
-        */
-       SessionManager* _sm;
 };
 
 
@@ -111,7 +107,7 @@ protected:
  */
 class ReceiveMessageQueue : public MessageQueue, public GC::Managed<> {
 public:
-       ReceiveMessageQueue(SessionManager* sm);
+       ReceiveMessageQueue() : _latest(0) { }
 
        /**
         * Insert a message into the queue.  
@@ -149,7 +145,7 @@ private:
  */
 class SendMessageQueue : public MessageQueue {
 public:
-       SendMessageQueue(SessionManager* sm);
+       SendMessageQueue() { }
 
        /**
         * Insert a message into the queue.  
@@ -169,9 +165,9 @@ public:
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index a46c27356bec667d5d403045faed7ba510c60fdb..c82cd0c62fc6bd9bff0a8cd3d8b53440f2ca6e9c 100644 (file)
@@ -59,9 +59,9 @@ const char* MESSAGE_PROTOCOL_VER =    "inkboard-protocol";
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index 5cbb8a0797a2c753cf46ed094d48b6d7e91b70f5..de14778b17e4acdf26cfe6e2ae1a4b33fb1966d3 100644 (file)
@@ -131,9 +131,9 @@ extern char const* MESSAGE_PROTOCOL_VER;
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index c10521b61db945709839ae428b73bdc583007e8e..095c6bab3a1171d4aa044ec2609e2aad6ba01ba2 100644 (file)
@@ -39,10 +39,16 @@ namespace Whiteboard {
 //
 // only_collect_nodes defaults to false because most invocations of this method also use the message string.
 void
-MessageUtilities::newObjectMessage(Glib::ustring* msgbuf, KeyToNodeMap& newidsbuf, NodeToKeyMap& newnodesbuf, NewChildObjectMessageList& childmsgbuf, XMLNodeTracker* xmt, Inkscape::XML::Node const* node, bool only_collect_nodes, bool collect_children)
+MessageUtilities::newObjectMessage(Glib::ustring &msgbuf, 
+                       KeyNodeTable& newnodesbuf,
+                       NewChildObjectMessageList& childmsgbuf, 
+                       XMLNodeTracker* xmt, 
+                       Inkscape::XML::Node const* node,
+                       bool only_collect_nodes,
+                       bool collect_children)
 {
        // Initialize pointers
-       std::string id, refid, parentid;
+       Glib::ustring id, refid, parentid;
 
        gchar const* name = NULL;
        XML::Node* parent = NULL;
@@ -50,16 +56,17 @@ MessageUtilities::newObjectMessage(Glib::ustring* msgbuf, KeyToNodeMap& newidsbu
 
        bool only_add_children = false;
 
+        //g_log(NULL, G_LOG_LEVEL_DEBUG, "newObjectMessage: processing node %p of type %s", node, NodeUtilities::nodeTypeToString(*node).data());
 
        if (node != NULL) {
                parent = sp_repr_parent(node);
                if (parent != NULL) {
+                        //g_log(NULL, G_LOG_LEVEL_DEBUG, "Attempting to find ID for parent node %p (on node %p)", parent, node);
                        parentid = NodeUtilities::findNodeID(*parent, xmt, newnodesbuf);
                        if (parentid.empty()) {
                                g_warning("Parent %p is not being tracked, creating new ID", parent);
                                parentid = xmt->generateKey();
-                               newidsbuf[parentid] = parent;
-                               newnodesbuf[parent] = parentid;
+                               newnodesbuf.put(parentid, parent);
                        }
 
                        if ( node != parent->firstChild() && parent != NULL ) {
@@ -71,12 +78,12 @@ MessageUtilities::newObjectMessage(Glib::ustring* msgbuf, KeyToNodeMap& newidsbu
                }
 
                if (ref != NULL) {
+                        //g_log(NULL, G_LOG_LEVEL_DEBUG, "Attempting to find ID for ref node %p (on %p)", ref, node);
                        refid = NodeUtilities::findNodeID(*ref, xmt, newnodesbuf);
                        if (refid.empty() && ref != NULL) {
                                g_warning("Ref %p is not being tracked, creating new ID", ref);
                                refid = xmt->generateKey();
-                               newidsbuf[refid] = ref;
-                               newnodesbuf[ref] = refid;
+                               newnodesbuf.put(refid, ref);
                        }
                }
 
@@ -88,18 +95,19 @@ MessageUtilities::newObjectMessage(Glib::ustring* msgbuf, KeyToNodeMap& newidsbu
        if (!xmt->isSpecialNode(node->name())) {
                if (!xmt->isTracking(*node)) {
                        id = xmt->generateKey();        
-                       newidsbuf[id] = node;
-                       newnodesbuf[node] = id;
+                        //g_log(NULL, G_LOG_LEVEL_DEBUG, "Inserting %p with id %s", node, id.c_str());
+                       newnodesbuf.put(id, node);
                } else {
                        id = xmt->get(*node);
+                //g_log(NULL, G_LOG_LEVEL_DEBUG, "Found id %s for node %p; not inserting into new nodes buffers.", id.c_str(), node);
                }
        } else {
+                //g_log(NULL, G_LOG_LEVEL_DEBUG, "Processing special node; not generating key");
                id = xmt->get(*node);
                if (id.empty()) {
-                       g_warning("Node %p (name %s) is a special node, but it could not be found in the node tracker (possible unexpected duplicate?)  Generating unique ID anyway.", node, node->name());
+                       g_warning(_("Node %p (name %s) is a special node, but it could not be found in the node tracker (possible unexpected duplicate?)  Generating unique ID anyway."), node, node->name());
                        id = xmt->generateKey();
-                       newidsbuf[id] = node;
-                       newnodesbuf[node] = id;
+                       newnodesbuf.put(id, node);
                }
                only_add_children = true;
        }
@@ -108,92 +116,85 @@ MessageUtilities::newObjectMessage(Glib::ustring* msgbuf, KeyToNodeMap& newidsbu
        // don't process the given node.
        if( !only_add_children && !id.empty() && msgbuf != NULL && !only_collect_nodes ) {
                // <MESSAGE_NEWOBJ>
-               (*msgbuf) = (*msgbuf) + "<" + MESSAGE_NEWOBJ + ">";
+               msgbuf = msgbuf + "<" + MESSAGE_NEWOBJ + ">";
 
                // <MESSAGE_PARENT>
-               (*msgbuf) = (*msgbuf) + "<" + MESSAGE_PARENT + ">";
+               msgbuf = msgbuf + "<" + MESSAGE_PARENT + ">";
 
                if(!parentid.empty()) {
-                       (*msgbuf) += parentid;
+                       msgbuf += parentid;
                }
 
                // </MESSAGE_NEWOBJ><MESSAGE_CHILD>id</MESSAGE_CHILD>
-               (*msgbuf) = (*msgbuf) + "</" + MESSAGE_PARENT + ">";
+               msgbuf = msgbuf + "</" + MESSAGE_PARENT + ">";
 
-               (*msgbuf) = (*msgbuf) + "<" + MESSAGE_CHILD + ">";
-               (*msgbuf) += id;
+               msgbuf = msgbuf + "<" + MESSAGE_CHILD + ">";
+               msgbuf += id;
 
-               (*msgbuf) = (*msgbuf) + "</" + MESSAGE_CHILD + ">";
+               msgbuf = msgbuf + "</" + MESSAGE_CHILD + ">";
 
                if(!refid.empty()) {
                        // <MESSAGE_REF>refid</MESSAGE_REF>
-                       (*msgbuf) = (*msgbuf) + "<" + MESSAGE_REF + ">";
+                       msgbuf = msgbuf + "<" + MESSAGE_REF + ">";
                        
-                       (*msgbuf) += refid;
+                       msgbuf += refid;
 
-                       (*msgbuf) = (*msgbuf) + "</" + MESSAGE_REF + ">";
+                       msgbuf = msgbuf + "</" + MESSAGE_REF + ">";
                }
 
                // <MESSAGE_NODETYPE>*node.type()</MESSAGE_NODETYPE>
-               (*msgbuf) = (*msgbuf) + "<" + MESSAGE_NODETYPE + ">" + NodeUtilities::nodeTypeToString(*node);
-               (*msgbuf) = (*msgbuf) + "</" + MESSAGE_NODETYPE + ">";
+               msgbuf = msgbuf + "<" + MESSAGE_NODETYPE + ">" + NodeUtilities::nodeTypeToString(*node);
+               msgbuf = msgbuf + "</" + MESSAGE_NODETYPE + ">";
 
                if (node->content() != NULL) {
                        // <MESSAGE_CONTENT>node->content()</MESSAGE_CONTENT>
-                       (*msgbuf) = (*msgbuf) + "<" + MESSAGE_CONTENT + ">" + node->content();
-                       (*msgbuf) = (*msgbuf) + "</" + MESSAGE_CONTENT + ">";
+                       msgbuf = msgbuf + "<" + MESSAGE_CONTENT + ">" + node->content();
+                       msgbuf = msgbuf + "</" + MESSAGE_CONTENT + ">";
                }
 
                // <MESSAGE_NAME>name</MESSAGE_NAME>
-               (*msgbuf) = (*msgbuf) + "<" + MESSAGE_NAME + ">";
+               msgbuf = msgbuf + "<" + MESSAGE_NAME + ">";
 
-               if( name != NULL ) {
-                       (*msgbuf) += name;
-               }
+               if( name != NULL )
+                       msgbuf += name;
 
-               (*msgbuf) = (*msgbuf) + "</" + MESSAGE_NAME + ">";
+               msgbuf = msgbuf + "</" + MESSAGE_NAME + ">";
 
                // </MESSAGE_NEWOBJ>
-               (*msgbuf) = (*msgbuf) + "</" + MESSAGE_NEWOBJ + ">";
+               msgbuf = msgbuf + "</" + MESSAGE_NEWOBJ + ">";
        } else if (id.empty()) {
                // if ID is NULL, then we have a real problem -- we were not able to find a key
                // nor generate one.  The only thing we can really do here is abort, since we have
                // no way to let the other client(s) uniquely identify this object.
-               /* FIXME: If this indicates a programming bug, then don't request translation with
-                * _(...): it is most useful in untranslated form so that developers may search for
-                * it when someone reports it in a bug report (as we want users to do for all bugs,
-                * as indicated by it being a g_warning string).
-                * 
-                * Otherwise, if it is not a programming bug but a network error or a bug in the
-                * remote peer (perhaps running different software) or whatever, then present it in
-                * an alert box, and avoid use of technical jargon `NULL'.
-                */
                g_warning(_("ID for new object is NULL even after generation and lookup attempts: the new object will NOT be sent, nor will any of its child objects!"));
                return;
        } else {
 
        }
 
+        //g_log(NULL, G_LOG_LEVEL_DEBUG, "Generated message");
 
        if (!only_collect_nodes && msgbuf != NULL && !id.empty()) {
                // Collect new object's attributes and append them onto the msgbuf
                Inkscape::Util::List<Inkscape::XML::AttributeRecord const> attrlist = node->attributeList();
 
                for(; attrlist; attrlist++) {
-                       MessageUtilities::objectChangeMessage(msgbuf, xmt, id, g_quark_to_string(attrlist->key), NULL, attrlist->value, false);
+                       MessageUtilities::objectChangeMessage(msgbuf,
+                         xmt, id, g_quark_to_string(attrlist->key),
+                          NULL, attrlist->value, false);
                }
        }
 
-       if (!only_collect_nodes) {
-               childmsgbuf.push_back(*msgbuf);
-       }
+       if (!only_collect_nodes)
+               childmsgbuf.push_back(msgbuf);
 
        if (!id.empty() && collect_children) {
                Glib::ustring childbuf;
                // Collect any child objects of this new object
                for ( Inkscape::XML::Node const *child = node->firstChild(); child != NULL; child = child->next() ) {
                        childbuf.clear();
-                       MessageUtilities::newObjectMessage(&childbuf, newidsbuf, newnodesbuf, childmsgbuf, xmt, child, only_collect_nodes);
+                       MessageUtilities::newObjectMessage(childbuf,
+                        newnodesbuf, childmsgbuf, xmt, child, only_collect_nodes);
                        if (!only_collect_nodes) {
                                // we're recursing down the tree, so we're picking up child nodes first
                                // and parents afterwards
@@ -205,232 +206,251 @@ MessageUtilities::newObjectMessage(Glib::ustring* msgbuf, KeyToNodeMap& newidsbu
 }
 
 void
-MessageUtilities::objectChangeMessage(ustring* msgbuf, XMLNodeTracker* xmt, std::string const id, gchar const* key, gchar const* oldval, gchar const* newval, bool is_interactive)
+MessageUtilities::objectChangeMessage(Glib::ustring &msgbuf, 
+                                    XMLNodeTracker* xmt, 
+                                    const Glib::ustring &id, 
+                                    gchar const* key, 
+                                    gchar const* oldval, 
+                                    gchar const* newval, 
+                                    bool is_interactive)
 {
-       // Construct message
-       
-       // <MESSAGE_CHANGE><MESSAGE_ID>id</MESSAGE_ID>
-       (*msgbuf) = (*msgbuf) + "<" + MESSAGE_CHANGE + ">";
-       (*msgbuf) = (*msgbuf) + "<" + MESSAGE_ID + ">";
-       (*msgbuf) += id;
-       (*msgbuf) = (*msgbuf) + "</" + MESSAGE_ID + ">";
-
-       // <MESSAGE_KEY>key</MESSAGE_KEY>
-       (*msgbuf) = (*msgbuf) + "<" + MESSAGE_KEY + ">";
-       if (key != NULL) {
-               (*msgbuf) += key;
-       }
-       (*msgbuf) = (*msgbuf) + "</" + MESSAGE_KEY + ">";
-
-       // <MESSAGE_OLDVAL>oldval</MESSAGE_OLDVAL>
-       (*msgbuf) = (*msgbuf) + "<" + MESSAGE_OLDVAL + ">";
-       if (oldval != NULL) {
-               (*msgbuf) += oldval;
-       }
-       (*msgbuf) = (*msgbuf) + "</" + MESSAGE_OLDVAL + ">";
-
-       // <MESSAGE_NEWVAL>newval</MESSAGE_NEWVAL>
-       (*msgbuf) = (*msgbuf) + "<" + MESSAGE_NEWVAL + ">";
-       if (newval != NULL) {
-               (*msgbuf) += newval;
-       }
-       (*msgbuf) = (*msgbuf) + "</" + MESSAGE_NEWVAL + ">";
-
-       // <MESSAGE_ISINTERACTIVE>is_interactive</MESSAGE_ISINTERACTIVE>
-       (*msgbuf) = (*msgbuf) + "<" + MESSAGE_ISINTERACTIVE + ">";
-       if (is_interactive) {
-               (*msgbuf) += "true";
-       } else {
-               (*msgbuf) += "false";
-       }
-       (*msgbuf) = (*msgbuf) + "</" + MESSAGE_ISINTERACTIVE + ">";
-
-       // </MESSAGE_CHANGE>
-       (*msgbuf) = (*msgbuf) + "</" + MESSAGE_CHANGE + ">";
+    // Construct message
+
+    // <MESSAGE_CHANGE><MESSAGE_ID>id</MESSAGE_ID>
+    msgbuf = msgbuf + "<" + MESSAGE_CHANGE + ">";
+    msgbuf = msgbuf + "<" + MESSAGE_ID + ">";
+    msgbuf += id;
+    msgbuf = msgbuf + "</" + MESSAGE_ID + ">";
+
+    // <MESSAGE_KEY>key</MESSAGE_KEY>
+    msgbuf = msgbuf + "<" + MESSAGE_KEY + ">";
+    if (key != NULL) {
+            msgbuf += key;
+    }
+    msgbuf = msgbuf + "</" + MESSAGE_KEY + ">";
+
+    // <MESSAGE_OLDVAL>oldval</MESSAGE_OLDVAL>
+    msgbuf = msgbuf + "<" + MESSAGE_OLDVAL + ">";
+    if (oldval != NULL) {
+            msgbuf += oldval;
+    }
+    msgbuf = msgbuf + "</" + MESSAGE_OLDVAL + ">";
+
+    // <MESSAGE_NEWVAL>newval</MESSAGE_NEWVAL>
+    msgbuf = msgbuf + "<" + MESSAGE_NEWVAL + ">";
+    if (newval != NULL) {
+            msgbuf += newval;
+    }
+    msgbuf = msgbuf + "</" + MESSAGE_NEWVAL + ">";
+
+    // <MESSAGE_ISINTERACTIVE>is_interactive</MESSAGE_ISINTERACTIVE>
+    msgbuf = msgbuf + "<" + MESSAGE_ISINTERACTIVE + ">";
+    if (is_interactive) {
+            msgbuf += "true";
+    } else {
+            msgbuf += "false";
+    }
+    msgbuf = msgbuf + "</" + MESSAGE_ISINTERACTIVE + ">";
+
+    // </MESSAGE_CHANGE>
+    msgbuf = msgbuf + "</" + MESSAGE_CHANGE + ">";
 }
 
 void
-MessageUtilities::objectDeleteMessage(Glib::ustring* msgbuf, XMLNodeTracker* xmt, Inkscape::XML::Node const& parent, Inkscape::XML::Node const& child, Inkscape::XML::Node const* prev)
+MessageUtilities::objectDeleteMessage(Glib::ustring &msgbuf, 
+                            XMLNodeTracker* xmt,
+                            Inkscape::XML::Node const& parent,
+                            Inkscape::XML::Node const& child,
+                            Inkscape::XML::Node const* prev)
 {
-       /*
-       gchar const* parentid = NULL;
-       gchar const* previd = NULL;
-       gchar const* childid = NULL;
-
-       childid = child.attribute("id");
-       parentid = parent.attribute("id");
-       if (prev != NULL) {
-               previd = prev->attribute("id");
-       }*/
-
-       std::string parentid, previd, childid;
-
-       childid = xmt->get(child);
-       parentid = xmt->get(parent);
-       previd = xmt->get(*prev);
-
-       if (!childid.empty()) {
-               // <MESSAGE_DELETE><MESSAGE_PARENT>parentid</MESSAGE_PARENT>
-               (*msgbuf) = (*msgbuf) + "<" + MESSAGE_DELETE + ">" + "<" + MESSAGE_PARENT + ">";
-               if (!parentid.empty()) {
-                       (*msgbuf) += parentid;
-               }
-               (*msgbuf) = (*msgbuf) + "</" + MESSAGE_PARENT + ">";
-
-               // <MESSAGE_CHILD>childid</MESSAGE_CHILD>
-               (*msgbuf) = (*msgbuf) + "<" + MESSAGE_CHILD + ">";
-               if (!childid.empty()) {
-                       (*msgbuf) += childid;
-               }
-               (*msgbuf) = (*msgbuf) + "</" + MESSAGE_CHILD + ">";
-
-               // <MESSAGE_REF>previd</MESSAGE_REF>
-               (*msgbuf) = (*msgbuf) + "<" + MESSAGE_REF + ">";
-               if (!previd.empty()) {
-                       (*msgbuf) += previd;
-               }
-               (*msgbuf) = (*msgbuf) + "</" + MESSAGE_REF + ">";
-
-               // </MESSAGE_DELETE>
-               (*msgbuf) = (*msgbuf) + "</" + MESSAGE_DELETE + ">";
-       }
+    /*
+    gchar const* parentid = NULL;
+    gchar const* previd = NULL;
+    gchar const* childid = NULL;
+
+    childid = child.attribute("id");
+    parentid = parent.attribute("id");
+    if (prev != NULL) {
+            previd = prev->attribute("id");
+    }*/
+
+    Glib::ustring parentid, previd, childid;
+
+    childid = xmt->get(child);
+    parentid = xmt->get(parent);
+    previd = xmt->get(*prev);
+
+    if (childid.empty())
+        return;
+            
+     // <MESSAGE_DELETE><MESSAGE_PARENT>parentid</MESSAGE_PARENT>
+     msgbuf = msgbuf + "<" + MESSAGE_DELETE + ">" + "<" + MESSAGE_PARENT + ">";
+     if (!parentid.empty()) {
+             msgbuf += parentid;
+     }
+     msgbuf = msgbuf + "</" + MESSAGE_PARENT + ">";
+
+     // <MESSAGE_CHILD>childid</MESSAGE_CHILD>
+     msgbuf = msgbuf + "<" + MESSAGE_CHILD + ">";
+     if (!childid.empty()) {
+             msgbuf += childid;
+     }
+     msgbuf = msgbuf + "</" + MESSAGE_CHILD + ">";
+
+     // <MESSAGE_REF>previd</MESSAGE_REF>
+     msgbuf = msgbuf + "<" + MESSAGE_REF + ">";
+     if (!previd.empty()) {
+             msgbuf += previd;
+     }
+     msgbuf = msgbuf + "</" + MESSAGE_REF + ">";
+
+     // </MESSAGE_DELETE>
+     msgbuf = msgbuf + "</" + MESSAGE_DELETE + ">";
 }
 
 void
-MessageUtilities::contentChangeMessage(Glib::ustring& msgbuf, std::string const nodeid, Util::ptr_shared<char> old_value, Util::ptr_shared<char> new_value)
+MessageUtilities::contentChangeMessage(Glib::ustring& msgbuf, 
+                       const Glib::ustring &nodeid, 
+                       Util::ptr_shared<char> old_value,
+                       Util::ptr_shared<char> new_value)
 {
-       if (!nodeid.empty()) {
-               // <MESSAGE_NODECONTENT>
-               msgbuf = msgbuf + "<" + MESSAGE_NODECONTENT + ">";
-
-               // <MESSAGE_ID>nodeid</MESSAGE_ID>
-               msgbuf = msgbuf + "<" + MESSAGE_ID + ">";
-               msgbuf += nodeid;
-               msgbuf = msgbuf + "</" + MESSAGE_ID + ">";
-
-               // <MESSAGE_OLDVAL>old_value</MESSAGE_OLDVAL>
-               msgbuf = msgbuf + "<" + MESSAGE_OLDVAL + ">";
-               msgbuf += old_value.pointer();
-               msgbuf = msgbuf + "</" + MESSAGE_OLDVAL + ">";
-
-               // <MESSAGE_NEWVAL>new_value</MESSAGE_NEWVAL>
-               msgbuf = msgbuf + "<" + MESSAGE_NEWVAL + ">";
-               msgbuf += new_value.pointer();
-               msgbuf = msgbuf + "</" + MESSAGE_NEWVAL + ">";
-
-               // </MESSAGE_NODECONTENT>
-               msgbuf = msgbuf + "</" + MESSAGE_NODECONTENT + ">";
-       }
+    if (nodeid.empty())
+        return;
+        
+     // <MESSAGE_NODECONTENT>
+     msgbuf = msgbuf + "<" + MESSAGE_NODECONTENT + ">";
+
+     // <MESSAGE_ID>nodeid</MESSAGE_ID>
+     msgbuf = msgbuf + "<" + MESSAGE_ID + ">";
+     msgbuf += nodeid;
+     msgbuf = msgbuf + "</" + MESSAGE_ID + ">";
+
+     // <MESSAGE_OLDVAL>old_value</MESSAGE_OLDVAL>
+     msgbuf = msgbuf + "<" + MESSAGE_OLDVAL + ">";
+     msgbuf += old_value.pointer();
+     msgbuf = msgbuf + "</" + MESSAGE_OLDVAL + ">";
+
+     // <MESSAGE_NEWVAL>new_value</MESSAGE_NEWVAL>
+     msgbuf = msgbuf + "<" + MESSAGE_NEWVAL + ">";
+     msgbuf += new_value.pointer();
+     msgbuf = msgbuf + "</" + MESSAGE_NEWVAL + ">";
+
+     // </MESSAGE_NODECONTENT>
+     msgbuf = msgbuf + "</" + MESSAGE_NODECONTENT + ">";
 }
 
 void
-MessageUtilities::childOrderChangeMessage(Glib::ustring& msgbuf, std::string const childid, std::string const oldprevid, std::string const newprevid)
+MessageUtilities::childOrderChangeMessage(Glib::ustring& msgbuf, 
+                          const Glib::ustring &childid, 
+                          const Glib::ustring &oldprevid, 
+                          const Glib::ustring &newprevid)
 {
-       if (!childid.empty()) {
-               // <MESSAGE_ORDERCHANGE>
-               msgbuf = msgbuf + "<" + MESSAGE_ORDERCHANGE + ">";
+    if (childid.empty())
+        return;
+        
+    // <MESSAGE_ORDERCHANGE>
+    msgbuf = msgbuf + "<" + MESSAGE_ORDERCHANGE + ">";
+
+    // <MESSAGE_ID>nodeid</MESSAGE_ID>
+    msgbuf = msgbuf + "<" + MESSAGE_CHILD + ">";
+    msgbuf += childid;
+    msgbuf = msgbuf + "</" + MESSAGE_CHILD + ">";
+
+    // <MESSAGE_OLDVAL>oldprevid</MESSAGE_OLDVAL>
+    /*
+    msgbuf = msgbuf + "<" + MESSAGE_OLDVAL + ">";
+    msgbuf += (*oldprevid);
+    msgbuf = msgbuf + "</" + MESSAGE_OLDVAL + ">";
+    */
+
+    // <MESSAGE_NEWVAL>newprevid</MESSAGE_NEWVAL>
+    msgbuf = msgbuf + "<" + MESSAGE_NEWVAL + ">";
+    msgbuf += newprevid;
+    msgbuf = msgbuf + "</" + MESSAGE_NEWVAL + ">";
+
+    // </MESSAGE_ORDERCHANGE>
+    msgbuf = msgbuf + "</" + MESSAGE_ORDERCHANGE + ">";
 
-               // <MESSAGE_ID>nodeid</MESSAGE_ID>
-               msgbuf = msgbuf + "<" + MESSAGE_CHILD + ">";
-               msgbuf += childid;
-               msgbuf = msgbuf + "</" + MESSAGE_CHILD + ">";
-
-               // <MESSAGE_OLDVAL>oldprevid</MESSAGE_OLDVAL>
-               /*
-               msgbuf = msgbuf + "<" + MESSAGE_OLDVAL + ">";
-               msgbuf += (*oldprevid);
-               msgbuf = msgbuf + "</" + MESSAGE_OLDVAL + ">";
-               */
-
-               // <MESSAGE_NEWVAL>newprevid</MESSAGE_NEWVAL>
-               msgbuf = msgbuf + "<" + MESSAGE_NEWVAL + ">";
-               msgbuf += newprevid;
-               msgbuf = msgbuf + "</" + MESSAGE_NEWVAL + ">";
-
-               // </MESSAGE_ORDERCHANGE>
-               msgbuf = msgbuf + "</" + MESSAGE_ORDERCHANGE + ">";
-       }
 }
 
 
 bool
-MessageUtilities::getFirstMessageTag(struct Node& buf, Glib::ustring const& msg)
+MessageUtilities::getFirstMessageTag(struct Node& buf, const Glib::ustring &msg)
 {
-       if (msg.empty()) {
-               return false;
-       }
-
-       // See if we have a valid start tag, i.e. < ... >.  If we do,
-       // continue; if not, stop and return NULL.
-       //
-       // find_first_of returns ULONG_MAX when it cannot find the first
-       // instance of the given character.
-
-       Glib::ustring::size_type startDelim = msg.find_first_of('<');
-       if (startDelim != ULONG_MAX) {
-               Glib::ustring::size_type endDelim = msg.find_first_of('>');
-               if (endDelim != ULONG_MAX) {
-                       if (endDelim > startDelim) {
-                               buf.tag = msg.substr(startDelim+1, (endDelim-startDelim)-1);
-                               if (buf.tag.find_first_of('/') == ULONG_MAX) { // start tags should not be end tags
-
-
-                                       // construct end tag (</buf.data>)
-                                       Glib::ustring endTag(buf.tag);
-                                       endTag.insert(0, "/");
-
-                                       Glib::ustring::size_type endTagLoc = msg.find(endTag, endDelim);
-                                       if (endTagLoc != ULONG_MAX) {
-                                               buf.data = msg.substr(endDelim+1, ((endTagLoc - 1) - (endDelim + 1)));
-                                               buf.next_pos = endTagLoc + endTag.length() + 1;
-
-                                               return true;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       return false;
+    if (msg.empty())
+        return false;
+
+    // See if we have a valid start tag, i.e. < ... >.  If we do,
+    // continue; if not, stop and return NULL.
+    //
+    // find_first_of returns ULONG_MAX when it cannot find the first
+    // instance of the given character.
+
+    Glib::ustring::size_type startDelim = msg.find_first_of('<');
+    if (startDelim != ULONG_MAX) {
+            Glib::ustring::size_type endDelim = msg.find_first_of('>');
+            if (endDelim != ULONG_MAX) {
+                    if (endDelim > startDelim) {
+                            buf.tag = msg.substr(startDelim+1, (endDelim-startDelim)-1);
+                            if (buf.tag.find_first_of('/') == ULONG_MAX) { // start tags should not be end tags
+
+
+                                    // construct end tag (</buf.data>)
+                                    Glib::ustring endTag(buf.tag);
+                                    endTag.insert(0, "/");
+
+                                    Glib::ustring::size_type endTagLoc = msg.find(endTag, endDelim);
+                                    if (endTagLoc != ULONG_MAX) {
+                                            buf.data = msg.substr(endDelim+1, ((endTagLoc - 1) - (endDelim + 1)));
+                                            buf.next_pos = endTagLoc + endTag.length() + 1;
+
+                                            return true;
+                                    }
+                            }
+                    }
+            }
+    }
+
+    return false;
 }
 
 bool
-MessageUtilities::findTag(struct Node& buf, Glib::ustring const& msg)
+MessageUtilities::findTag(struct Node& buf, const Glib::ustring &msg)
 {
-       if (msg.empty()) {
-               return false;
-       }
-
-       // Read desired tag type out of buffer, and append
-       // < > to it 
-       
-       Glib::ustring searchterm("<");
-       searchterm += buf.tag;
-       searchterm + ">";
-
-       Glib::ustring::size_type tagStart = msg.find(searchterm, 0);
-       if (tagStart != ULONG_MAX) {
-               // Find ending tag starting at the point at the end of
-               // the start tag.
-               searchterm.insert(1, "/");
-               Glib::ustring::size_type tagEnd = msg.find(searchterm, tagStart + searchterm.length());
-               if (tagEnd != ULONG_MAX) {
-                       Glib::ustring::size_type start = tagStart + searchterm.length();
-                       buf.data = msg.substr(start, tagEnd - start);
-                       return true;
-               }
-       }
-       return false;
+    if (msg.empty())
+        return false;
+
+    // Read desired tag type out of buffer, and append
+    // < > to it 
+
+    Glib::ustring searchterm("<");
+    searchterm += buf.tag;
+    searchterm + ">";
+
+    Glib::ustring::size_type tagStart = msg.find(searchterm, 0);
+    if (tagStart != ULONG_MAX) {
+            // Find ending tag starting at the point at the end of
+            // the start tag.
+            searchterm.insert(1, "/");
+            Glib::ustring::size_type tagEnd = msg.find(searchterm, tagStart + searchterm.length());
+            if (tagEnd != ULONG_MAX) {
+                    Glib::ustring::size_type start = tagStart + searchterm.length();
+                    buf.data = msg.substr(start, tagEnd - start);
+                    return true;
+            }
+    }
+    return false;
 }
 
 Glib::ustring
-MessageUtilities::makeTagWithContent(Glib::ustring tagname, Glib::ustring content)
+MessageUtilities::makeTagWithContent(const Glib::ustring &tagname,
+                                     const Glib::ustring &content)
 {
-       Glib::ustring buf;
-       buf = "<" + tagname + ">";
-       buf += content;
-       buf += "</" + tagname + ">";
-       return buf;
+    Glib::ustring buf = "<" + tagname + ">";
+    buf += content;
+    buf += "</" + tagname + ">";
+    return buf;
 }
 
 
@@ -444,9 +464,9 @@ MessageUtilities::makeTagWithContent(Glib::ustring tagname, Glib::ustring conten
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index c6d464f0861b57490450d916b52e379631445b2d..dad805c41a51011a81d3760501541004fafed031 100644 (file)
@@ -26,7 +26,7 @@ namespace Inkscape {
 
 namespace Util {
 
-template <typename T>
+template< typename T >
 class ptr_shared;
 
 }
@@ -43,24 +43,49 @@ class XMLNodeTracker;
 
 class MessageUtilities {
 public:
-       // Message generation utilities
-       static void newObjectMessage(ustring* msgbuf, KeyToNodeMap& newidsbuf, NodeToKeyMap& newnodesbuf, NewChildObjectMessageList& childmsgbuf, XMLNodeTracker* xmt, Inkscape::XML::Node const* node, bool only_collect_nodes = false, bool collect_children = true); 
-       static void objectChangeMessage(ustring* msgbuf, XMLNodeTracker* xmt, std::string const id, gchar const* key, gchar const* oldval, gchar const* newval, bool is_interactive);
-       static void objectDeleteMessage(ustring* msgbuf, XMLNodeTracker* xmt, Inkscape::XML::Node const& parent, Inkscape::XML::Node const& child, Inkscape::XML::Node const* prev);
-       static void contentChangeMessage(ustring& msgbuf, std::string const nodeid, Util::ptr_shared<char> old_value, Util::ptr_shared<char> new_value);
-       static void childOrderChangeMessage(ustring& msgbuf, std::string const childid, std::string const oldprevid, std::string const newprevid);
-
-       // Message parsing utilities
-       static bool getFirstMessageTag(struct Node& buf, ustring const& msg);
-       static bool findTag(struct Node& buf, ustring const& msg);
-
-       // Message tag generation utilities
-       static Glib::ustring makeTagWithContent(Glib::ustring tagname, Glib::ustring content);
+    // Message generation utilities
+    static void newObjectMessage(Glib::ustring &msgbuf, 
+                           KeyNodeTable& newnodesbuf, 
+                           NewChildObjectMessageList& childmsgbuf, 
+                           XMLNodeTracker* xmt,
+                           Inkscape::XML::Node const* node, 
+                           bool only_collect_nodes = false,
+                           bool collect_children = true); 
+    static void objectChangeMessage(Glib::ustring &msgbuf, 
+                           XMLNodeTracker* xmt,
+                           const Glib::ustring &id, 
+                           gchar const* key,
+                           gchar const* oldval, 
+                           gchar const* newval,
+                           bool is_interactive);
+    static void objectDeleteMessage(Glib::ustring &msgbuf,
+                           XMLNodeTracker* xmt, 
+                           Inkscape::XML::Node const& parent,
+                           Inkscape::XML::Node const& child,
+                           Inkscape::XML::Node const* prev);
+    static void contentChangeMessage(Glib::ustring &msgbuf,
+                           const Glib::ustring &nodeid,
+                           Util::ptr_shared<char> old_value,
+                           Util::ptr_shared<char> new_value);
+    static void childOrderChangeMessage(Glib::ustring &msgbuf,
+                           const Glib::ustring &childid,
+                           const Glib::ustring &oldprevid,
+                           const Glib::ustring &newprevid);
+
+    // Message parsing utilities
+    static bool getFirstMessageTag(struct Node& buf,
+                          const Glib::ustring &msg);
+    static bool findTag(struct Node& buf, 
+                          const Glib::ustring &msg);
+
+    // Message tag generation utilities
+    static Glib::ustring makeTagWithContent(const Glib::ustring &tagname,
+                                            const Glib::ustring &content);
 
 private:
-       // noncopyable, nonassignable
-       MessageUtilities(MessageUtilities const&);
-       MessageUtilities& operator=(MessageUtilities const&);
+    // noncopyable, nonassignable
+    MessageUtilities(MessageUtilities const&);
+    MessageUtilities& operator=(MessageUtilities const&);
 
 };
 
@@ -81,5 +106,5 @@ private:
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
 #endif
diff --git a/src/jabber_whiteboard/message-verifier.h b/src/jabber_whiteboard/message-verifier.h
new file mode 100644 (file)
index 0000000..48ef01b
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __INKSCAPE_WHITEBOARD_MESSAGE_VERIFIER_H__
+#define __INKSCAPE_WHITEBOARD_MESSAGE_VERIFIER_H__
+
+/**
+ * Inkscape::Whiteboard::MessageVerifier -- performs basic XMPP-related
+ * validity checks on incoming messages
+ *
+ * Authors:
+ * David Yip <yipdw@alumni.rose-hulman.edu>
+ *
+ * Copyright (c) 2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+ /**
+  * The class has been written, but I forgot to commit that file to SVN,
+  * and the only other copy I have is on a computer that I do not currently
+  * have access to.  So, for now, this is just a placeholder with enums
+  * to get things working.
+  */
+
+enum MessageValidityTestResult {
+       RESULT_VALID,
+       RESULT_INVALID
+};
+
+}
+
+}
+
+#endif
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/new-inkboard-document.cpp b/src/jabber_whiteboard/new-inkboard-document.cpp
new file mode 100644 (file)
index 0000000..e67a3c8
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+ * new-inkboard-document.h
+ * Functions to create new Inkboard documents, based off of sp_document_new /
+ * sp_file_new
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ *
+ * Copyright (c) 2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <glibmm.h>
+#include <glibmm/i18n.h>
+
+#include "document.h"
+#include "document-private.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "interface.h"
+#include "sp-namedview.h"
+#include "desktop-handles.h"
+
+#include "gc-anchored.h"
+
+#include "ui/view/view-widget.h"
+
+#include "application/application.h"
+#include "application/editor.h"
+
+#include "util/ucompose.hpp"
+
+#include "xml/node.h"
+#include "xml/repr.h"
+
+#include "jabber_whiteboard/inkboard-document.h"
+#include "jabber_whiteboard/new-inkboard-document.h"
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+SPDocument*
+makeInkboardDocument(int code, gchar const* rootname, SessionType type, Glib::ustring const& to)
+{
+       SPDocument* doc;
+       InkboardDocument* rdoc = new InkboardDocument(g_quark_from_static_string("xml"), type, to);
+       rdoc->setAttribute("version", "1.0");
+       rdoc->setAttribute("standalone", "no");
+       XML::Node *comment = sp_repr_new_comment(" Created with Inkscape (http://www.inkscape.org/) ");
+       rdoc->appendChild(comment);
+       GC::release(comment);
+
+       XML::Node* root = sp_repr_new(rootname);
+       rdoc->appendChild(root);
+       GC::release(root);
+
+       Glib::ustring name = String::ucompose(_("Inkboard session (%1 to %2)"), SessionManager::instance().getClient().getJid(), to);
+
+       doc = sp_document_create(rdoc, NULL, NULL, name.c_str(), TRUE);
+       return doc;
+}
+
+// TODO: When the switchover to the new GUI is complete, this function should go away
+// and be replaced with a call to Inkscape::NSApplication::Editor::createDesktop.  
+// It currently only exists to correctly mimic the desktop creation functionality
+// in file.cpp.
+//
+// \see sp_file_new
+SPDesktop*
+makeInkboardDesktop(SPDocument* doc)
+{
+       SPDesktop* dt;
+
+       if (NSApplication::Application::getNewGui()) {
+               dt = NSApplication::Editor::createDesktop(doc);
+       } else {
+        SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL));
+        g_return_val_if_fail(dtw != NULL, NULL);
+        sp_document_unref(doc);
+
+        sp_create_window(dtw, TRUE);
+        dt = static_cast<SPDesktop*>(dtw->view);
+        sp_namedview_window_from_document(dt);
+       }
+
+       return dt;
+}
+
+}
+
+}
diff --git a/src/jabber_whiteboard/new-inkboard-document.h b/src/jabber_whiteboard/new-inkboard-document.h
new file mode 100644 (file)
index 0000000..d55cfe7
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * new-inkboard-document.h
+ * Functions to create new Inkboard documents, based off of sp_document_new /
+ * sp_file_new
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ *
+ * Copyright (c) 2006 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef __INKSCAPE_WHITEBOARD_NEW_DOCUMENT_H__
+#define __INKSCAPE_WHITEBOARD_NEW_DOCUMENT_H__
+
+#include <glibmm.h>
+
+class SPDocument;
+class SPDesktop;
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+SPDocument* makeInkboardDocument(int code, gchar const* rootname, SessionType type, Glib::ustring const& to);
+SPDesktop* makeInkboardDesktop(SPDocument* doc);
+
+}
+
+}
+
+#endif
diff --git a/src/jabber_whiteboard/node-tracker-event-tracker.cpp b/src/jabber_whiteboard/node-tracker-event-tracker.cpp
deleted file mode 100644 (file)
index da872c5..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Tracks node add/remove events to an XMLNodeTracker, and eliminates cases such as
- * consecutive add/remove.
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "xml/node.h"
-
-#include "jabber_whiteboard/node-tracker-event-tracker.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-bool
-NodeTrackerEventTracker::tryToTrack(XML::Node* node, NodeTrackerAction action)
-{
-       // 1.  Check if node is being tracked.
-       NodeActionMap::iterator i = this->_actions.find(node);
-       if (i != this->_actions.end()) {
-               // 2a.  Check the action.  If it is the same as the action we are registering,
-               // return false.  Otherwise, register the action with the actions map
-               // and return true.
-               if (i->second == action) {
-                       return false;
-               } else {
-                       this->_actions[node] = action;
-                       return true;
-               }
-       } else {
-               // 2b.  If we aren't tracking this node, insert it with the given action.
-               this->_actions[node] = action;
-               return true;
-       }
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/node-tracker-event-tracker.h b/src/jabber_whiteboard/node-tracker-event-tracker.h
deleted file mode 100644 (file)
index c600592..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Tracks node add/remove events to an XMLNodeTracker, and eliminates cases such as
- * consecutive add/remove.
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_NODE_TRACKER_EVENT_TRACKER_H__
-#define __WHITEBOARD_NODE_TRACKER_EVENT_TRACKER_H__
-
-#include <map>
-
-#include "jabber_whiteboard/typedefs.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-typedef std::pair< XML::Node*, std::string > NodeKeyPair;
-typedef std::map< XML::Node*, NodeTrackerAction > NodeActionMap;
-
-class NodeTrackerEventTracker {
-public:
-       NodeTrackerEventTracker() { }
-       ~NodeTrackerEventTracker() { }
-       bool tryToTrack(XML::Node* node, NodeTrackerAction action);
-
-       NodeTrackerAction getAction(XML::Node const* node)
-       {
-               NodeActionMap::iterator i = this->_actions.find(const_cast< XML::Node* >(node));
-               if (i != this->_actions.end()) {
-                       return i->second;
-               } else {
-                       return NODE_UNKNOWN;
-               }
-       }
-
-       void clear()
-       {
-               this->_actions.clear();
-       }
-private:
-       NodeActionMap _actions;
-};
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/node-tracker-observer.h b/src/jabber_whiteboard/node-tracker-observer.h
deleted file mode 100644 (file)
index 86aa5c3..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * Convenience base class for XML::NodeObservers that need to extract data
- * from an XMLNodeTracker and queue up added or removed nodes for later
- * processing
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_NODE_TRACKER_OBSERVER_H__
-#define __WHITEBOARD_NODE_TRACKER_OBSERVER_H__
-
-#include "xml/node-observer.h"
-
-#include "jabber_whiteboard/node-tracker-event-tracker.h"
-#include "jabber_whiteboard/node-tracker.h"
-#include "jabber_whiteboard/typedefs.h"
-
-namespace Inkscape {
-
-namespace XML {
-
-class Node;
-
-}
-
-namespace Whiteboard {
-
-class NodeTrackerObserver : public XML::NodeObserver {
-public:
-       NodeTrackerObserver(XMLNodeTracker* xnt) : _xnt(xnt) { }
-       virtual ~NodeTrackerObserver() { }
-
-       // just reinforce the fact that we don't implement any of the 
-       // notification methods here
-    virtual void notifyChildAdded(XML::Node &node, XML::Node &child, XML::Node *prev)=0;
-
-    virtual void notifyChildRemoved(XML::Node &node, XML::Node &child, XML::Node *prev)=0;
-
-    virtual void notifyChildOrderChanged(XML::Node &node, XML::Node &child,
-                                         XML::Node *old_prev, XML::Node *new_prev)=0;
-
-    virtual void notifyContentChanged(XML::Node &node,
-                                      Util::ptr_shared<char> old_content,
-                                      Util::ptr_shared<char> new_content)=0;
-
-    virtual void notifyAttributeChanged(XML::Node &node, GQuark name,
-                                        Util::ptr_shared<char> old_value,
-                                        Util::ptr_shared<char> new_value)=0;
-
-
-       // ...but we do provide node tracking facilities
-       KeyToNodeActionList& getNodeTrackerActions()
-       {
-               return this->newnodes;
-       }
-
-       KeyToNodeActionList getNodeTrackerActionsCopy()
-       {
-               return this->newnodes;
-       }
-
-       void clearNodeBuffers()
-       {
-               this->newnodes.clear();
-               this->newkeys.clear();
-               this->actions.clear();
-       }
-
-protected:
-       std::string _findOrGenerateNodeID(XML::Node& node)
-       {
-               NodeToKeyMap::iterator i = newkeys.find(&node);
-               if (i != newkeys.end()) {
-//                     g_log(NULL, G_LOG_LEVEL_DEBUG, "Found key for %p (local): %s", &node, i->second.c_str());
-                       return i->second;
-               } else {
-                       std::string nodeid = this->_xnt->get(node);
-                       if (nodeid.empty()) {
-//                             g_log(NULL, G_LOG_LEVEL_DEBUG, "Generating key for %p", &node);
-                               return this->_xnt->generateKey();
-                       } else {
-//                             g_log(NULL, G_LOG_LEVEL_DEBUG, "Found key for %p (tracker): %s", &node, nodeid.c_str());
-                               return nodeid;
-                       }
-               }
-       }
-
-       KeyToNodeActionList newnodes;
-       NodeTrackerEventTracker actions;
-       NodeToKeyMap newkeys;
-       XMLNodeTracker* _xnt;
-
-private:
-       // noncopyable, nonassignable
-       NodeTrackerObserver(NodeTrackerObserver const& other);
-       NodeTrackerObserver& operator=(NodeTrackerObserver const& other);
-
-};
-
-}
-
-}
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 84bc12945bee60ed9d9f4dc7749ee9ae362499d3..a506d472a8c999ec1e9888f0fea3da8ce3e351de 100644 (file)
@@ -52,217 +52,187 @@ char const* specialnodenames[] = {
 };
 
 XMLNodeTracker::XMLNodeTracker(SessionManager* sm) :
-       _rootKey(DOCUMENT_ROOT_NODE),
-       _namedviewKey(DOCUMENT_NAMEDVIEW_NODE)
+                         _rootKey(DOCUMENT_ROOT_NODE),
+                         _namedviewKey(DOCUMENT_NAMEDVIEW_NODE)
 {
-       this->_sm = sm;
-       this->_counter = 0;
-
-       // Construct special node maps
-       this->createSpecialNodeTables();
-       this->reset();
+    _sm = sm;
+   init();
 }
 
-XMLNodeTracker::~XMLNodeTracker()
+XMLNodeTracker::XMLNodeTracker() :
+                         _rootKey(DOCUMENT_ROOT_NODE),
+                         _namedviewKey(DOCUMENT_NAMEDVIEW_NODE)
 {
-       this->_clear();
+    _sm = NULL;
+    init();
 }
 
-void
-XMLNodeTracker::put(std::string key, XML::Node const& node)
+XMLNodeTracker::~XMLNodeTracker()
 {
-       this->put(key, const_cast< XML::Node& >(node));
+    _clear();
 }
 
-void 
-XMLNodeTracker::put(std::string key, XML::Node& node)
-{      
-       KeyToTrackerNodeMap::iterator i = this->_keyToNode.find(key);
-       if (i != this->_keyToNode.end()) {
-               this->_keyToNode.erase(i);
-       }
-       this->_keyToNode.insert(std::make_pair< std::string, XML::Node* >(key, &node));
-
-       TrackerNodeToKeyMap::iterator j = this->_nodeToKey.find(&node);
-       if (j != this->_nodeToKey.end()) {
-               this->_nodeToKey.erase(j);
-       }
-       this->_nodeToKey.insert(std::make_pair< XML::Node*, std::string >(&node, key));
-}
 
 void
-XMLNodeTracker::put(KeyToNodeMap& newids, NodeToKeyMap& newnodes)
+XMLNodeTracker::init()
 {
-       // TODO: redo
-       KeyToNodeMap::iterator i = newids.begin();
+    _counter = 0;
 
-       for(; i != newids.end(); i++) {
-               this->put((*i).first, *((*i).second));
-       }
+    // Construct special node maps
+    createSpecialNodeTables();
+    if (_sm)
+        reset();
 }
 
 void
-XMLNodeTracker::process(KeyToNodeActionList& actions)
+XMLNodeTracker::setSessionManager(const SessionManager *val)
 {
-       KeyToNodeActionList::iterator i = actions.begin();
-       for(; i != actions.end(); i++) {
-               // Get the action to perform.
-               SerializedEventNodeAction action = *i;
-               switch(action.second) {
-                       case NODE_ADD:
-                               this->put(action.first.first, *action.first.second);
-                               break;
-                       case NODE_REMOVE:
-               //              this->remove(const_cast< XML::Node& >(*action.first.second));
-                               break;
-                       default:
-                               break;
-               }
-       }
+    _sm = (SessionManager *)val;
+    if (_sm)
+        reset();
 }
 
-XML::Node*
-XMLNodeTracker::get(std::string& key)
-{
-       KeyToTrackerNodeMap::iterator i = this->_keyToNode.find(key);
-       if (i != this->_keyToNode.end()) {
-               return (*i).second;
-       } else {
-               g_warning("Key %s is not being tracked!", key.c_str());
-               return NULL;
-       }
-}
-
-XML::Node*
-XMLNodeTracker::get(std::string const& key)
-{
-       return this->get(const_cast< std::string& >(key));
+void 
+XMLNodeTracker::put(const Glib::ustring &key, const XML::Node &nodeArg)
+{      
+    keyNodeTable.put(key, &nodeArg);
 }
 
 
-std::string const
-XMLNodeTracker::get(XML::Node& node)
+void
+XMLNodeTracker::process(const KeyToNodeActionList &actions)
 {
-       TrackerNodeToKeyMap::iterator i = this->_nodeToKey.find(&node);
-       if (i != this->_nodeToKey.end()) {
-               return (*i).second;
-       } else {
-               return "";
-       }
+    KeyToNodeActionList::const_iterator iter = actions.begin();
+    for(; iter != actions.end(); iter++) {
+        // Get the action to perform.
+        SerializedEventNodeAction action = *iter;
+        switch(action.second) {
+            case NODE_ADD:
+                //g_log(NULL, G_LOG_LEVEL_DEBUG, 
+                //"NODE_ADD event: key %s, node %p", 
+                //action.first.first.c_str(), action.first.second);
+                put(action.first.key, *action.first.node);
+                break;
+            case NODE_REMOVE:
+                //g_log(NULL, G_LOG_LEVEL_DEBUG,
+                //"NODE_REMOVE event: key %s, node %p",
+                // action.first.first.c_str(), action.first.second);
+                //remove(const_cast< XML::Node& >(*action.first.second));
+                break;
+            default:
+                break;
+        }
+    }
 }
 
-std::string const
-XMLNodeTracker::get(XML::Node const& node)
+XML::Node*
+XMLNodeTracker::get(const Glib::ustring &key)
 {
-       return this->get(const_cast< XML::Node& >(node));
-}
+    XML::Node *node = keyNodeTable.get(key);
+    if (node)
+        return node;
 
-bool
-XMLNodeTracker::isTracking(std::string& key)
-{
-       return (this->_keyToNode.find(key) != this->_keyToNode.end());
+    g_warning("Key %s is not being tracked!", key.c_str());
+    return NULL;
 }
 
-bool
-XMLNodeTracker::isTracking(std::string const& key)
+Glib::ustring
+XMLNodeTracker::get(const XML::Node &nodeArg)
 {
-       return this->isTracking(const_cast< std::string& >(key));
+    Glib::ustring key = keyNodeTable.get((XML::Node *)&nodeArg);
+    return key;
 }
 
 bool
-XMLNodeTracker::isTracking(XML::Node& node)
+XMLNodeTracker::isTracking(const Glib::ustring &key)
 {
-       return (this->_nodeToKey.find(&node) != this->_nodeToKey.end());
+    return (get(key)!=NULL);
 }
 
 bool
-XMLNodeTracker::isTracking(XML::Node const& node)
+XMLNodeTracker::isTracking(const XML::Node &node)
 {
-       return this->isTracking(const_cast< XML::Node& >(node));
+    return (get(node).size()>0);
 }
 
+
 bool
-XMLNodeTracker::isRootNode(XML::Node& node)
+XMLNodeTracker::isRootNode(const XML::Node &node)
 {
-       XML::Node* docroot = sp_document_repr_root(this->_sm->document());
-       return (docroot == &node);
+    XML::Node* docroot = sp_document_repr_root(_sm->getDocument());
+    return (docroot == &node);
 }
 
 
 void
-XMLNodeTracker::remove(std::string& key)
+XMLNodeTracker::remove(const Glib::ustring& key)
 {
-       if (this->isTracking(key)) {
-               XML::Node* element = this->get(key);
-               this->_keyToNode.erase(key);
-               this->_nodeToKey.erase(element);
-       } 
+    g_log(NULL, G_LOG_LEVEL_DEBUG, "Removing node with key %s", key.c_str());
+    keyNodeTable.remove(key);
 }
 
 void
-XMLNodeTracker::remove(XML::Node& node)
+XMLNodeTracker::remove(const XML::Node &nodeArg)
 {
-       if (this->isTracking(node)) {
-               std::string const element = this->get(node);
-               this->_nodeToKey.erase(&node);
-               this->_keyToNode.erase(element);
-       }
+    //g_log(NULL, G_LOG_LEVEL_DEBUG, "Removing node %p", &node);
+    keyNodeTable.remove((XML::Node *)&nodeArg);
 }
 
-bool 
-XMLNodeTracker::isSpecialNode(char const* name)
-{
-       return (this->_specialnodes.find(name) != this->_specialnodes.end());   
-}
 
 bool 
-XMLNodeTracker::isSpecialNode(std::string const& name)
+XMLNodeTracker::isSpecialNode(const Glib::ustring &name)
 {
-       return (this->_specialnodes.find(name.data()) != this->_specialnodes.end());    
+    return (_specialnodes.find(name.data()) != _specialnodes.end());   
 }
 
-std::string const
+Glib::ustring
 XMLNodeTracker::getSpecialNodeKeyFromName(Glib::ustring const& name)
 {
-       return this->_specialnodes[name.data()];
+    return _specialnodes[name.data()];
 }
 
-std::string const
-XMLNodeTracker::getSpecialNodeKeyFromName(Glib::ustring const* name)
-{
-       return this->_specialnodes[name->data()];       
-}
-
-std::string
+Glib::ustring
 XMLNodeTracker::generateKey(gchar const* JID)
 {
-       return String::compose("%1;%2", this->_counter++, JID);
+    return String::compose("%1;%2", _counter++, JID);
 }
 
-std::string 
+Glib::ustring 
 XMLNodeTracker::generateKey()
 {
-       SessionData* sd = this->_sm->session_data;
-       std::bitset< NUM_FLAGS >& status = sd->status;
-       if (status[IN_CHATROOM]) {
-               // This is not strictly required for chatrooms: chatrooms will
-               // function just fine with the user-to-user ID scheme.  However,
-               // the user-to-user scheme can lead to loss of anonymity
-               // in anonymous chat rooms, since it contains the real JID
-               // of a user.
-               return String::compose("%1;%2@%3/%4", this->_counter++, sd->chat_name, sd->chat_server, sd->chat_handle);
-       } else {
-               return String::compose("%1;%2", this->_counter++, sd->jid);
-       }
+    std::bitset< NUM_FLAGS >& status = _sm->getStatus();
+    Glib::ustring ret;
+    if (status[IN_CHATROOM]) {
+        // This is not strictly required for chatrooms: chatrooms will
+        // function just fine with the user-to-user ID scheme.  However,
+        // the user-to-user scheme can lead to loss of anonymity
+        // in anonymous chat rooms, since it contains the real JID
+        // of a user.
+        /*
+        ret = String::compose("%1;%2@%3/%4",
+                 _counter++,
+                 _sm->getClient().getUsername(),
+                 _sm->getClient().getHost(),
+                 sd->chat_handle);
+       */
+       //We need to work on this since Pedro allows multiple chatrooms
+        ret = String::compose("%1;%2",
+                 _counter++, 
+                 _sm->getClient().getJid());
+    } else {
+        ret = String::compose("%1;%2",
+                 _counter++, 
+                 _sm->getClient().getJid());
+    }
+    return  ret;
 }
 
 void
 XMLNodeTracker::createSpecialNodeTables()
 {
-       int const sz = sizeof(specialnodekeys) / sizeof(char const*);
-       for(int i = 0; i < sz; i++) {
-               this->_specialnodes[specialnodenames[i]] = specialnodekeys[i];
-       }
+    int const sz = sizeof(specialnodekeys) / sizeof(char const*);
+    for(int i = 0; i < sz; i++)
+         _specialnodes[specialnodenames[i]] = specialnodekeys[i];
 }
 
 
@@ -270,89 +240,69 @@ XMLNodeTracker::createSpecialNodeTables()
 void 
 XMLNodeTracker::dump()
 {
-       g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker dump for %s", this->_sm->session_data->jid.c_str());
-       KeyToTrackerNodeMap::iterator i = this->_keyToNode.begin();
-       TrackerNodeToKeyMap::iterator j = this->_nodeToKey.begin();
-       std::map< char const*, char const* >::iterator k = this->_specialnodes.begin();
-       
-
-       g_log(NULL, G_LOG_LEVEL_DEBUG, "%u entries in keyToNode, %u entries in nodeToKey", this->_keyToNode.size(), this->_nodeToKey.size());
-
-       if (this->_keyToNode.size() != this->_nodeToKey.size()) {
-               g_warning("Map sizes do not match!");
-       }
-
-       g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker keyToNode dump");
-       while(i != this->_keyToNode.end()) {
-               if (!((*i).first.empty())) {
-                       if ((*i).second != NULL) {
-                               g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t%p (%s) (%s)", (*i).first.c_str(), (*i).second, (*i).second->name(), (*i).second->content());
-                       } else {
-                               g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t(null)", (*i).first.c_str());
-                       }
-               } else {
-                       g_log(NULL, G_LOG_LEVEL_DEBUG, "(null)\t->\t%p (%s)", (*i).second, (*i).second->name());
-               }
-               i++;
-       }
-
-       g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker nodeToKey dump");
-       while(j != this->_nodeToKey.end()) {
-               if (!((*j).second.empty())) {
-                       if ((*j).first) {
-                               g_log(NULL, G_LOG_LEVEL_DEBUG, "%p\t->\t%s (parent %p)", (*j).first, (*j).second.c_str(), (*j).first->parent());
-                       } else {
-                               g_log(NULL, G_LOG_LEVEL_DEBUG, "(null)\t->\t%s", (*j).second.c_str());
-                       }
-               } else {
-                       g_log(NULL, G_LOG_LEVEL_DEBUG, "%p\t->\t(null)", (*j).first);
-               }
-               j++;
-       }
-
-       g_log(NULL, G_LOG_LEVEL_DEBUG, "_specialnodes dump");
-       while(k != this->_specialnodes.end()) {
-               g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t%s", (*k).first, (*k).second);
-               k++;
-       }
+    g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker dump for %s",
+           _sm->getClient().getJid().c_str());
+
+
+
+    g_log(NULL, G_LOG_LEVEL_DEBUG, "%u entries in keyNodeTable", 
+                         keyNodeTable.size());
+
+    g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker keyNodeTable dump");
+    for (unsigned int i=0 ; i<keyNodeTable.size() ; i++)
+        {
+        KeyNodePair pair = keyNodeTable.item(i);
+        Glib::ustring key = pair.key;
+        XML::Node *node = pair.node;
+        char *name    = "none";
+        char *content = "none";
+        if (node)
+            {
+            name = (char *)node->name();
+            content = (char *)node->content();
+            }
+        g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t%p (%s) (%s)",
+                  key.c_str(), node, name, content);
+        }
+
+    g_log(NULL, G_LOG_LEVEL_DEBUG, "_specialnodes dump");
+    std::map< char const*, char const* >::iterator k = _specialnodes.begin();
+    while(k != _specialnodes.end()) {
+            g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t%s", (*k).first, (*k).second);
+            k++;
+    }
 }
 
 void
 XMLNodeTracker::reset()
 {
-       this->_clear();
-
-       // Find and insert special nodes
-       // root node
-       this->put(this->_rootKey, *(sp_document_repr_root(this->_sm->document())));
-
-       // namedview node
-       SPObject* namedview = sp_item_group_get_child_by_name((SPGroup *)this->_sm->document()->root, NULL, DOCUMENT_NAMEDVIEW_NAME);
-       if (!namedview) {
-               g_warning("namedview node does not exist; it will be created during synchronization");
-       } else {
-               this->put(this->_namedviewKey, *(SP_OBJECT_REPR(namedview)));
-       }
+    _clear();
+
+    // Find and insert special nodes
+    // root node
+    put(_rootKey, *(sp_document_repr_root(_sm->getDocument())));
+
+    // namedview node
+    SPObject* namedview = sp_item_group_get_child_by_name(
+                 (SPGroup *)_sm->getDocument()->root,
+                  NULL, DOCUMENT_NAMEDVIEW_NAME);
+    if (!namedview) {
+            g_warning("namedview node does not exist; it will be created during synchronization");
+    } else {
+            put(_namedviewKey, *(SP_OBJECT_REPR(namedview)));
+    }
 }
 
 void
 XMLNodeTracker::_clear()
 {
-       // Remove all keys in both trackers, and delete each key.
-       this->_keyToNode.clear();
-       this->_nodeToKey.clear();
-
-       /*
-       TrackerNodeToKeyMap::iterator j = this->_nodeToKey.begin();
-       for(; j != this->_nodeToKey.end(); j++) {
-               this->_nodeToKey.erase(j);
-       }
-       */
+    // Remove all keys in both trackers, and delete each key.
+    keyNodeTable.clear();
 }
 
-}
+}  // namespace Whiteboard
 
-}
+}  // namespace Inkscape
 
 
 
@@ -360,9 +310,9 @@ XMLNodeTracker::_clear()
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index 9c92b815aca1137791323435d5b5a7adc6802e5b..660b784fbf589f6be71c83343f873b527d92bf4d 100644 (file)
@@ -67,21 +67,21 @@ struct strcmpless : public std::binary_function< char const*, char const*, bool
  */
 class XMLNodeTracker  {
 public:
+       /**
+        * Constructor.
+                */
+       XMLNodeTracker();
+
        /**
         * Constructor.
         *
         * \param sm The SessionManager with which an XMLNodeTracker instance is to be associated with.
         */
        XMLNodeTracker(SessionManager* sm);
+
        ~XMLNodeTracker();
 
-       /** 
-        * Insert a (key,node) pair into the tracker.
-        *
-        * \param key The key to associate with the node.
-        * \param node The node to associate with the key.
-        */
-       void put(std::string key, XML::Node& node);
+        void setSessionManager(const SessionManager *val);
 
        /** 
         * Insert a (key,node) pair into the tracker.
@@ -89,31 +89,14 @@ public:
         * \param key The key to associate with the node.
         * \param node The node to associate with the key.
         */
-       void put(std::string key, XML::Node const& node);
-
-       /** 
-        * Insert a range of (key,node) pairs into the tracker.
-        *
-        * The size of the two maps must be the same.
-        * \param newids The keys to associate with the nodes.
-        * \param newnodes The nodes to associate with the keys.
-        */
-       void put(KeyToNodeMap& newids, NodeToKeyMap& newnodes);
+       void put(const Glib::ustring &key, const XML::Node &node);
 
        /**
         * Process a list of node actions to add and remove nodes from the tracker.
         *
         * \param actions The action list to process.
         */
-       void process(KeyToNodeActionList& actions);
-
-       /**
-        * Retrieve an XML::Node given a key.
-        *
-        * \param key Reference to a string key.
-        * \return Pointer to an XML::Node, or NULL if no associated node could be found.
-        */
-       XML::Node* get(std::string& key);
+       void process(const KeyToNodeActionList& actions);
 
        /**
         * Retrieve an XML::Node given a key.
@@ -121,15 +104,7 @@ public:
         * \param key Reference to a const string key.
         * \return Pointer to an XML::Node, or NULL if no associated node could be found.
         */
-       XML::Node* get(std::string const& key);
-
-       /**
-        * Retrieve a string key given a reference to an XML::Node.
-        *
-        * \param node Reference to an XML::Node.
-        * \return The associated string key, or an empty string if no associated key could be found.
-        */
-       std::string const get(XML::Node& node);
+       XML::Node* get(const Glib::ustring &key);
 
        /**
         * Retrieve a string key given a reference to an XML::Node.
@@ -137,21 +112,21 @@ public:
         * \param node Reference to a const XML::Node.
         * \return The associated string key, or an empty string if no associated key could be found.
         */
-       std::string const get(XML::Node const& node);
+       Glib::ustring get(const XML::Node &node);
 
        /**
         * Remove an entry from the tracker based on key.
         *
         * \param The key of the entry to remove.
         */
-       void remove(std::string& key);
+       void remove(const Glib::ustring& key);
 
        /**
         * Remove an entry from the tracker based on XML::Node.
         *
         * \param A reference to the XML::Node associated with the entry to remove.
         */
-       void remove(XML::Node& node);
+       void remove(const XML::Node& node);
 
        /**
         * Return whether or not a (key,node) pair is being tracked, given a string key.
@@ -159,15 +134,7 @@ public:
         * \param The key associated with the pair to check.
         * \return Whether or not the pair is being tracked.
         */
-       bool isTracking(std::string& key);
-
-       /**
-        * Return whether or not a (key,node) pair is being tracked, given a string key.
-        *
-        * \param The key associated with the pair to check.
-        * \return Whether or not the pair is being tracked.
-        */
-       bool isTracking(std::string const& key);
+       bool isTracking(const Glib::ustring &key);
 
        /**
         * Return whether or not a (key,node) pair is being tracked, given a node.
@@ -175,26 +142,7 @@ public:
         * \param The node associated with the pair to check.
         * \return Whether or not the pair is being tracked.
         */
-       bool isTracking(XML::Node& node);
-
-       /**
-        * Return whether or not a (key,node) pair is being tracked, given a node.
-        *
-        * \param The node associated with the pair to check.
-        * \return Whether or not the pair is being tracked.
-        */
-       bool isTracking(XML::Node const& node);
-
-       /**
-        * Return whether or not a node identified by a given name is a special node.
-        *
-        * \see Inkscape::Whiteboard::specialnodekeys
-        * \see Inkscape::Whiteboard::specialnodenames
-        *
-        * \param The name associated with the node.
-        * \return Whether or not the node is a special node.
-        */
-       bool isSpecialNode(char const* name);
+       bool isTracking(const XML::Node & node);
 
        /**
         * Return whether or not a node identified by a given name is a special node.
@@ -205,7 +153,7 @@ public:
         * \param The name associated with the node.
         * \return Whether or not the node is a special node.
         */
-       bool isSpecialNode(std::string const& name);
+       bool isSpecialNode(Glib::ustring const& name);
 
        /**
         * Retrieve the key of a special node given the name of a special node.
@@ -216,18 +164,8 @@ public:
         * \param The name associated with the node.
         * \return The key of the special node.
         */
-       std::string const getSpecialNodeKeyFromName(Glib::ustring const& name);
-
-       /**
-        * Retrieve the key of a special node given the name of a special node.
-        *
-        * \see Inkscape::Whiteboard::specialnodekeys
-        * \see Inkscape::Whiteboard::specialnodenames
-        *
-        * \param The name associated with the node.
-        * \return The key of the special node.
-        */
-       std::string const getSpecialNodeKeyFromName(Glib::ustring const* name);
+       Glib::ustring getSpecialNodeKeyFromName(
+                               const Glib::ustring &name);
 
        /**
         * Returns whether or not the given node is the root node of the SPDocument associated
@@ -236,7 +174,7 @@ public:
         * \param Reference to an XML::Node to test.
         * \return Whether or not the given node is the document root node.
         */
-       bool isRootNode(XML::Node& node);
+       bool isRootNode(const XML::Node& node);
 
        /** 
         * Generate a node key given a JID.
@@ -244,7 +182,7 @@ public:
         * \param The JID to use in the key.
         * \return A node string key.
         */
-       std::string generateKey(gchar const* JID);
+       Glib::ustring generateKey(gchar const* JID);
 
        /** 
         * Generate a node key given the JID specified in the SessionData structure associated
@@ -252,30 +190,31 @@ public:
         *
         * \return A node string key.
         */
-       std::string generateKey();
+       Glib::ustring generateKey();
 
        // TODO: remove debugging function
        void dump();
        void reset();
 
 private:
+        //common code called by constructors
+        void init();
+        
        void createSpecialNodeTables();
        void _clear();
        
        unsigned int _counter;
        SessionManager* _sm;
-
-       // defined in typedefs.h
-       KeyToTrackerNodeMap _keyToNode;
-       TrackerNodeToKeyMap _nodeToKey;
+        
+        KeyNodeTable keyNodeTable;
 
        std::map< char const*, char const*, strcmpless > _specialnodes;
 
        // Keys for special nodes
-       std::string _rootKey;
-       std::string _defsKey;
-       std::string _namedviewKey;
-       std::string _metadataKey;
+       Glib::ustring _rootKey;
+       Glib::ustring _defsKey;
+       Glib::ustring _namedviewKey;
+       Glib::ustring _metadataKey;
 
        // noncopyable, nonassignable
        XMLNodeTracker(XMLNodeTracker const&);
@@ -292,9 +231,9 @@ private:
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index f0cbacddc4b54772279b4e2777ffacefec9ece17..cbf4b6ea1c56a8a988f4974597769913f4e4ffa9 100644 (file)
@@ -10,7 +10,7 @@
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
-#include "util/share.h"
+#include "util/shared-c-string-ptr.h"
 #include "util/list.h"
 
 #include "xml/node-observer.h"
@@ -54,7 +54,7 @@ NodeUtilities::lookupReprByValue(Inkscape::XML::Node* root, gchar const* key, Gl
 }
 */
 
-Glib::ustring const
+Glib::ustring
 NodeUtilities::nodeTypeToString(XML::Node const& node)
 {
        switch(node.type()) {
@@ -84,21 +84,21 @@ NodeUtilities::stringToNodeType(Glib::ustring const& type)
        }
 }
 
-std::string const
-NodeUtilities::findNodeID(XML::Node const& node, XMLNodeTracker* tracker, NodeToKeyMap const& newnodes)
+Glib::ustring
+NodeUtilities::findNodeID(XML::Node       const& node, 
+                          XMLNodeTracker* tracker,
+                          KeyNodeTable    const& newnodes)
 {
-//     g_log(NULL, G_LOG_LEVEL_DEBUG, "Attempting to locate id for %p", &node);
-       NodeToKeyMap::const_iterator result = newnodes.find(&node);
-       if (result != newnodes.end()) {
-//             g_log(NULL, G_LOG_LEVEL_DEBUG, "Located id for %p: %s", &node, (*result).second.c_str());
-               return (*result).second;
-       }
+        //g_log(NULL, G_LOG_LEVEL_DEBUG, "Attempting to locate id for %p", &node);
+        Glib::ustring key = newnodes.get((XML::Node *)&node);
+        if (key.size()>0)
+            return key;
 
        if (tracker->isTracking(node)) {
-//             g_log(NULL, G_LOG_LEVEL_DEBUG, "Located id for %p (in tracker): %s", &node, tracker->get(node).c_str());
+                 //g_log(NULL, G_LOG_LEVEL_DEBUG, "Located id for %p (in tracker): %s", &node, tracker->get(node).c_str());
                return tracker->get(node);
        } else {
-//             g_log(NULL, G_LOG_LEVEL_DEBUG, "Failed to locate id");
+                //g_log(NULL, G_LOG_LEVEL_DEBUG, "Failed to locate id");
                return "";
        }
 }
@@ -111,9 +111,9 @@ NodeUtilities::findNodeID(XML::Node const& node, XMLNodeTracker* tracker, NodeTo
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index c74027de2c9a3bad0f8758adf38b68ab70e12287..4a025f14949a264b6bb84d27e3fa0021d5a5ab84 100644 (file)
@@ -30,12 +30,15 @@ class XMLNodeTracker;
 class NodeUtilities {
 public:
        // Node utilities
-//     static Inkscape::XML::Node* lookupReprByValue(Inkscape::XML::Node* root, gchar const* key, ustring const* value);
-       static Glib::ustring const nodeTypeToString(XML::Node const& node);
+        //static Inkscape::XML::Node* lookupReprByValue(Inkscape::XML::Node* root,
+        //                      gchar const* key, Glib::ustring const* value);
+       static Glib::ustring nodeTypeToString(XML::Node const& node);
        static XML::NodeType stringToNodeType(Glib::ustring const& type);
 
        // Node key search utility method
-       static std::string const findNodeID(XML::Node const& node, XMLNodeTracker* tracker, NodeToKeyMap const& newnodes);
+       static Glib::ustring findNodeID(XML::Node const& node, 
+                              XMLNodeTracker* tracker, 
+                              KeyNodeTable const& newnodes);
 
 private:
        // noncopyable, nonassignable
@@ -53,9 +56,9 @@ private:
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/jabber_whiteboard/pedrodom.cpp b/src/jabber_whiteboard/pedrodom.cpp
deleted file mode 100644 (file)
index 903c159..0000000
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
- * Implementation of the Pedro mini-DOM parser and tree
- *
- * Authors:
- *   Bob Jamison
- *
- * Copyright (C) 2005 Bob Jamison
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-
-#include "pedrodom.h"
-
-namespace Pedro
-{
-
-
-
-//########################################################################
-//# E L E M E N T
-//########################################################################
-
-Element *Element::clone()
-{
-    Element *elem = new Element(name, value);
-    elem->parent     = parent;
-    elem->attributes = attributes;
-    elem->namespaces = namespaces;
-
-    std::vector<Element *>::iterator iter;
-    for (iter = children.begin(); iter != children.end() ; iter++)
-        {
-        elem->addChild((*iter)->clone());
-        }
-    return elem;
-}
-
-
-void Element::findElementsRecursive(std::vector<Element *>&res, const DOMString &name)
-{
-    if (getName() == name)
-        {
-        res.push_back(this);
-        }
-    for (unsigned int i=0; i<children.size() ; i++)
-        children[i]->findElementsRecursive(res, name);
-}
-
-std::vector<Element *> Element::findElements(const DOMString &name)
-{
-    std::vector<Element *> res;
-    findElementsRecursive(res, name);
-    return res;
-}
-
-DOMString Element::getAttribute(const DOMString &name)
-{
-    for (unsigned int i=0 ; i<attributes.size() ; i++)
-        if (attributes[i].getName() ==name)
-            return attributes[i].getValue();
-    return "";
-}
-
-DOMString Element::getTagAttribute(const DOMString &tagName, const DOMString &attrName)
-{
-    std::vector<Element *>elems = findElements(tagName);
-    if (elems.size() <1)
-        return "";
-    DOMString res = elems[0]->getAttribute(attrName);
-    return res;
-}
-
-DOMString Element::getTagValue(const DOMString &tagName)
-{
-    std::vector<Element *>elems = findElements(tagName);
-    if (elems.size() <1)
-        return "";
-    DOMString res = elems[0]->getValue();
-    return res;
-}
-
-void Element::addChild(Element *child)
-{
-    if (!child)
-        return;
-    child->parent = this;
-    children.push_back(child);
-}
-
-
-void Element::addAttribute(const DOMString &name, const DOMString &value)
-{
-    Attribute attr(name, value);
-    attributes.push_back(attr);
-}
-
-void Element::addNamespace(const DOMString &prefix, const DOMString &namespaceURI)
-{
-    Namespace ns(prefix, namespaceURI);
-    namespaces.push_back(ns);
-}
-
-void Element::writeIndentedRecursive(FILE *f, int indent)
-{
-    int i;
-    if (!f)
-        return;
-    //Opening tag, and attributes
-    for (i=0;i<indent;i++)
-        fputc(' ',f);
-    fprintf(f,"<%s",name.c_str());
-    for (unsigned int i=0 ; i<attributes.size() ; i++)
-        {
-        fprintf(f," %s=\"%s\"",
-              attributes[i].getName().c_str(),
-              attributes[i].getValue().c_str());
-        }
-    for (unsigned int i=0 ; i<namespaces.size() ; i++)
-        {
-        fprintf(f," xmlns:%s=\"%s\"",
-              namespaces[i].getPrefix().c_str(),
-              namespaces[i].getNamespaceURI().c_str());
-        }
-    fprintf(f,">\n");
-
-    //Between the tags
-    if (value.size() > 0)
-        {
-        for (int i=0;i<indent;i++)
-            fputc(' ', f);
-        fprintf(f," %s\n", value.c_str());
-        }
-
-    for (unsigned int i=0 ; i<children.size() ; i++)
-        children[i]->writeIndentedRecursive(f, indent+2);
-
-    //Closing tag
-    for (int i=0; i<indent; i++)
-        fputc(' ',f);
-    fprintf(f,"</%s>\n", name.c_str());
-}
-
-void Element::writeIndented(FILE *f)
-{
-    writeIndentedRecursive(f, 0);
-}
-
-void Element::print()
-{
-    writeIndented(stdout);
-}
-
-
-//########################################################################
-//# P A R S E R
-//########################################################################
-
-
-
-typedef struct
-    {
-    char *escaped;
-    char value;
-    } EntityEntry;
-
-static EntityEntry entities[] =
-{
-    { "&amp;" , '&'  },
-    { "&lt;"  , '<'  },
-    { "&gt;"  , '>'  },
-    { "&apos;", '\'' },
-    { "&quot;", '"'  },
-    { NULL    , '\0' }
-};
-
-
-
-void Parser::getLineAndColumn(long pos, long *lineNr, long *colNr)
-{
-    long line = 1;
-    long col  = 1;
-    for (long i=0 ; i<pos ; i++)
-        {
-        XMLCh ch = parsebuf[i];
-        if (ch == '\n' || ch == '\r')
-            {
-            col = 0;
-            line ++;
-            }
-        else
-            col++;
-        }
-    *lineNr = line;
-    *colNr  = col;
-
-}
-
-
-void Parser::error(char *fmt, ...)
-{
-    long lineNr;
-    long colNr;
-    getLineAndColumn(currentPosition, &lineNr, &colNr);
-    va_list args;
-    fprintf(stderr, "xml error at line %ld, column %ld:", lineNr, colNr);
-    va_start(args,fmt);
-    vfprintf(stderr,fmt,args);
-    va_end(args) ;
-    fprintf(stderr, "\n");
-}
-
-
-
-int Parser::peek(long pos)
-{
-    if (pos >= parselen)
-        return -1;
-    currentPosition = pos;
-    int ch = parsebuf[pos];
-    //printf("ch:%c\n", ch);
-    return ch;
-}
-
-
-
-DOMString Parser::encode(const DOMString &str)
-{
-    DOMString ret;
-    for (unsigned int i=0 ; i<str.size() ; i++)
-        {
-        XMLCh ch = (XMLCh)str[i];
-        if (ch == '&')
-            ret.append("&amp;");
-        else if (ch == '<')
-            ret.append("&lt;");
-        else if (ch == '>')
-            ret.append("&gt;");
-        else if (ch == '\'')
-            ret.append("&apos;");
-        else if (ch == '"')
-            ret.append("&quot;");
-        else
-            ret.push_back(ch);
-
-        }
-    return ret;
-}
-
-
-int Parser::match(long p0, const char *text)
-{
-    int p = p0;
-    while (*text)
-        {
-        if (peek(p) != *text)
-            return p0;
-        p++; text++;
-        }
-    return p;
-}
-
-
-
-int Parser::skipwhite(long p)
-{
-
-    while (p<parselen)
-        {
-        int p2 = match(p, "<!--");
-        if (p2 > p)
-            {
-            p = p2;
-            while (p<parselen)
-              {
-              p2 = match(p, "-->");
-              if (p2 > p)
-                  {
-                  p = p2;
-                  break;
-                  }
-              p++;
-              }
-          }
-      XMLCh b = peek(p);
-      if (!isspace(b))
-          break;
-      p++;
-      }
-  return p;
-}
-
-/* modify this to allow all chars for an element or attribute name*/
-int Parser::getWord(int p0, DOMString &buf)
-{
-    int p = p0;
-    while (p<parselen)
-        {
-        XMLCh b = peek(p);
-        if (b<=' ' || b=='/' || b=='>' || b=='=')
-            break;
-        buf.push_back(b);
-        p++;
-        }
-    return p;
-}
-
-int Parser::getQuoted(int p0, DOMString &buf, int do_i_parse)
-{
-
-    int p = p0;
-    if (peek(p) != '"' && peek(p) != '\'')
-        return p0;
-    p++;
-
-    while ( p<parselen )
-        {
-        XMLCh b = peek(p);
-        if (b=='"' || b=='\'')
-            break;
-        if (b=='&' && do_i_parse)
-            {
-            bool found = false;
-            for (EntityEntry *ee = entities ; ee->value ; ee++)
-                {
-                int p2 = match(p, ee->escaped);
-                if (p2>p)
-                    {
-                    buf.push_back(ee->value);
-                    p = p2;
-                    found = true;
-                    break;
-                    }
-                }
-            if (!found)
-                {
-                error("unterminated entity");
-                return false;
-                }
-            }
-        else
-            {
-            buf.push_back(b);
-            p++;
-            }
-        }
-    return p;
-}
-
-int Parser::parseVersion(int p0)
-{
-    //printf("### parseVersion: %d\n", p0);
-
-    int p = p0;
-
-    p = skipwhite(p0);
-
-    if (peek(p) != '<')
-        return p0;
-
-    p++;
-    if (p>=parselen || peek(p)!='?')
-        return p0;
-
-    p++;
-
-    DOMString buf;
-
-    while (p<parselen)
-        {
-        XMLCh ch = peek(p);
-        if (ch=='?')
-            {
-            p++;
-            break;
-            }
-        buf.push_back(ch);
-        p++;
-        }
-
-    if (peek(p) != '>')
-        return p0;
-    p++;
-
-    //printf("Got version:%s\n",buf.c_str());
-    return p;
-}
-
-int Parser::parseDoctype(int p0)
-{
-    //printf("### parseDoctype: %d\n", p0);
-
-    int p = p0;
-    p = skipwhite(p);
-
-    if (p>=parselen || peek(p)!='<')
-        return p0;
-
-    p++;
-
-    if (peek(p)!='!' || peek(p+1)=='-')
-        return p0;
-    p++;
-
-    DOMString buf;
-    while (p<parselen)
-        {
-        XMLCh ch = peek(p);
-        if (ch=='>')
-            {
-            p++;
-            break;
-            }
-        buf.push_back(ch);
-        p++;
-        }
-
-    //printf("Got doctype:%s\n",buf.c_str());
-    return p;
-}
-
-int Parser::parseElement(int p0, Element *par,int depth)
-{
-
-    int p = p0;
-
-    int p2 = p;
-
-    p = skipwhite(p);
-
-    //## Get open tag
-    XMLCh ch = peek(p);
-    if (ch!='<')
-        return p0;
-
-    p++;
-
-    DOMString openTagName;
-    p = skipwhite(p);
-    p = getWord(p, openTagName);
-    //printf("####tag :%s\n", openTagName.c_str());
-    p = skipwhite(p);
-
-    //Add element to tree
-    Element *n = new Element(openTagName);
-    n->parent = par;
-    par->addChild(n);
-
-    // Get attributes
-    if (peek(p) != '>')
-        {
-        while (p<parselen)
-            {
-            p = skipwhite(p);
-            ch = peek(p);
-            //printf("ch:%c\n",ch);
-            if (ch=='>')
-                break;
-            else if (ch=='/' && p<parselen+1)
-                {
-                p++;
-                p = skipwhite(p);
-                ch = peek(p);
-                if (ch=='>')
-                    {
-                    p++;
-                    //printf("quick close\n");
-                    return p;
-                    }
-                }
-            DOMString attrName;
-            p2 = getWord(p, attrName);
-            if (p2==p)
-                break;
-            //printf("name:%s",buf);
-            p=p2;
-            p = skipwhite(p);
-            ch = peek(p);
-            //printf("ch:%c\n",ch);
-            if (ch!='=')
-                break;
-            p++;
-            p = skipwhite(p);
-            // ch = parsebuf[p];
-            // printf("ch:%c\n",ch);
-            DOMString attrVal;
-            p2 = getQuoted(p, attrVal, true);
-            p=p2+1;
-            //printf("name:'%s'   value:'%s'\n",attrName.c_str(),attrVal.c_str());
-            char *namestr = (char *)attrName.c_str();
-            if (strncmp(namestr, "xmlns:", 6)==0)
-                n->addNamespace(attrName, attrVal);
-            else
-                n->addAttribute(attrName, attrVal);
-            }
-        }
-
-    bool cdata = false;
-
-    p++;
-    // ### Get intervening data ### */
-    DOMString data;
-    while (p<parselen)
-        {
-        //# COMMENT
-        p2 = match(p, "<!--");
-        if (!cdata && p2>p)
-            {
-            p = p2;
-            while (p<parselen)
-                {
-                p2 = match(p, "-->");
-                if (p2 > p)
-                    {
-                    p = p2;
-                    break;
-                    }
-                p++;
-                }
-            }
-
-        ch = peek(p);
-        //# END TAG
-        if (ch=='<' && !cdata && peek(p+1)=='/')
-            {
-            break;
-            }
-        //# CDATA
-        p2 = match(p, "<![CDATA[");
-        if (p2 > p)
-            {
-            cdata = true;
-            p = p2;
-            continue;
-            }
-
-        //# CHILD ELEMENT
-        if (ch == '<')
-            {
-            p2 = parseElement(p, n, depth+1);
-            if (p2 == p)
-                {
-                /*
-                printf("problem on element:%s.  p2:%d p:%d\n",
-                      openTagName.c_str(), p2, p);
-                */
-                return p0;
-                }
-            p = p2;
-            continue;
-            }
-        //# ENTITY
-        if (ch=='&' && !cdata)
-            {
-            bool found = false;
-            for (EntityEntry *ee = entities ; ee->value ; ee++)
-                {
-                int p2 = match(p, ee->escaped);
-                if (p2>p)
-                    {
-                    data.push_back(ee->value);
-                    p = p2;
-                    found = true;
-                    break;
-                    }
-                }
-            if (!found)
-                {
-                error("unterminated entity");
-                return -1;
-                }
-            continue;
-            }
-
-        //# NONE OF THE ABOVE
-        data.push_back(ch);
-        p++;
-        }/*while*/
-
-
-    n->value = data;
-    //printf("%d : data:%s\n",p,data.c_str());
-
-    //## Get close tag
-    p = skipwhite(p);
-    ch = peek(p);
-    if (ch != '<')
-        {
-        error("no < for end tag\n");
-        return p0;
-        }
-    p++;
-    ch = peek(p);
-    if (ch != '/')
-        {
-        error("no / on end tag");
-        return p0;
-        }
-    p++;
-    ch = peek(p);
-    p = skipwhite(p);
-    DOMString closeTagName;
-    p = getWord(p, closeTagName);
-    if (openTagName != closeTagName)
-        {
-        error("Mismatched closing tag.  Expected </%S>. Got '%S'.",
-                openTagName.c_str(), closeTagName.c_str());
-        return p0;
-        }
-    p = skipwhite(p);
-    if (peek(p) != '>')
-        {
-        error("no > on end tag for '%s'", closeTagName.c_str());
-        return p0;
-        }
-    p++;
-    // printf("close element:%s\n",closeTagName.c_str());
-    p = skipwhite(p);
-    return p;
-}
-
-
-
-
-Element *Parser::parse(XMLCh *buf,int pos,int len)
-{
-    parselen = len;
-    parsebuf = buf;
-    Element *rootNode = new Element("root");
-    pos = parseVersion(pos);
-    pos = parseDoctype(pos);
-    pos = parseElement(pos, rootNode, 0);
-    return rootNode;
-}
-
-
-Element *Parser::parse(const char *buf, int pos, int len)
-{
-
-    XMLCh *charbuf = (XMLCh *)malloc((len+1) * sizeof(XMLCh));
-    long i = 0;
-    while (i< len)
-        {
-        charbuf[i] = (XMLCh)buf[i];
-        i++;
-        }
-    charbuf[i] = '\0';
-    Element *n = parse(charbuf, 0, len);
-    free(charbuf);
-    return n;
-}
-
-Element *Parser::parse(const DOMString &buf)
-{
-    long len = buf.size();
-    XMLCh *charbuf = (XMLCh *)malloc((len+1) * sizeof(XMLCh));
-    long i = 0;
-    while (i< len)
-        {
-        charbuf[i] = (XMLCh)buf[i];
-        i++;
-        }
-    charbuf[i] = '\0';
-    Element *n = parse(charbuf, 0, len);
-    free(charbuf);
-    return n;
-}
-
-Element *Parser::parseFile(const char *fileName)
-{
-
-    //##### LOAD INTO A CHAR BUF, THEN CONVERT TO XMLCh
-    if (!fileName)
-        return NULL;
-
-    FILE *f = fopen(fileName, "rb");
-    if (!f)
-        return NULL;
-
-    struct stat   statBuf;
-    if (fstat(fileno(f),&statBuf)<0)
-        {
-        fclose(f);
-        return NULL;
-        }
-    long filelen = statBuf.st_size;
-
-    //printf("length:%d\n",filelen);
-    XMLCh *charbuf = (XMLCh *)malloc((filelen+1) * sizeof(XMLCh));
-    for (XMLCh *p=charbuf ; !feof(f) ; p++)
-        {
-        *p = (XMLCh)fgetc(f);
-        }
-    fclose(f);
-    charbuf[filelen] = '\0';
-
-
-    /*
-    printf("nrbytes:%d\n",wc_count);
-    printf("buf:%ls\n======\n",charbuf);
-    */
-    Element *n = parse(charbuf, 0, filelen);
-    free(charbuf);
-    return n;
-}
-
-
-
-
-
-
-
-}//namespace Pedro
-
-#if 0
-//########################################################################
-//#  T E S T
-//########################################################################
-
-bool doTest(char *fileName)
-{
-    Pedro::Parser parser;
-
-    Pedro::Element *elem = parser.parseFile(fileName);
-
-    if (!elem)
-        {
-        printf("Parsing failed\n");
-        return false;
-        }
-
-    elem->print();
-
-    delete elem;
-
-    return true;
-}
-
-
-
-int main(int argc, char **argv)
-{
-    if (argc != 2)
-        {
-        printf("usage: %s <xmlfile>\n", argv[0]);
-        return 1;
-        }
-
-    if (!doTest(argv[1]))
-        return 1;
-
-    return 0;
-}
-
-#endif
-
-//########################################################################
-//#  E N D    O F    F I L E
-//########################################################################
-
-
diff --git a/src/jabber_whiteboard/pedrodom.h b/src/jabber_whiteboard/pedrodom.h
deleted file mode 100644 (file)
index 9c66512..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-#ifndef __PEDRODOM_H__
-#define __PEDRODOM_H__
-/*
- * API for the Pedro mini-DOM parser and tree
- *
- * Authors:
- *   Bob Jamison
- *
- * Copyright (C) 2005-2006 Bob Jamison
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <string>
-#include <vector>
-
-
-namespace Pedro
-{
-
-typedef std::string DOMString;
-typedef unsigned int XMLCh;
-
-
-class Namespace
-{
-public:
-    Namespace()
-        {}
-
-    Namespace(const DOMString &prefixArg, const DOMString &namespaceURIArg)
-        {
-        prefix       = prefixArg;
-        namespaceURI = namespaceURIArg;
-        }
-
-    Namespace(const Namespace &other)
-        {
-        assign(other);
-        }
-
-    Namespace &operator=(const Namespace &other)
-        {
-        assign(other);
-        return *this;
-        }
-
-    virtual ~Namespace()
-        {}
-
-    virtual DOMString getPrefix()
-        { return prefix; }
-
-    virtual DOMString getNamespaceURI()
-        { return namespaceURI; }
-
-protected:
-
-    void assign(const Namespace &other)
-        {
-        prefix       = other.prefix;
-        namespaceURI = other.namespaceURI;
-        }
-
-    DOMString prefix;
-    DOMString namespaceURI;
-
-};
-
-class Attribute
-{
-public:
-    Attribute()
-        {}
-
-    Attribute(const DOMString &nameArg, const DOMString &valueArg)
-        {
-        name  = nameArg;
-        value = valueArg;
-        }
-
-    Attribute(const Attribute &other)
-        {
-        assign(other);
-        }
-
-    Attribute &operator=(const Attribute &other)
-        {
-        assign(other);
-        return *this;
-        }
-
-    virtual ~Attribute()
-        {}
-
-    virtual DOMString getName()
-        { return name; }
-
-    virtual DOMString getValue()
-        { return value; }
-
-protected:
-
-    void assign(const Attribute &other)
-        {
-        name  = other.name;
-        value = other.value;
-        }
-
-    DOMString name;
-    DOMString value;
-
-};
-
-
-class Element
-{
-friend class Parser;
-
-public:
-    Element()
-        {
-        parent = NULL;
-        }
-
-    Element(const DOMString &nameArg)
-        {
-        parent = NULL;
-        name   = nameArg;
-        }
-
-    Element(const DOMString &nameArg, const DOMString &valueArg)
-        {
-        parent = NULL;
-        name   = nameArg;
-        value  = valueArg;
-        }
-
-    Element(const Element &other)
-        {
-        assign(other);
-        }
-
-    Element &operator=(const Element &other)
-        {
-        assign(other);
-        return *this;
-        }
-
-    virtual Element *clone();
-
-    virtual ~Element()
-        {
-        for (unsigned int i=0 ; i<children.size() ; i++)
-            delete children[i];
-        }
-
-    virtual DOMString getName()
-        { return name; }
-
-    virtual DOMString getValue()
-        { return value; }
-
-    Element *getParent()
-        { return parent; }
-
-    std::vector<Element *> getChildren()
-        { return children; }
-
-    std::vector<Element *> findElements(const DOMString &name);
-
-    DOMString getAttribute(const DOMString &name);
-
-    DOMString getTagAttribute(const DOMString &tagName, const DOMString &attrName);
-
-    DOMString getTagValue(const DOMString &tagName);
-
-    void addChild(Element *child);
-
-    void addAttribute(const DOMString &name, const DOMString &value);
-
-    void addNamespace(const DOMString &prefix, const DOMString &namespaceURI);
-
-
-    /**
-     * Prettyprint an XML tree to an output stream.  Elements are indented
-     * according to element hierarchy.
-     * @param f a stream to receive the output
-     * @param elem the element to output
-     */
-    void writeIndented(FILE *f);
-
-    /**
-     * Prettyprint an XML tree to standard output.  This is the equivalent of
-     * writeIndented(stdout).
-     * @param elem the element to output
-     */
-    void print();
-
-protected:
-
-    void assign(const Element &other)
-        {
-        parent     = other.parent;
-        children   = other.children;
-        attributes = other.attributes;
-        namespaces = other.namespaces;
-        name       = other.name;
-        value      = other.value;
-        }
-
-    void findElementsRecursive(std::vector<Element *>&res, const DOMString &name);
-
-    void writeIndentedRecursive(FILE *f, int indent);
-
-    Element *parent;
-
-    std::vector<Element *>children;
-
-    std::vector<Attribute> attributes;
-    std::vector<Namespace> namespaces;
-
-    DOMString name;
-    DOMString value;
-
-};
-
-
-
-
-
-class Parser
-{
-public:
-    /**
-     * Constructor
-     */
-    Parser()
-        { init(); }
-
-    virtual ~Parser()
-        {}
-
-    /**
-     * Parse XML in a char buffer.
-     * @param buf a character buffer to parse
-     * @param pos position to start parsing
-     * @param len number of chars, from pos, to parse.
-     * @return a pointer to the root of the XML document;
-     */
-    Element *parse(const char *buf,int pos,int len);
-
-    /**
-     * Parse XML in a char buffer.
-     * @param buf a character buffer to parse
-     * @param pos position to start parsing
-     * @param len number of chars, from pos, to parse.
-     * @return a pointer to the root of the XML document;
-     */
-    Element *parse(const DOMString &buf);
-
-    /**
-     * Parse a named XML file.  The file is loaded like a data file;
-     * the original format is not preserved.
-     * @param fileName the name of the file to read
-     * @return a pointer to the root of the XML document;
-     */
-    Element *parseFile(const char *fileName);
-
-    /**
-     * Utility method to preprocess a string for XML
-     * output, escaping its entities.
-     * @param str the string to encode
-     */
-    static DOMString encode(const DOMString &str);
-
-
-private:
-
-    void init()
-        {
-        keepGoing       = true;
-        currentNode     = NULL;
-        parselen        = 0;
-        parsebuf        = NULL;
-        currentPosition = 0;
-        }
-
-    void getLineAndColumn(long pos, long *lineNr, long *colNr);
-
-    void error(char *fmt, ...);
-
-    int peek(long pos);
-
-    int match(long pos, const char *text);
-
-    int skipwhite(long p);
-
-    int getWord(int p0, DOMString &buf);
-
-    int getQuoted(int p0, DOMString &buf, int do_i_parse);
-
-    int parseVersion(int p0);
-
-    int parseDoctype(int p0);
-
-    int parseElement(int p0, Element *par,int depth);
-
-    Element *parse(XMLCh *buf,int pos,int len);
-
-    bool       keepGoing;
-    Element    *currentNode;
-    long       parselen;
-    XMLCh      *parsebuf;
-    DOMString  cdatabuf;
-    long       currentPosition;
-    int        colNr;
-
-};
-
-
-
-}//namespace Pedro
-
-
-#endif /* __PEDRODOM_H__ */
-
-//########################################################################
-//#  E N D    O F    F I L E
-//########################################################################
-
diff --git a/src/jabber_whiteboard/pedroxmpp.cpp b/src/jabber_whiteboard/pedroxmpp.cpp
deleted file mode 100644 (file)
index f5ce69e..0000000
+++ /dev/null
@@ -1,4842 +0,0 @@
-/*
- * Implementation the Pedro mini-XMPP client
- *
- * Authors:
- *   Bob Jamison
- *
- * Copyright (C) 2005 Bob Jamison
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-#include <stdio.h>
-#include <stdarg.h>
-
-#include <sys/stat.h>
-
-#include "pedroxmpp.h"
-#include "pedrodom.h"
-
-#ifdef __WIN32__
-
-#include <windows.h>
-
-#else /* UNIX */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-
-#include <pthread.h>
-
-#endif
-
-#ifdef HAVE_SSL
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#endif
-
-
-namespace Pedro
-{
-
-//########################################################################
-//########################################################################
-//### U T I L I T Y
-//########################################################################
-//########################################################################
-
-
-//########################################################################
-//# B A S E    6 4
-//########################################################################
-
-//#################
-//# ENCODER
-//#################
-
-
-static char *base64encode =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-/**
- * This class is for Base-64 encoding
- */
-class Base64Encoder
-{
-
-public:
-
-    Base64Encoder()
-        {
-        reset();
-        }
-
-    virtual ~Base64Encoder()
-        {}
-
-    virtual void reset()
-        {
-        outBuf   = 0L;
-        bitCount = 0;
-        buf = "";
-        }
-
-    virtual void append(int ch);
-
-    virtual void append(char *str);
-
-    virtual void append(unsigned char *str, int len);
-
-    virtual void append(const DOMString &str);
-
-    virtual DOMString finish();
-
-    static DOMString encode(const DOMString &str);
-
-
-private:
-
-
-    unsigned long outBuf;
-
-    int bitCount;
-
-    DOMString buf;
-
-};
-
-
-
-/**
- * Writes the specified byte to the output buffer
- */
-void Base64Encoder::append(int ch)
-{
-    outBuf   <<=  8;
-    outBuf   |=  (ch & 0xff);
-    bitCount +=  8;
-    if (bitCount >= 24)
-        {
-        int indx  = (int)((outBuf & 0x00fc0000L) >> 18);
-        int obyte = (int)base64encode[indx & 63];
-        buf.push_back(obyte);
-
-        indx      = (int)((outBuf & 0x0003f000L) >> 12);
-        obyte     = (int)base64encode[indx & 63];
-        buf.push_back(obyte);
-
-        indx      = (int)((outBuf & 0x00000fc0L) >>  6);
-        obyte     = (int)base64encode[indx & 63];
-        buf.push_back(obyte);
-
-        indx      = (int)((outBuf & 0x0000003fL)      );
-        obyte     = (int)base64encode[indx & 63];
-        buf.push_back(obyte);
-
-        bitCount = 0;
-        outBuf   = 0L;
-        }
-}
-
-/**
- * Writes the specified string to the output buffer
- */
-void Base64Encoder::append(char *str)
-{
-    while (*str)
-        append((int)*str++);
-}
-
-/**
- * Writes the specified string to the output buffer
- */
-void Base64Encoder::append(unsigned char *str, int len)
-{
-    while (len>0)
-        {
-        append((int)*str++);
-        len--;
-        }
-}
-
-/**
- * Writes the specified string to the output buffer
- */
-void Base64Encoder::append(const DOMString &str)
-{
-    append((char *)str.c_str());
-}
-
-/**
- * Closes this output stream and releases any system resources
- * associated with this stream.
- */
-DOMString Base64Encoder::finish()
-{
-    //get any last bytes (1 or 2) out of the buffer
-    if (bitCount == 16)
-        {
-        outBuf <<= 2;  //pad to make 18 bits
-
-        int indx  = (int)((outBuf & 0x0003f000L) >> 12);
-        int obyte = (int)base64encode[indx & 63];
-        buf.push_back(obyte);
-
-        indx      = (int)((outBuf & 0x00000fc0L) >>  6);
-        obyte     = (int)base64encode[indx & 63];
-        buf.push_back(obyte);
-
-        indx      = (int)((outBuf & 0x0000003fL)      );
-        obyte     = (int)base64encode[indx & 63];
-        buf.push_back(obyte);
-
-        buf.push_back('=');
-        }
-    else if (bitCount == 8)
-        {
-        outBuf <<= 4; //pad to make 12 bits
-
-        int indx  = (int)((outBuf & 0x00000fc0L) >>  6);
-        int obyte = (int)base64encode[indx & 63];
-        buf.push_back(obyte);
-
-        indx      = (int)((outBuf & 0x0000003fL)      );
-        obyte     = (int)base64encode[indx & 63];
-        buf.push_back(obyte);
-
-        buf.push_back('=');
-        buf.push_back('=');
-        }
-
-    DOMString ret = buf;
-    reset();
-    return ret;
-}
-
-
-DOMString Base64Encoder::encode(const DOMString &str)
-{
-    Base64Encoder encoder;
-    encoder.append(str);
-    DOMString ret = encoder.finish();
-    return ret;
-}
-
-
-
-//#################
-//# DECODER
-//#################
-
-static int base64decode[] =
-{
-/*00*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-/*08*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-/*10*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-/*18*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-/*20*/    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-/*28*/    -1,   -1,   -1,   62,   -1,   -1,   -1,   63,
-/*30*/    52,   53,   54,   55,   56,   57,   58,   59,
-/*38*/    60,   61,   -1,   -1,   -1,   -1,   -1,   -1,
-/*40*/    -1,    0,    1,    2,    3,    4,    5,    6,
-/*48*/     7,    8,    9,   10,   11,   12,   13,   14,
-/*50*/    15,   16,   17,   18,   19,   20,   21,   22,
-/*58*/    23,   24,   25,   -1,   -1,   -1,   -1,   -1,
-/*60*/    -1,   26,   27,   28,   29,   30,   31,   32,
-/*68*/    33,   34,   35,   36,   37,   38,   39,   40,
-/*70*/    41,   42,   43,   44,   45,   46,   47,   48,
-/*78*/    49,   50,   51,   -1,   -1,   -1,   -1,   -1
-};
-
-class Base64Decoder
-{
-public:
-    Base64Decoder()
-        {
-        reset();
-        }
-
-    virtual ~Base64Decoder()
-        {}
-
-    virtual void reset()
-        {
-        inCount = 0;
-        buf.clear();
-        }
-
-
-    virtual void append(int ch);
-
-    virtual void append(char *str);
-
-    virtual void append(const DOMString &str);
-
-    std::vector<unsigned char> finish();
-
-    static std::vector<unsigned char> decode(const DOMString &str);
-
-    static DOMString decodeToString(const DOMString &str);
-
-private:
-
-    int inBytes[4];
-    int inCount;
-    std::vector<unsigned char> buf;
-};
-
-/**
- * Appends one char to the decoder
- */
-void Base64Decoder::append(int ch)
-{
-    if (isspace(ch))
-        return;
-    else if (ch == '=') //padding
-        {
-        inBytes[inCount++] = 0;
-        }
-    else
-        {
-        int byteVal = base64decode[ch & 0x7f];
-        //printf("char:%c %d\n", ch, byteVal);
-        if (byteVal < 0)
-            {
-            //Bad lookup value
-            }
-        inBytes[inCount++] = byteVal;
-        }
-
-    if (inCount >=4 )
-        {
-        unsigned char b0 = ((inBytes[0]<<2) & 0xfc) | ((inBytes[1]>>4) & 0x03);
-        unsigned char b1 = ((inBytes[1]<<4) & 0xf0) | ((inBytes[2]>>2) & 0x0f);
-        unsigned char b2 = ((inBytes[2]<<6) & 0xc0) | ((inBytes[3]   ) & 0x3f);
-        buf.push_back(b0);
-        buf.push_back(b1);
-        buf.push_back(b2);
-        inCount = 0;
-        }
-
-}
-
-void Base64Decoder::append(char *str)
-{
-    while (*str)
-        append((int)*str++);
-}
-
-void Base64Decoder::append(const DOMString &str)
-{
-    append((char *)str.c_str());
-}
-
-std::vector<unsigned char> Base64Decoder::finish()
-{
-    std::vector<unsigned char> ret = buf;
-    reset();
-    return ret;
-}
-
-std::vector<unsigned char> Base64Decoder::decode(const DOMString &str)
-{
-    Base64Decoder decoder;
-    decoder.append(str);
-    std::vector<unsigned char> ret = decoder.finish();
-    return ret;
-}
-
-DOMString Base64Decoder::decodeToString(const DOMString &str)
-{
-    Base64Decoder decoder;
-    decoder.append(str);
-    std::vector<unsigned char> ret = decoder.finish();
-    DOMString buf;
-    for (unsigned int i=0 ; i<ret.size() ; i++)
-        buf.push_back(ret[i]);
-    return buf;
-}
-
-
-
-//########################################################################
-//# S H A   1
-//########################################################################
-
-class Sha1
-{
-public:
-
-    /**
-     *
-     */
-    Sha1()
-        { init(); }
-
-    /**
-     *
-     */
-    virtual ~Sha1()
-        {}
-
-
-    /**
-     * Static convenience method.  This would be the most commonly used
-     * version;
-     * @parm digest points to a bufer of 20 unsigned chars
-     */
-    static void hash(unsigned char *dataIn, int len, unsigned char *digest);
-
-    /**
-     * Static convenience method.  This will fill a string with the hex
-     * codex string.
-     */
-    static DOMString hashHex(unsigned char *dataIn, int len);
-
-    /**
-     *  Initialize the context (also zeroizes contents)
-     */
-    virtual void init();
-
-    /**
-     *
-     */
-    virtual void append(unsigned char *dataIn, int len);
-
-    /**
-     *
-     * @parm digest points to a bufer of 20 unsigned chars
-     */
-    virtual void finish(unsigned char *digest);
-
-
-private:
-
-    void hashblock();
-
-    unsigned long H[5];
-    unsigned long W[80];
-    unsigned long sizeHi,sizeLo;
-    int lenW;
-
-};
-
-
-
-void Sha1::hash(unsigned char *dataIn, int len, unsigned char *digest)
-{
-    Sha1 sha1;
-    sha1.append(dataIn, len);
-    sha1.finish(digest);
-}
-
-static char *sha1hex = "0123456789abcdef";
-
-DOMString Sha1::hashHex(unsigned char *dataIn, int len)
-{
-    unsigned char hashout[20];
-    hash(dataIn, len, hashout);
-    DOMString ret;
-    for (int i=0 ; i<20 ; i++)
-        {
-        unsigned char ch = hashout[i];
-        ret.push_back(sha1hex[ (ch>>4) & 15 ]);
-        ret.push_back(sha1hex[ ch      & 15 ]);
-        }
-    return ret;
-}
-
-
-void Sha1::init()
-{
-
-    lenW   = 0;
-    sizeHi = 0;
-    sizeLo = 0;
-
-    // Initialize H with the magic constants (see FIPS180 for constants)
-    H[0] = 0x67452301L;
-    H[1] = 0xefcdab89L;
-    H[2] = 0x98badcfeL;
-    H[3] = 0x10325476L;
-    H[4] = 0xc3d2e1f0L;
-
-    for (int i = 0; i < 80; i++)
-        W[i] = 0;
-}
-
-
-void Sha1::append(unsigned char *dataIn, int len)
-{
-    // Read the data into W and process blocks as they get full
-    for (int i = 0; i < len; i++)
-        {
-        W[lenW / 4] <<= 8;
-        W[lenW / 4] |= (unsigned long)dataIn[i];
-        if ((++lenW) % 64 == 0)
-            {
-            hashblock();
-            lenW = 0;
-            }
-        sizeLo += 8;
-        sizeHi += (sizeLo < 8);
-        }
-}
-
-
-void Sha1::finish(unsigned char hashout[20])
-{
-    unsigned char pad0x80 = 0x80;
-    unsigned char pad0x00 = 0x00;
-    unsigned char padlen[8];
-
-    // Pad with a binary 1 (e.g. 0x80), then zeroes, then length
-    padlen[0] = (unsigned char)((sizeHi >> 24) & 255);
-    padlen[1] = (unsigned char)((sizeHi >> 16) & 255);
-    padlen[2] = (unsigned char)((sizeHi >>  8) & 255);
-    padlen[3] = (unsigned char)((sizeHi >>  0) & 255);
-    padlen[4] = (unsigned char)((sizeLo >> 24) & 255);
-    padlen[5] = (unsigned char)((sizeLo >> 16) & 255);
-    padlen[6] = (unsigned char)((sizeLo >>  8) & 255);
-    padlen[7] = (unsigned char)((sizeLo >>  0) & 255);
-
-    append(&pad0x80, 1);
-
-    while (lenW != 56)
-        append(&pad0x00, 1);
-    append(padlen, 8);
-
-    // Output hash
-    for (int i = 0; i < 20; i++)
-        {
-        hashout[i] = (unsigned char)(H[i / 4] >> 24);
-        H[i / 4] <<= 8;
-        }
-
-    // Re-initialize the context (also zeroizes contents)
-    init();
-}
-
-
-#define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL)
-
-void Sha1::hashblock()
-{
-
-    for (int t = 16; t <= 79; t++)
-        W[t] = SHA_ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
-
-    unsigned long A = H[0];
-    unsigned long B = H[1];
-    unsigned long C = H[2];
-    unsigned long D = H[3];
-    unsigned long E = H[4];
-
-    unsigned long TEMP;
-
-    for (int t = 0; t <= 19; t++)
-        {
-        TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) +
-                E + W[t] + 0x5a827999L) & 0xffffffffL;
-        E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
-        }
-    for (int t = 20; t <= 39; t++)
-        {
-        TEMP = (SHA_ROTL(A,5) + (B^C^D) +
-                E + W[t] + 0x6ed9eba1L) & 0xffffffffL;
-        E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
-        }
-    for (int t = 40; t <= 59; t++)
-        {
-        TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) +
-                E + W[t] + 0x8f1bbcdcL) & 0xffffffffL;
-        E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
-        }
-    for (int t = 60; t <= 79; t++)
-        {
-        TEMP = (SHA_ROTL(A,5) + (B^C^D) +
-                E + W[t] + 0xca62c1d6L) & 0xffffffffL;
-        E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
-        }
-
-    H[0] += A;
-    H[1] += B;
-    H[2] += C;
-    H[3] += D;
-    H[4] += E;
-}
-
-
-
-
-
-//########################################################################
-//# M D  5
-//########################################################################
-
-class Md5
-{
-public:
-
-    /**
-     *
-     */
-    Md5()
-        { init(); }
-
-    /**
-     *
-     */
-    virtual ~Md5()
-        {}
-
-    /**
-     * Static convenience method.
-     * @parm digest points to an buffer of 16 unsigned chars
-     */
-    static void hash(unsigned char *dataIn,
-                     unsigned long len, unsigned char *digest);
-
-    static DOMString Md5::hashHex(unsigned char *dataIn, unsigned long len);
-
-    /**
-     *  Initialize the context (also zeroizes contents)
-     */
-    virtual void init();
-
-    /**
-     *
-     */
-    virtual void append(unsigned char *dataIn, unsigned long len);
-
-    /**
-     *
-     */
-    virtual void append(const DOMString &str);
-
-    /**
-     * Finalize and output the hash.
-     * @parm digest points to an buffer of 16 unsigned chars
-     */
-    virtual void finish(unsigned char *digest);
-
-
-    /**
-     * Same as above , but hex to an output String
-     */
-    virtual DOMString finishHex();
-
-private:
-
-    void transform(unsigned long *buf, unsigned long *in);
-
-    unsigned long buf[4];
-    unsigned long bits[2];
-    unsigned char in[64];
-
-};
-
-
-
-
-void Md5::hash(unsigned char *dataIn, unsigned long len, unsigned char *digest)
-{
-    Md5 md5;
-    md5.append(dataIn, len);
-    md5.finish(digest);
-}
-
-DOMString Md5::hashHex(unsigned char *dataIn, unsigned long len)
-{
-    Md5 md5;
-    md5.append(dataIn, len);
-    DOMString ret = md5.finishHex();
-    return ret;
-}
-
-
-
-/*
- * Note: this code is harmless on little-endian machines.
- */
-/*
-static void byteReverse(unsigned char *buf, unsigned long longs)
-{
-    do
-        {
-        unsigned long t = (unsigned long)
-            ((unsigned) buf[3] << 8 | buf[2]) << 16 |
-            ((unsigned) buf[1] << 8 | buf[0]);
-        *(unsigned long *) buf = t;
-        buf += 4;
-        } while (--longs);
-}
-*/
-
-static void md5_memcpy(void *dest, void *src, int n)
-{
-    unsigned char *s1 = (unsigned char *)dest;
-    unsigned char *s2 = (unsigned char *)src;
-    while (n--)
-        *s1++ = *s2++;
-}
-
-static void md5_memset(void *dest, char v, int n)
-{
-    unsigned char *s = (unsigned char *)dest;
-    while (n--)
-        *s++ = v;
-}
-
-/**
- * Initialize MD5 polynomials and storage
- */
-void Md5::init()
-{
-    buf[0]  = 0x67452301;
-    buf[1]  = 0xefcdab89;
-    buf[2]  = 0x98badcfe;
-    buf[3]  = 0x10325476;
-
-    bits[0] = 0;
-    bits[1] = 0;
-}
-
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-void Md5::append(unsigned char *source, unsigned long len)
-{
-
-    // Update bitcount
-    unsigned long t = bits[0];
-    if ((bits[0] = t + ((unsigned long) len << 3)) < t)
-           bits[1]++;// Carry from low to high
-    bits[1] += len >> 29;
-
-       //Bytes already in shsInfo->data
-    t = (t >> 3) & 0x3f;
-
-
-    // Handle any leading odd-sized chunks
-    if (t)
-        {
-        unsigned char *p = (unsigned char *) in + t;
-        t = 64 - t;
-        if (len < t)
-            {
-            md5_memcpy(p, source, len);
-            return;
-            }
-        md5_memcpy(p, source, t);
-        //byteReverse(in, 16);
-        transform(buf, (unsigned long *) in);
-        source += t;
-        len    -= t;
-        }
-
-    // Process data in 64-byte chunks
-    while (len >= 64)
-        {
-        md5_memcpy(in, source, 64);
-        //byteReverse(in, 16);
-        transform(buf, (unsigned long *) in);
-        source += 64;
-        len    -= 64;
-        }
-
-    // Handle any remaining bytes of data.
-    md5_memcpy(in, source, len);
-}
-
-/*
- * Update context to reflect the concatenation of another string
- */
-void Md5::append(const DOMString &str)
-{
-    append((unsigned char *)str.c_str(), str.size());
-}
-
-/*
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-void Md5::finish(unsigned char *digest)
-{
-    // Compute number of bytes mod 64
-    unsigned int count = (bits[0] >> 3) & 0x3F;
-
-    // Set the first char of padding to 0x80.
-    // This is safe since there is always at least one byte free
-    unsigned char *p = in + count;
-    *p++ = 0x80;
-
-    // Bytes of padding needed to make 64 bytes
-    count = 64 - 1 - count;
-
-    // Pad out to 56 mod 64
-    if (count < 8)
-        {
-           // Two lots of padding:  Pad the first block to 64 bytes
-           md5_memset(p, 0, count);
-           //byteReverse(in, 16);
-           transform(buf, (unsigned long *) in);
-
-           // Now fill the next block with 56 bytes
-           md5_memset(in, 0, 56);
-        }
-    else
-        {
-        // Pad block to 56 bytes
-        md5_memset(p, 0, count - 8);
-        }
-    //byteReverse(in, 14);
-
-    // Append length in bits and transform
-    ((unsigned long *) in)[14] = bits[0];
-    ((unsigned long *) in)[15] = bits[1];
-
-    transform(buf, (unsigned long *) in);
-    //byteReverse((unsigned char *) buf, 4);
-    md5_memcpy(digest, buf, 16);
-    init();  // Security!  ;-)
-}
-
-static char *md5hex = "0123456789abcdef";
-
-DOMString Md5::finishHex()
-{
-    unsigned char hashout[16];
-    finish(hashout);
-    DOMString ret;
-    for (int i=0 ; i<16 ; i++)
-        {
-        unsigned char ch = hashout[i];
-        ret.push_back(md5hex[ (ch>>4) & 15 ]);
-        ret.push_back(md5hex[ ch      & 15 ]);
-        }
-    return ret;
-}
-
-
-
-//#  The four core functions - F1 is optimized somewhat
-
-//  #define F1(x, y, z) (x & y | ~x & z)
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-// ## This is the central step in the MD5 algorithm.
-#define MD5STEP(f, w, x, y, z, data, s) \
-       ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data.  MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- * @parm buf points to an array of 4 unsigned longs
- * @parm in points to an array of 16 unsigned longs
- */
-void Md5::transform(unsigned long *buf, unsigned long *in)
-{
-    unsigned long a = buf[0];
-    unsigned long b = buf[1];
-    unsigned long c = buf[2];
-    unsigned long d = buf[3];
-
-    MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
-    MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
-    MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
-    MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
-    MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
-    MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
-    MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
-    MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
-    MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
-    MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
-    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
-    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
-    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
-    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
-    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
-    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
-    MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
-    MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
-    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
-    MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
-    MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
-    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
-    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
-    MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
-    MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
-    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
-    MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
-    MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
-    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
-    MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
-    MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
-    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
-    MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
-    MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
-    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
-    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
-    MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
-    MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
-    MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
-    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
-    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
-    MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
-    MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
-    MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
-    MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
-    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
-    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
-    MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23);
-
-    MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
-    MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10);
-    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
-    MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21);
-    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
-    MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10);
-    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
-    MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21);
-    MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f,  6);
-    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
-    MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15);
-    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
-    MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82,  6);
-    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
-    MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15);
-    MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21);
-
-    buf[0] += a;
-    buf[1] += b;
-    buf[2] += c;
-    buf[3] += d;
-}
-
-
-
-
-
-
-
-//########################################################################
-//########################################################################
-//### T H R E A D
-//########################################################################
-//########################################################################
-
-
-//########################################################################
-//### T H R E A D
-//########################################################################
-
-/**
- * This is the interface for a delegate class which can
- * be run by a Thread.
- * Thread thread(runnable);
- * thread.start();
- */
-class Runnable
-{
-public:
-
-    Runnable()
-        {}
-    virtual ~Runnable()
-        {}
-
-    /**
-     * The method of a delegate class which can
-     * be run by a Thread.  Thread is completed when this
-     * method is done.
-     */
-    virtual void run() = 0;
-
-};
-
-
-
-/**
- *  A simple wrapper of native threads in a portable class.
- *  It can be used either to execute its own run() method, or
- *  delegate to a Runnable class's run() method.
- */
-class Thread
-{
-public:
-
-    /**
-     *  Create a thread which will execute its own run() method.
-     */
-    Thread()
-        { runnable = NULL ; started = false; }
-
-    /**
-     * Create a thread which will run a Runnable class's run() method.
-     */
-    Thread(const Runnable &runner)
-        { runnable = (Runnable *)&runner; started = false; }
-
-    /**
-     *  This does not kill a spawned thread.
-     */
-    virtual ~Thread()
-        {}
-
-    /**
-     *  Static method to pause the current thread for a given
-     *  number of milliseconds.
-     */
-    static void sleep(unsigned long millis);
-
-    /**
-     *  This method will be executed if the Thread was created with
-     *  no delegated Runnable class.  The thread is completed when
-     *  the method is done.
-     */
-    virtual void run()
-        {}
-
-    /**
-     *  Starts the thread.
-     */
-    virtual void start();
-
-    /**
-     *  Calls either this class's run() method, or that of a Runnable.
-     *  A user would normally not call this directly.
-     */
-    virtual void execute()
-        {
-        started = true;
-        if (runnable)
-            runnable->run();
-        else
-            run();
-        }
-
-private:
-
-    Runnable *runnable;
-
-    bool started;
-
-};
-
-
-
-
-
-#ifdef __WIN32__
-
-
-static DWORD WINAPI WinThreadFunction(LPVOID context)
-{
-    Thread *thread = (Thread *)context;
-    thread->execute();
-    return 0;
-}
-
-
-void Thread::start()
-{
-    DWORD dwThreadId;
-    HANDLE hThread = CreateThread(NULL, 0, WinThreadFunction,
-               (LPVOID)this,  0,  &dwThreadId);
-    //Make sure the thread is started before 'this' is deallocated
-    while (!started)
-        sleep(10);
-    CloseHandle(hThread);
-}
-
-void Thread::sleep(unsigned long millis)
-{
-    Sleep(millis);
-}
-
-#else /* UNIX */
-
-
-void *PthreadThreadFunction(void *context)
-{
-    Thread *thread = (Thread *)context;
-    thread->execute();
-    return NULL;
-}
-
-
-void Thread::start()
-{
-    pthread_t thread;
-
-    int ret = pthread_create(&thread, NULL,
-            PthreadThreadFunction, (void *)this);
-    if (ret != 0)
-        printf("Thread::start: thread creation failed: %s\n", strerror(ret));
-
-    //Make sure the thread is started before 'this' is deallocated
-    while (!started)
-        sleep(10);
-
-}
-
-void Thread::sleep(unsigned long millis)
-{
-    timespec requested;
-    requested.tv_sec = millis / 1000;
-    requested.tv_nsec = (millis % 1000 ) * 1000000L;
-    nanosleep(&requested, NULL);
-}
-
-#endif
-
-
-//########################################################################
-//########################################################################
-//### S O C K E T
-//########################################################################
-//########################################################################
-
-
-
-
-
-class TcpSocket
-{
-public:
-
-    TcpSocket();
-
-    TcpSocket(const std::string &hostname, int port);
-
-    TcpSocket(const char *hostname, int port);
-
-    TcpSocket(const TcpSocket &other);
-
-    virtual ~TcpSocket();
-
-    bool isConnected();
-
-    void enableSSL(bool val);
-
-    bool connect(const std::string &hostname, int portno);
-
-    bool connect(const char *hostname, int portno);
-
-    bool startTls();
-
-    bool connect();
-
-    bool disconnect();
-
-    bool setReceiveTimeout(unsigned long millis);
-
-    long available();
-
-    bool write(int ch);
-
-    bool write(char *str);
-
-    bool write(const std::string &str);
-
-    int read();
-
-    std::string readLine();
-
-private:
-    void init();
-
-    std::string hostname;
-    int  portno;
-    int  sock;
-    bool connected;
-
-    bool sslEnabled;
-
-    unsigned long receiveTimeout;
-
-#ifdef HAVE_SSL
-    SSL_CTX *sslContext;
-    SSL *sslStream;
-#endif
-
-};
-
-
-
-//#########################################################################
-//# U T I L I T Y
-//#########################################################################
-
-static void mybzero(void *s, size_t n)
-{
-    unsigned char *p = (unsigned char *)s;
-    while (n > 0)
-        {
-        *p++ = (unsigned char)0;
-        n--;
-        }
-}
-
-static void mybcopy(void *src, void *dest, size_t n)
-{
-    unsigned char *p = (unsigned char *)dest;
-    unsigned char *q = (unsigned char *)src;
-    while (n > 0)
-        {
-        *p++ = *q++;
-        n--;
-        }
-}
-
-
-
-//#########################################################################
-//# T C P    C O N N E C T I O N
-//#########################################################################
-
-TcpSocket::TcpSocket()
-{
-    init();
-}
-
-
-TcpSocket::TcpSocket(const char *hostnameArg, int port)
-{
-    init();
-    hostname  = hostnameArg;
-    portno    = port;
-}
-
-TcpSocket::TcpSocket(const std::string &hostnameArg, int port)
-{
-    init();
-    hostname  = hostnameArg;
-    portno    = port;
-}
-
-
-#ifdef HAVE_SSL
-
-static void cryptoLockCallback(int mode, int type, const char *file, int line)
-{
-    //printf("########### LOCK\n");
-    static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
-    const char *errstr = NULL;
-
-    int rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
-    if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
-        {
-        errstr = "invalid mode";
-        goto err;
-        }
-
-    if (type < 0 || type >= CRYPTO_NUM_LOCKS)
-        {
-        errstr = "type out of bounds";
-        goto err;
-        }
-
-    if (mode & CRYPTO_LOCK)
-        {
-        if (modes[type])
-            {
-            errstr = "already locked";
-            /* must not happen in a single-threaded program
-             * (would deadlock)
-             */
-            goto err;
-            }
-
-        modes[type] = rw;
-        }
-    else if (mode & CRYPTO_UNLOCK)
-        {
-        if (!modes[type])
-            {
-             errstr = "not locked";
-             goto err;
-             }
-
-        if (modes[type] != rw)
-            {
-            errstr = (rw == CRYPTO_READ) ?
-                  "CRYPTO_r_unlock on write lock" :
-                  "CRYPTO_w_unlock on read lock";
-            }
-
-        modes[type] = 0;
-        }
-    else
-        {
-        errstr = "invalid mode";
-        goto err;
-        }
-
-    err:
-    if (errstr)
-        {
-        /* we cannot use bio_err here */
-        fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
-                errstr, mode, type, file, line);
-        }
-}
-
-static unsigned long cryptoIdCallback()
-{
-#ifdef __WIN32__
-    unsigned long ret = (unsigned long) GetCurrentThreadId();
-#else
-    unsigned long ret = (unsigned long) pthread_self();
-#endif
-    return ret;
-}
-
-#endif
-
-
-TcpSocket::TcpSocket(const TcpSocket &other)
-{
-    init();
-    sock      = other.sock;
-    hostname  = other.hostname;
-    portno    = other.portno;
-}
-
-static bool tcp_socket_inited = false;
-
-void TcpSocket::init()
-{
-    if (!tcp_socket_inited)
-        {
-#ifdef __WIN32__
-        WORD wVersionRequested = MAKEWORD( 2, 2 );
-        WSADATA wsaData;
-        WSAStartup( wVersionRequested, &wsaData );
-#endif
-#ifdef HAVE_SSL
-        sslStream  = NULL;
-        sslContext = NULL;
-           CRYPTO_set_locking_callback(cryptoLockCallback);
-        CRYPTO_set_id_callback(cryptoIdCallback);
-        SSL_library_init();
-        SSL_load_error_strings();
-#endif
-        tcp_socket_inited = true;
-        }
-    sock           = -1;
-    connected      = false;
-    hostname       = "";
-    portno         = -1;
-    sslEnabled     = false;
-    receiveTimeout = 0;
-}
-
-TcpSocket::~TcpSocket()
-{
-    disconnect();
-}
-
-bool TcpSocket::isConnected()
-{
-    if (!connected || sock < 0)
-        return false;
-    return true;
-}
-
-void TcpSocket::enableSSL(bool val)
-{
-    sslEnabled = val;
-}
-
-
-bool TcpSocket::connect(const char *hostnameArg, int portnoArg)
-{
-    hostname = hostnameArg;
-    portno   = portnoArg;
-    return connect();
-}
-
-bool TcpSocket::connect(const std::string &hostnameArg, int portnoArg)
-{
-    hostname = hostnameArg;
-    portno   = portnoArg;
-    return connect();
-}
-
-
-
-#ifdef HAVE_SSL
-/*
-static int password_cb(char *buf, int bufLen, int rwflag, void *userdata)
-{
-    char *password = "password";
-    if (bufLen < (int)(strlen(password)+1))
-        return 0;
-
-    strcpy(buf,password);
-    int ret = strlen(password);
-    return ret;
-}
-
-static void infoCallback(const SSL *ssl, int where, int ret)
-{
-    switch (where)
-        {
-        case SSL_CB_ALERT:
-            {
-            printf("## %d SSL ALERT: %s\n",  where, SSL_alert_desc_string_long(ret));
-            break;
-            }
-        default:
-            {
-            printf("## %d SSL: %s\n",  where, SSL_state_string_long(ssl));
-            break;
-            }
-        }
-}
-*/
-#endif
-
-
-bool TcpSocket::startTls()
-{
-#ifdef HAVE_SSL
-    sslStream  = NULL;
-    sslContext = NULL;
-
-    //SSL_METHOD *meth = SSLv23_method();
-    //SSL_METHOD *meth = SSLv3_client_method();
-    SSL_METHOD *meth = TLSv1_client_method();
-    sslContext = SSL_CTX_new(meth);
-    //SSL_CTX_set_info_callback(sslContext, infoCallback);
-
-#if 0
-    char *keyFile  = "client.pem";
-    char *caList   = "root.pem";
-    /* Load our keys and certificates*/
-    if (!(SSL_CTX_use_certificate_chain_file(sslContext, keyFile)))
-        {
-        fprintf(stderr, "Can't read certificate file\n");
-        disconnect();
-        return false;
-        }
-
-    SSL_CTX_set_default_passwd_cb(sslContext, password_cb);
-
-    if (!(SSL_CTX_use_PrivateKey_file(sslContext, keyFile, SSL_FILETYPE_PEM)))
-        {
-        fprintf(stderr, "Can't read key file\n");
-        disconnect();
-        return false;
-        }
-
-    /* Load the CAs we trust*/
-    if (!(SSL_CTX_load_verify_locations(sslContext, caList, 0)))
-        {
-        fprintf(stderr, "Can't read CA list\n");
-        disconnect();
-        return false;
-        }
-#endif
-
-    /* Connect the SSL socket */
-    sslStream  = SSL_new(sslContext);
-    SSL_set_fd(sslStream, sock);
-
-    if (SSL_connect(sslStream)<=0)
-        {
-        fprintf(stderr, "SSL connect error\n");
-        disconnect();
-        return false;
-        }
-
-    sslEnabled = true;
-#endif /*HAVE_SSL*/
-    return true;
-}
-
-
-bool TcpSocket::connect()
-{
-    if (hostname.size()<1)
-        {
-        printf("open: null hostname\n");
-        return false;
-        }
-
-    if (portno<1)
-        {
-        printf("open: bad port number\n");
-        return false;
-        }
-
-    sock = socket(PF_INET, SOCK_STREAM, 0);
-    if (sock < 0)
-        {
-        printf("open: error creating socket\n");
-        return false;
-        }
-
-    char *c_hostname = (char *)hostname.c_str();
-    struct hostent *server = gethostbyname(c_hostname);
-    if (!server)
-        {
-        printf("open: could not locate host '%s'\n", c_hostname);
-        return false;
-        }
-
-    struct sockaddr_in serv_addr;
-    mybzero((char *) &serv_addr, sizeof(serv_addr));
-    serv_addr.sin_family = AF_INET;
-    mybcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
-         server->h_length);
-    serv_addr.sin_port = htons(portno);
-
-    int ret = ::connect(sock, (const sockaddr *)&serv_addr, sizeof(serv_addr));
-    if (ret < 0)
-        {
-        printf("open: could not connect to host '%s'\n", c_hostname);
-        return false;
-        }
-
-     if (sslEnabled)
-        {
-        if (!startTls())
-            return false;
-        }
-    connected = true;
-    return true;
-}
-
-bool TcpSocket::disconnect()
-{
-    bool ret  = true;
-    connected = false;
-#ifdef HAVE_SSL
-    if (sslEnabled)
-        {
-        if (sslStream)
-            {
-            int r = SSL_shutdown(sslStream);
-            switch(r)
-                {
-                case 1:
-                    break; /* Success */
-                case 0:
-                case -1:
-                default:
-                    //printf("Shutdown failed");
-                    ret = false;
-                }
-            SSL_free(sslStream);
-            }
-        if (sslContext)
-            SSL_CTX_free(sslContext);
-        }
-    sslStream  = NULL;
-    sslContext = NULL;
-#endif /*HAVE_SSL*/
-
-#ifdef __WIN32__
-    closesocket(sock);
-#else
-    ::close(sock);
-#endif
-    sock = -1;
-    sslEnabled = false;
-
-    return ret;
-}
-
-
-
-bool TcpSocket::setReceiveTimeout(unsigned long millis)
-{
-    receiveTimeout = millis;
-    return true;
-}
-
-/**
- * For normal sockets, return the number of bytes waiting to be received.
- * For SSL, just return >0 when something is ready to be read.
- */
-long TcpSocket::available()
-{
-    if (!isConnected())
-        return -1;
-
-    long count = 0;
-#ifdef __WIN32__
-    if (ioctlsocket(sock, FIONREAD, (unsigned long *)&count) != 0)
-        return -1;
-#else
-    if (ioctl(sock, FIONREAD, &count) != 0)
-        return -1;
-#endif
-    if (count<=0 && sslEnabled)
-        {
-#ifdef HAVE_SSL
-        return SSL_pending(sslStream);
-#endif
-        }
-    return count;
-}
-
-
-
-bool TcpSocket::write(int ch)
-{
-    if (!isConnected())
-        {
-        printf("write: socket closed\n");
-        return false;
-        }
-    unsigned char c = (unsigned char)ch;
-
-    if (sslEnabled)
-        {
-#ifdef HAVE_SSL
-        int r = SSL_write(sslStream, &c, 1);
-        if (r<=0)
-            {
-            switch(SSL_get_error(sslStream, r))
-                {
-                default:
-                    printf("SSL write problem");
-                    return -1;
-                }
-            }
-#endif
-        }
-    else
-        {
-        if (send(sock, (const char *)&c, 1, 0) < 0)
-        //if (send(sock, &c, 1, 0) < 0)
-            {
-            printf("write: could not send data\n");
-            return false;
-            }
-        }
-    return true;
-}
-
-bool TcpSocket::write(char *str)
-{
-   if (!isConnected())
-        {
-        printf("write(str): socket closed\n");
-        return false;
-        }
-    int len = strlen(str);
-
-    if (sslEnabled)
-        {
-#ifdef HAVE_SSL
-        int r = SSL_write(sslStream, (unsigned char *)str, len);
-        if (r<=0)
-            {
-            switch(SSL_get_error(sslStream, r))
-                {
-                default:
-                    printf("SSL write problem");
-                    return -1;
-                }
-            }
-#endif
-        }
-    else
-        {
-        if (send(sock, str, len, 0) < 0)
-        //if (send(sock, &c, 1, 0) < 0)
-            {
-            printf("write: could not send data\n");
-            return false;
-            }
-        }
-    return true;
-}
-
-bool TcpSocket::write(const std::string &str)
-{
-    return write((char *)str.c_str());
-}
-
-int TcpSocket::read()
-{
-    if (!isConnected())
-        return -1;
-
-    //We'll use this loop for timeouts, so that SSL and plain sockets
-    //will behave the same way
-    if (receiveTimeout > 0)
-        {
-        unsigned long tim = 0;
-        while (true)
-            {
-            int avail = available();
-            if (avail > 0)
-                break;
-            if (tim >= receiveTimeout)
-                return -2;
-            Thread::sleep(20);
-            tim += 20;
-            }
-        }
-
-    //check again
-    if (!isConnected())
-        return -1;
-
-    unsigned char ch;
-    if (sslEnabled)
-        {
-#ifdef HAVE_SSL
-        if (!sslStream)
-            return -1;
-        int r = SSL_read(sslStream, &ch, 1);
-        unsigned long err = SSL_get_error(sslStream, r);
-        switch (err)
-            {
-            case SSL_ERROR_NONE:
-                 break;
-            case SSL_ERROR_ZERO_RETURN:
-                return -1;
-            case SSL_ERROR_SYSCALL:
-                printf("SSL read problem(syscall) %s\n",
-                     ERR_error_string(ERR_get_error(), NULL));
-                return -1;
-            default:
-                printf("SSL read problem %s\n",
-                     ERR_error_string(ERR_get_error(), NULL));
-                return -1;
-            }
-#endif
-        }
-    else
-        {
-        if (recv(sock, (char *)&ch, 1, 0) <= 0)
-            {
-            printf("read: could not receive data\n");
-            disconnect();
-            return -1;
-            }
-        }
-    return (int)ch;
-}
-
-std::string TcpSocket::readLine()
-{
-    std::string ret;
-
-    while (isConnected())
-        {
-        int ch = read();
-        if (ch<0)
-            return ret;
-        if (ch=='\r' || ch=='\n')
-            return ret;
-        ret.push_back((char)ch);
-        }
-
-    return ret;
-}
-
-
-//########################################################################
-//########################################################################
-//### X M P P
-//########################################################################
-//########################################################################
-
-
-
-
-//########################################################################
-//# X M P P    E V E N T
-//########################################################################
-
-
-XmppEvent::XmppEvent(int type)
-{
-    eventType = type;
-    presence  = false;
-    dom       = NULL;
-}
-
-XmppEvent::XmppEvent(const XmppEvent &other)
-{
-    assign(other);
-}
-
-XmppEvent &XmppEvent::operator=(const XmppEvent &other)
-{
-    assign(other);
-    return (*this);
-}
-
-XmppEvent::~XmppEvent()
-{
-    if (dom)
-        delete dom;
-}
-
-void XmppEvent::assign(const XmppEvent &other)
-{
-    eventType = other.eventType;
-    presence  = other.presence;
-    status    = other.status;
-    show      = other.show;
-    to        = other.to;
-    from      = other.from;
-    group     = other.group;
-    data      = other.data;
-    fileName  = other.fileName;
-    fileDesc  = other.fileDesc;
-    fileSize  = other.fileSize;
-    fileHash  = other.fileHash;
-    setDOM(other.dom);
-}
-
-int XmppEvent::getType() const
-{
-    return eventType;
-}
-
-DOMString XmppEvent::getIqId() const
-{
-    return iqId;
-}
-
-void XmppEvent::setIqId(const DOMString &val)
-{
-    iqId = val;
-}
-
-DOMString XmppEvent::getStreamId() const
-{
-    return streamId;
-}
-
-void XmppEvent::setStreamId(const DOMString &val)
-{
-    streamId = val;
-}
-
-bool XmppEvent::getPresence() const
-{
-    return presence;
-}
-
-void XmppEvent::setPresence(bool val)
-{
-    presence = val;
-}
-
-DOMString XmppEvent::getShow() const
-{
-    return show;
-}
-
-void XmppEvent::setShow(const DOMString &val)
-{
-    show = val;
-}
-
-DOMString XmppEvent::getStatus() const
-{
-    return status;
-}
-
-void XmppEvent::setStatus(const DOMString &val)
-{
-    status = val;
-}
-
-DOMString XmppEvent::getTo() const
-{
-    return to;
-}
-
-void XmppEvent::setTo(const DOMString &val)
-{
-    to = val;
-}
-
-DOMString XmppEvent::getFrom() const
-{
-    return from;
-}
-
-void XmppEvent::setFrom(const DOMString &val)
-{
-    from = val;
-}
-
-DOMString XmppEvent::getGroup() const
-{
-    return group;
-}
-
-void XmppEvent::setGroup(const DOMString &val)
-{
-    group = val;
-}
-
-DOMString XmppEvent::getData() const
-{
-    return data;
-}
-
-void XmppEvent::setData(const DOMString &val)
-{
-    data = val;
-}
-
-DOMString XmppEvent::getFileName() const
-{
-    return fileName;
-}
-
-void XmppEvent::setFileName(const DOMString &val)
-{
-    fileName = val;
-}
-
-DOMString XmppEvent::getFileDesc() const
-{
-    return fileDesc;
-}
-
-void XmppEvent::setFileDesc(const DOMString &val)
-{
-    fileDesc = val;
-}
-
-long XmppEvent::getFileSize() const
-{
-    return fileSize;
-}
-
-void XmppEvent::setFileSize(long val)
-{
-    fileSize = val;
-}
-
-DOMString XmppEvent::getFileHash() const
-{
-    return fileHash;
-}
-
-void XmppEvent::setFileHash(const DOMString &val)
-{
-    fileHash = val;
-}
-
-Element *XmppEvent::getDOM() const
-{
-    return dom;
-}
-
-void XmppEvent::setDOM(const Element *val)
-{
-    if (!val)
-        dom = NULL;
-    else
-        dom = ((Element *)val)->clone();
-}
-
-
-std::vector<XmppUser> XmppEvent::getUserList() const
-{
-    return userList;
-}
-
-void XmppEvent::setUserList(const std::vector<XmppUser> &val)
-{
-    userList = val;
-}
-
-//########################################################################
-//# X M P P    E V E N T    T A R G E T
-//########################################################################
-
-//###########################
-//# CONSTRUCTORS
-//###########################
-
-XmppEventTarget::XmppEventTarget()
-{
-    eventQueueEnabled = false;
-}
-
-
-XmppEventTarget::XmppEventTarget(const XmppEventTarget &other)
-{
-    listeners         = other.listeners;
-    eventQueueEnabled = other.eventQueueEnabled;
-}
-
-XmppEventTarget::~XmppEventTarget()
-{
-}
-
-
-//###########################
-//# M E S S A G E S
-//###########################
-
-void XmppEventTarget::error(char *fmt, ...)
-{
-    va_list args;
-    va_start(args,fmt);
-    vsnprintf(targetWriteBuf, targetWriteBufLen, fmt, args);
-    va_end(args) ;
-    printf("Error:%s\n", targetWriteBuf);
-    XmppEvent evt(XmppEvent::EVENT_ERROR);
-    evt.setData(targetWriteBuf);
-    dispatchXmppEvent(evt);
-}
-
-void XmppEventTarget::status(char *fmt, ...)
-{
-    va_list args;
-    va_start(args,fmt);
-    vsnprintf(targetWriteBuf, targetWriteBufLen, fmt, args);
-    va_end(args) ;
-    //printf("Status:%s\n", targetWriteBuf);
-    XmppEvent evt(XmppEvent::EVENT_STATUS);
-    evt.setData(targetWriteBuf);
-    dispatchXmppEvent(evt);
-}
-
-
-
-//###########################
-//# L I S T E N E R S
-//###########################
-
-void XmppEventTarget::dispatchXmppEvent(const XmppEvent &event)
-{
-    std::vector<XmppEventListener *>::iterator iter;
-    for (iter = listeners.begin(); iter != listeners.end() ; iter++)
-        (*iter)->processXmppEvent(event);
-    if (eventQueueEnabled)
-        eventQueue.push_back(event);
-}
-
-void XmppEventTarget::addXmppEventListener(const XmppEventListener &listener)
-{
-    XmppEventListener *lsnr = (XmppEventListener *)&listener;
-    std::vector<XmppEventListener *>::iterator iter;
-    for (iter = listeners.begin(); iter != listeners.end() ; iter++)
-        if (*iter == lsnr)
-            return;
-    listeners.push_back(lsnr);
-}
-
-void XmppEventTarget::removeXmppEventListener(const XmppEventListener &listener)
-{
-    XmppEventListener *lsnr = (XmppEventListener *)&listener;
-    std::vector<XmppEventListener *>::iterator iter;
-    for (iter = listeners.begin(); iter != listeners.end() ; iter++)
-        if (*iter == lsnr)
-            listeners.erase(iter);
-}
-
-void XmppEventTarget::clearXmppEventListeners()
-{
-    listeners.clear();
-}
-
-
-//###########################
-//# E V E N T    Q U E U E
-//###########################
-
-void XmppEventTarget::eventQueueEnable(bool val)
-{
-    eventQueueEnabled = val;
-    if (!eventQueueEnabled)
-        eventQueue.clear();
-}
-
-int XmppEventTarget::eventQueueAvailable()
-{
-    return eventQueue.size();
-}
-
-XmppEvent XmppEventTarget::eventQueuePop()
-{
-    if (!eventQueueEnabled || eventQueue.size()<1)
-        {
-        XmppEvent dummy(XmppEvent::EVENT_NONE);
-        return dummy;
-        }
-    XmppEvent event = *(eventQueue.begin());
-    eventQueue.erase(eventQueue.begin());
-    return event;
-}
-
-
-//########################################################################
-//# X M P P    S T R E A M
-//########################################################################
-
-/**
- *
- */
-class XmppStream
-{
-public:
-
-    /**
-     *
-     */
-    XmppStream();
-
-    /**
-     *
-     */
-    virtual ~XmppStream();
-
-    /**
-     *
-     */
-    virtual void reset();
-
-    /**
-     *
-     */
-    virtual int getState();
-
-    /**
-     *
-     */
-    virtual void setState(int val);
-
-    /**
-     *
-     */
-    virtual DOMString getStreamId();
-
-    /**
-     *
-     */
-    void setStreamId(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual DOMString getIqId();
-
-    /**
-     *
-     */
-    void setIqId(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual int getSeqNr();
-
-    /**
-     *
-     */
-    virtual DOMString getPeerId();
-
-    /**
-     *
-     */
-    virtual void setPeerId(const DOMString &val);
-
-    /**
-     *
-     */
-    int available();
-
-    /**
-     *
-     */
-    void receiveData(std::vector<unsigned char> &newData);
-
-    /**
-     *
-     */
-    std::vector<unsigned char> read();
-
-private:
-
-
-    DOMString streamId;
-
-    DOMString iqId;
-
-    DOMString sourceId;
-
-    int state;
-
-    long seqNr;
-
-    std::vector<unsigned char> data;
-};
-
-
-/**
- *
- */
-XmppStream::XmppStream()
-{
-    reset();
-}
-
-/**
- *
- */
-XmppStream::~XmppStream()
-{
-    reset();
-}
-
-/**
- *
- */
-void XmppStream::reset()
-{
-    state = XmppClient::STREAM_AVAILABLE;
-    seqNr = 0;
-    data.clear();
-}
-
-/**
- *
- */
-int XmppStream::getState()
-{
-    return state;
-}
-
-/**
- *
- */
-void XmppStream::setState(int val)
-{
-    state = val;
-}
-
-/**
- *
- */
-DOMString XmppStream::getStreamId()
-{
-    return streamId;
-}
-
-/**
- *
- */
-void XmppStream::setStreamId(const DOMString &val)
-{
-    streamId = val;
-}
-
-/**
- *
- */
-DOMString XmppStream::getIqId()
-{
-    return iqId;
-}
-
-
-/**
- *
- */
-void XmppStream::setIqId(const DOMString &val)
-{
-    iqId = val;
-}
-
-/**
- *  Source or destination JID
- */
-void XmppStream::setPeerId(const DOMString &val)
-{
-    sourceId = val;
-}
-
-/**
- *  Source or destination JID
- */
-DOMString XmppStream::getPeerId()
-{
-    return sourceId;
-}
-
-/**
- *  Stream packet sequence number
- */
-int XmppStream::getSeqNr()
-{
-    seqNr++;
-    if (seqNr >= 65535)
-        seqNr = 0;
-    return seqNr;
-}
-
-/**
- *
- */
-int XmppStream::available()
-{
-    return data.size();
-}
-
-/**
- *
- */
-void XmppStream::receiveData(std::vector<unsigned char> &newData)
-{
-    std::vector<unsigned char>::iterator iter;
-    for (iter=newData.begin() ; iter!=newData.end() ; iter++)
-        data.push_back(*iter);
-}
-
-/**
- *
- */
-std::vector<unsigned char> XmppStream::read()
-{
-    if (state != XmppClient::STREAM_OPEN)
-        {
-        std::vector<unsigned char>dummy;
-        return dummy;
-        }
-    std::vector<unsigned char> ret = data;
-    data.clear();
-    return ret;
-}
-
-
-
-
-
-
-//########################################################################
-//# X M P P    C L I E N T
-//########################################################################
-class ReceiverThread : public Runnable
-{
-public:
-
-    ReceiverThread(XmppClient &par) : client(par) {}
-
-    virtual ~ReceiverThread() {}
-
-    void run()
-      { client.receiveAndProcessLoop(); }
-
-private:
-
-    XmppClient &client;
-};
-
-
-//###########################
-//# CONSTRUCTORS
-//###########################
-
-XmppClient::XmppClient()
-{
-    init();
-}
-
-
-XmppClient::XmppClient(const XmppClient &other) : XmppEventTarget(other)
-{
-    init();
-    assign(other);
-}
-
-void XmppClient::assign(const XmppClient &other)
-{
-    msgId         = other.msgId;
-    host          = other.host;
-    realm         = other.realm;
-    port          = other.port;
-    username      = other.username;
-    password      = other.password;
-    resource      = other.resource;
-    connected     = other.connected;
-    groupChats    = other.groupChats;
-}
-
-
-void XmppClient::init()
-{
-    sock          = new TcpSocket();
-    msgId         = 0;
-    connected     = false;
-
-    for (int i=0 ; i<outputStreamCount ; i++)
-        {
-        outputStreams[i] = new XmppStream();
-        }
-    for (int i=0 ; i<inputStreamCount ; i++)
-        {
-        inputStreams[i] = new XmppStream();
-        }
-    for (int i=0 ; i<fileSendCount ; i++)
-        {
-        fileSends[i] = new XmppStream();
-        }
-}
-
-XmppClient::~XmppClient()
-{
-    disconnect();
-    delete sock;
-    for (int i=0 ; i<outputStreamCount ; i++)
-        {
-        delete outputStreams[i];
-        }
-    for (int i=0 ; i<inputStreamCount ; i++)
-        {
-        delete inputStreams[i];
-        }
-    for (int i=0 ; i<fileSendCount ; i++)
-        {
-        delete fileSends[i];
-        }
-    groupChatsClear();
-}
-
-//##############################################
-//# UTILILY
-//##############################################
-
-/**
- *
- */
-bool XmppClient::pause(unsigned long millis)
-{
-    Thread::sleep(millis);
-    return true;
-}
-
-
-static int strIndex(const DOMString &str, char *key)
-{
-    unsigned int p = str.find(key);
-    if (p == DOMString::npos)
-        return -1;
-    return p;
-}
-
-
-DOMString XmppClient::toXml(const DOMString &str)
-{
-    return Parser::encode(str);
-}
-
-static DOMString trim(const DOMString &str)
-{
-    unsigned int i;
-    for (i=0 ; i<str.size() ; i++)
-        if (!isspace(str[i]))
-            break;
-    int start = i;
-    for (i=str.size() ; i>0 ; i--)
-        if (!isspace(str[i-1]))
-            break;
-    int end = i;
-    if (start>=end)
-        return "";
-    return str.substr(start, end);
-}
-
-//##############################################
-//# VARIABLES  (ones that need special handling)
-//##############################################
-/**
- *
- */
-DOMString XmppClient::getUsername()
-{
-    return username;
-}
-
-/**
- *
- */
-void XmppClient::setUsername(const DOMString &val)
-{
-    int p = strIndex(val, "@");
-    if (p > 0)
-        {
-        username = val.substr(0, p);
-        realm    = val.substr(p+1, jid.size()-p-1);
-        }
-    else
-       {
-       realm    = host;
-       username = val;
-       }
-}
-
-//##############################################
-//# CONNECTION
-//##############################################
-
-//#######################
-//# RECEIVING
-//#######################
-DOMString XmppClient::readStanza()
-{
-    int  openCount    = 0;
-    bool inTag        = false;
-    bool slashSeen    = false;
-    bool trivialTag   = false;
-    bool querySeen    = false;
-    bool inQuote      = false;
-    bool textSeen     = false;
-    DOMString buf;
-
-    while (true)
-        {
-        int ch = sock->read();
-        //printf("%c", ch); fflush(stdout);
-        if (ch<0)
-            {
-            if (ch == -2) //a simple timeout, not an error
-                {
-                //Since we are timed out, let's assume that we
-                //are between chunks of text.  Let's reset all states.
-                //printf("-----#### Timeout\n");
-                continue;
-                }
-            else
-                {
-                keepGoing = false;
-                if (!sock->isConnected())
-                    {
-                    disconnect();
-                    return "";
-                    }
-                else
-                    {
-                    error("socket read error");
-                    disconnect();
-                    return "";
-                    }
-                }
-            }
-        buf.push_back(ch);
-        if (ch == '<')
-            {
-            inTag      = true;
-            slashSeen  = false;
-            querySeen  = false;
-            inQuote    = false;
-            textSeen   = false;
-            trivialTag = false;
-            }
-        else if (ch == '>')
-            {
-            if (!inTag)  //unescaped '>' in pcdata? horror
-                continue;
-            inTag     = false;
-            if (!trivialTag && !querySeen)
-                {
-                if (slashSeen)
-                    openCount--;
-                else
-                    openCount++;
-                }
-            //printf("# openCount:%d t:%d q:%d\n",
-            //      openCount, trivialTag, querySeen);
-            //check if we are 'balanced', but not a <?version?> tag
-            if (openCount <= 0 && !querySeen)
-                {
-                break;
-                }
-            //we know that this one will be open-ended
-            if (strIndex(buf, "<stream:stream") >= 0)
-                {
-                buf.append("</stream:stream>");
-                break;
-                }
-            }
-        else if (ch == '/')
-            {
-            if (inTag && !inQuote)
-                {
-                slashSeen = true;
-                if (textSeen) // <tagName/>  <--looks like this
-                    trivialTag = true;
-                }
-            }
-        else if (ch == '?')
-            {
-            if (inTag && !inQuote)
-                querySeen = true;
-            }
-        else if (ch == '"' || ch == '\'')
-            {
-            if (inTag)
-                inQuote = !inQuote;
-            }
-        else
-            {
-            if (inTag && !inQuote && !isspace(ch))
-                textSeen = true;
-            }
-        }
-    return buf;
-}
-
-
-
-static bool isGroupChat(Element *root)
-{
-    if (!root)
-        return false;
-    std::vector<Element *>elems = root->findElements("x");
-    for (unsigned int i=0 ; i<elems.size() ; i++)
-        {
-        DOMString xmlns = elems[i]->getAttribute("xmlns");
-        //printf("### XMLNS ### %s\n", xmlns.c_str());
-        if (strIndex(xmlns, "http://jabber.org/protocol/muc") >=0 )
-            return true;
-        }
-   return false;
-}
-
-
-
-
-static bool parseJid(const DOMString &fullJid,
-             DOMString &jid, DOMString &resource)
-{
-    int p = strIndex(fullJid, "/");
-    if (p < 0)
-        {
-        jid = fullJid;
-        resource = "";
-        return true;
-        }
-    jid = fullJid.substr(0, p);
-    resource = fullJid.substr(p+1, fullJid.size()-p-1);
-    return true;
-}
-
-
-
-
-bool XmppClient::processMessage(Element *root)
-{
-    DOMString from    = root->getTagAttribute("message", "from");
-    DOMString to      = root->getTagAttribute("message", "to");
-    DOMString type    = root->getTagAttribute("message", "type");
-
-    //####Check for embedded namespaces here
-    //# IN BAND BYTESTREAMS
-    DOMString ibbNamespace = "http://jabber.org/protocol/ibb";
-    if (root->getTagAttribute("data", "xmlns") == ibbNamespace)
-        {
-        DOMString streamId = root->getTagAttribute("data", "sid");
-        if (streamId.size() > 0)
-            {
-            for (int i=0 ; i<inputStreamCount ; i++)
-                {
-                XmppStream *ins = inputStreams[i];
-                //printf("##ins:%s  streamid:%s\n",
-                //    ins->getStreamId().c_str(),  streamId.c_str());
-                if (ins->getStreamId() == streamId)
-                    {
-                    //# We have a winner
-                    if (ins->getState() != STREAM_OPEN)
-                        {
-                        XmppEvent event(XmppEvent::EVENT_ERROR);
-                        event.setFrom(from);
-                        event.setData("received unrequested stream data");
-                        dispatchXmppEvent(event);
-                        return true;
-                        }
-                    DOMString data = root->getTagValue("data");
-                    std::vector<unsigned char>binData =
-                               Base64Decoder::decode(data);
-                    ins->receiveData(binData);
-                    }
-                }
-            }
-        }
-
-
-    //#### NORMAL MESSAGES
-    DOMString subject = root->getTagValue("subject");
-    DOMString body    = root->getTagValue("body");
-    DOMString thread  = root->getTagValue("thread");
-    //##rfc 3921, para 2.4.  ignore if no recognizable info
-    if (subject.size() < 1 && body.size()<1 && thread.size()<1)
-        return true;
-
-    if (type == "groupchat")
-        {
-        DOMString fromGid;
-        DOMString fromNick;
-        parseJid(from, fromGid, fromNick);
-        //printf("fromGid:%s  fromNick:%s\n",
-        //        fromGid.c_str(), fromNick.c_str());
-        DOMString toGid;
-        DOMString toNick;
-        parseJid(to, toGid, toNick);
-        //printf("toGid:%s  toNick:%s\n",
-        //        toGid.c_str(), toNick.c_str());
-
-        if (fromNick.size() > 0)//normal group message
-            {
-            XmppEvent event(XmppEvent::EVENT_MUC_MESSAGE);
-            event.setGroup(fromGid);
-            event.setFrom(fromNick);
-            event.setData(body);
-            event.setDOM(root);
-            dispatchXmppEvent(event);
-            }
-        else // from the server itself
-            {
-            //note the space before, so it doesnt match 'unlocked'
-            if (strIndex(body, " locked") >= 0)
-                {
-                printf("LOCKED!! ;)\n");
-                char *fmt =
-                "<iq from='%s' id='create%d' to='%s' type='set'>"
-                "<query xmlns='http://jabber.org/protocol/muc#owner'>"
-                "<x xmlns='jabber:x:data' type='submit'/>"
-                "</query></iq>\n";
-                if (!write(fmt, jid.c_str(), msgId++, fromGid.c_str()))
-                    return false;
-                }
-            }
-        }
-    else
-        {
-        XmppEvent event(XmppEvent::EVENT_MESSAGE);
-        event.setFrom(from);
-        event.setData(body);
-        event.setDOM(root);
-        dispatchXmppEvent(event);
-        }
-
-    return true;
-}
-
-
-
-
-bool XmppClient::processPresence(Element *root)
-{
-
-    DOMString fullJid     = root->getTagAttribute("presence", "from");
-    DOMString to          = root->getTagAttribute("presence", "to");
-    DOMString presenceStr = root->getTagAttribute("presence", "type");
-    bool presence = true;
-    if (presenceStr == "unavailable")
-        presence = false;
-    DOMString status      = root->getTagValue("status");
-    DOMString show        = root->getTagValue("show");
-
-    if (isGroupChat(root))
-        {
-        DOMString fromGid;
-        DOMString fromNick;
-        parseJid(fullJid, fromGid, fromNick);
-        //printf("fromGid:%s  fromNick:%s\n",
-        //        fromGid.c_str(), fromNick.c_str());
-        DOMString item_jid = root->getTagAttribute("item", "jid");
-        if (item_jid == jid) //Me
-            {
-            if (presence)
-                {
-                groupChatCreate(fromGid);
-                groupChatUserAdd(fromGid, fromNick, "");
-                groupChatUserShow(fromGid, fromNick, "available");
-
-                XmppEvent event(XmppEvent::EVENT_MUC_JOIN);
-                event.setGroup(fromGid);
-                event.setFrom(fromNick);
-                event.setPresence(presence);
-                event.setShow(show);
-                event.setStatus(status);
-                dispatchXmppEvent(event);
-                }
-            else
-                {
-                groupChatDelete(fromGid);
-                groupChatUserDelete(fromGid, fromNick);
-
-                XmppEvent event(XmppEvent::EVENT_MUC_LEAVE);
-                event.setGroup(fromGid);
-                event.setFrom(fromNick);
-                event.setPresence(presence);
-                event.setShow(show);
-                event.setStatus(status);
-                dispatchXmppEvent(event);
-                }
-            }
-        else // someone else
-            {
-            if (presence)
-                {
-                groupChatUserAdd(fromGid, fromNick, "");
-                }
-            else
-                groupChatUserDelete(fromGid, fromNick);               
-            groupChatUserShow(fromGid, fromNick, show);
-            XmppEvent event(XmppEvent::EVENT_MUC_PRESENCE);
-            event.setGroup(fromGid);
-            event.setFrom(fromNick);
-            event.setPresence(presence);
-            event.setShow(show);
-            event.setStatus(status);
-            dispatchXmppEvent(event);
-            }
-        }
-    else
-        {
-        DOMString shortJid;
-        DOMString dummy;
-        parseJid(fullJid, shortJid, dummy);
-        rosterShow(shortJid, show); //users in roster do not have resource
-        
-        XmppEvent event(XmppEvent::EVENT_PRESENCE);
-        event.setFrom(fullJid);
-        event.setPresence(presence);
-        event.setShow(show);
-        event.setStatus(status);
-        dispatchXmppEvent(event);
-        }
-
-    return true;
-}
-
-
-
-bool XmppClient::processIq(Element *root)
-{
-    DOMString from  = root->getTagAttribute("iq", "from");
-    DOMString id    = root->getTagAttribute("iq", "id");
-    DOMString type  = root->getTagAttribute("iq", "type");
-    DOMString xmlns = root->getTagAttribute("query", "xmlns");
-
-    if (id.size()<1)
-        return true;
-
-    //Group chat
-    if (strIndex(xmlns, "http://jabber.org/protocol/muc") >=0 )
-        {
-        printf("results of MUC query\n");
-        }
-    //printf("###IQ xmlns:%s\n", xmlns.c_str());
-
-    //### FILE TRANSFERS
-    DOMString siNamespace = "http://jabber.org/protocol/si";
-    if (root->getTagAttribute("si", "xmlns") == siNamespace)
-        {
-        if (type == "set")
-            {
-            DOMString streamId = root->getTagAttribute("si", "id");
-            DOMString fname    = root->getTagAttribute("file", "name");
-            DOMString sizeStr  = root->getTagAttribute("file", "size");
-            DOMString hash     = root->getTagAttribute("file", "hash");
-            XmppEvent event(XmppEvent::XmppEvent::EVENT_FILE_RECEIVE);
-            event.setFrom(from);
-            event.setIqId(id);
-            event.setStreamId(streamId);
-            event.setFileName(fname);
-            event.setFileHash(hash);
-            event.setFileSize(atol(sizeStr.c_str()));
-            dispatchXmppEvent(event);
-            }
-        else  //result
-            {
-            printf("Got result\n");
-            for (int i=0 ; i<fileSendCount ; i++)
-                {
-                XmppStream *outf = fileSends[i];
-                if (outf->getIqId() == id &&
-                    from == outf->getPeerId())
-                    {
-                    if (type == "error")
-                        {
-                        outf->setState(STREAM_ERROR);
-                        error("user '%s' rejected file", from.c_str());
-                        return true;
-                        }
-                    else if (type == "result")
-                        {
-                        if (outf->getState() == STREAM_OPENING)
-                            {
-                            XmppEvent event(XmppEvent::XmppEvent::EVENT_FILE_ACCEPTED);
-                            event.setFrom(from);
-                            dispatchXmppEvent(event);
-                            outf->setState(STREAM_OPEN);
-                            }
-                        else if (outf->getState() == STREAM_CLOSING)
-                            {
-                            outf->setState(STREAM_CLOSED);
-                            }
-                        return true;
-                        }
-                    }
-                }
-            }
-        return true;
-        }
-
-
-    //### IN-BAND BYTESTREAMS
-    //### Incoming stream requests
-    DOMString ibbNamespace = "http://jabber.org/protocol/ibb";
-    if (root->getTagAttribute("open", "xmlns") == ibbNamespace)
-        {
-        DOMString streamId = root->getTagAttribute("open", "sid");
-        XmppEvent event(XmppEvent::XmppEvent::EVENT_STREAM_RECEIVE_INIT);
-        dispatchXmppEvent(event);
-        if (streamId.size()>0)
-            {
-            for (int i=0 ; i<inputStreamCount ; i++)
-                {
-                XmppStream *ins = inputStreams[i];
-                if (ins->getStreamId() == streamId)
-                    {
-                    ins->setState(STREAM_OPENING);
-                    ins->setIqId(id);
-                    return true;
-                    }
-                }
-            }
-        return true;
-        }
-    else if (root->getTagAttribute("close", "xmlns") == ibbNamespace)
-        {
-        XmppEvent event(XmppEvent::XmppEvent::EVENT_STREAM_RECEIVE_CLOSE);
-        dispatchXmppEvent(event);
-        DOMString streamId = root->getTagAttribute("close", "sid");
-        if (streamId.size()>0)
-            {
-            for (int i=0 ; i<inputStreamCount ; i++)
-                {
-                XmppStream *ins = inputStreams[i];
-                if (ins->getStreamId() == streamId &&
-                    from == ins->getPeerId())
-                    {
-                    ins->setState(STREAM_CLOSING);
-                    ins->setIqId(id);
-                    return true;
-                    }
-                }
-            }
-        return true;
-        }
-    //### Responses to outgoing requests
-    for (int i=0 ; i<outputStreamCount ; i++)
-        {
-        XmppStream *outs = outputStreams[i];
-        if (outs->getIqId() == id)
-            {
-            if (type == "error")
-                {
-                outs->setState(STREAM_ERROR);
-                return true;
-                }
-            else if (type == "result")
-                {
-                if (outs->getState() == STREAM_OPENING)
-                    {
-                    outs->setState(STREAM_OPEN);
-                    }
-                else if (outs->getState() == STREAM_CLOSING)
-                    {
-                    outs->setState(STREAM_CLOSED);
-                    }
-                return true;
-                }
-            }
-        }
-
-    //###Normal Roster stuff
-    if (root->getTagAttribute("query", "xmlns") == "jabber:iq:roster")
-        {
-        roster.clear();
-        std::vector<Element *>elems = root->findElements("item");
-        for (unsigned int i=0 ; i<elems.size() ; i++)
-            {
-            Element *item = elems[i];
-            DOMString userJid      = item->getAttribute("jid");
-            DOMString name         = item->getAttribute("name");
-            DOMString subscription = item->getAttribute("subscription");
-            DOMString group        = item->getTagValue("group");
-            //printf("jid:%s name:%s sub:%s group:%s\n", userJid.c_str(), name.c_str(),
-            //        subscription.c_str(), group.c_str());
-            XmppUser user(userJid, name, subscription, group);
-            roster.push_back(user);
-            }
-        XmppEvent event(XmppEvent::XmppEvent::EVENT_ROSTER);
-        dispatchXmppEvent(event);
-        }
-
-    return true;
-}
-
-
-
-bool XmppClient::receiveAndProcess()
-{
-    if (!keepGoing)
-        return false;
-
-    Parser parser;
-
-    DOMString recvBuf = readStanza();
-    recvBuf = trim(recvBuf);
-    if (recvBuf.size() < 1)
-        return true;
-
-    //Ugly hack.  Apparently the first char can be dropped on timeouts
-    //if (recvBuf[0] != '<')
-    //    recvBuf.insert(0, "<");
-
-    status("RECV: %s", recvBuf.c_str());
-    Element *root = parser.parse(recvBuf);
-    if (!root)
-        {
-        printf("Bad elem\n");
-        return true;
-        }
-
-    //#### MESSAGE
-    std::vector<Element *>elems = root->findElements("message");
-    if (elems.size()>0)
-        {
-        if (!processMessage(root))
-            return false;
-        }
-
-    //#### PRESENCE
-    elems = root->findElements("presence");
-    if (elems.size()>0)
-        {
-        if (!processPresence(root))
-            return false;
-        }
-
-    //#### INFO
-    elems = root->findElements("iq");
-    if (elems.size()>0)
-        {
-        if (!processIq(root))
-            return false;
-        }
-
-    delete root;
-
-    return true;
-}
-
-
-bool XmppClient::receiveAndProcessLoop()
-{
-    keepGoing = true;
-    while (true)
-        {
-        if (!keepGoing)
-            {
-            printf("Abort requested\n");
-            break;
-            }
-        if (!receiveAndProcess())
-            return false;
-        }
-    return true;
-}
-
-//#######################
-//# SENDING
-//#######################
-
-bool XmppClient::write(char *fmt, ...)
-{
-    va_list args;
-    va_start(args,fmt);
-    vsnprintf((char *)writeBuf, writeBufLen, fmt,args);
-    va_end(args) ;
-    status("SEND: %s", writeBuf);
-    if (!sock->write((char *)writeBuf))
-        {
-        error("Cannot write to socket");
-        return false;
-        }
-    return true;
-}
-
-//#######################
-//# CONNECT
-//#######################
-
-bool XmppClient::checkConnect()
-{
-    if (!connected)
-        {
-        XmppEvent evt(XmppEvent::EVENT_ERROR);
-        evt.setData("Attempted operation while disconnected");
-        dispatchXmppEvent(evt);
-        return false;
-        }
-    return true;
-}
-
-bool XmppClient::iqAuthenticate(const DOMString &streamId)
-{
-    Parser parser;
-
-    char *fmt =
-    "<iq type='get' to='%s' id='auth%d'>"
-    "<query xmlns='jabber:iq:auth'><username>%s</username></query>"
-    "</iq>\n";
-    if (!write(fmt, realm.c_str(), msgId++, username.c_str()))
-        return false;
-
-    DOMString recbuf = readStanza();
-    //printf("iq received: '%s'\n", recbuf.c_str());
-    Element *elem = parser.parse(recbuf);
-    //elem->print();
-    DOMString iqType = elem->getTagAttribute("iq", "type");
-    //printf("##iqType:%s\n", iqType.c_str());
-    delete elem;
-
-    if (iqType != "result")
-        {
-        error("error:server does not allow login");
-        return false;
-        }
-
-    bool digest = true;
-    if (digest)
-        {
-        //## Digest authentication
-        DOMString digest = streamId;
-        digest.append(password);
-        digest = Sha1::hashHex((unsigned char *)digest.c_str(), digest.size());
-        //printf("digest:%s\n", digest.c_str());
-        fmt =
-        "<iq type='set' id='auth%d'>"
-        "<query xmlns='jabber:iq:auth'>"
-        "<username>%s</username>"
-        "<digest>%s</digest>"
-        "<resource>%s</resource>"
-        "</query>"
-        "</iq>\n";
-        if (!write(fmt, msgId++, username.c_str(),
-                    digest.c_str(), resource.c_str()))
-            return false;
-        }
-    else
-        {
-
-        //## Plaintext authentication
-        fmt =
-        "<iq type='set' id='auth%d'>"
-        "<query xmlns='jabber:iq:auth'>"
-        "<username>%s</username>"
-        "<password>%s</password>"
-        "<resource>%s</resource>"
-        "</query>"
-        "</iq>\n";
-        if (!write(fmt, msgId++, username.c_str(),
-                   password.c_str(), resource.c_str()))
-            return false;
-        }
-
-    recbuf = readStanza();
-    //printf("iq received: '%s'\n", recbuf.c_str());
-    elem = parser.parse(recbuf);
-    //elem->print();
-    iqType = elem->getTagAttribute("iq", "type");
-    //printf("##iqType:%s\n", iqType.c_str());
-    delete elem;
-
-    if (iqType != "result")
-        {
-        error("server does not allow login");
-        return false;
-        }
-
-    return true;
-}
-
-
-
-bool XmppClient::saslMd5Authenticate()
-{
-    Parser parser;
-    char *fmt =
-    "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' "
-    "mechanism='DIGEST-MD5'/>\n";
-    if (!write(fmt))
-        return false;
-
-    DOMString recbuf = readStanza();
-    status("challenge received: '%s'", recbuf.c_str());
-    Element *elem = parser.parse(recbuf);
-    //elem->print();
-    DOMString b64challenge = elem->getTagValue("challenge");
-    delete elem;
-
-    if (b64challenge.size() < 1)
-        {
-        error("login: no SASL challenge offered by server");
-        return false;
-        }
-    DOMString challenge = Base64Decoder::decodeToString(b64challenge);
-    status("challenge:'%s'", challenge.c_str());
-
-    unsigned int p1 = challenge.find("nonce=\"");
-    if (p1 == DOMString::npos)
-        {
-        error("login: no SASL nonce sent by server");
-        return false;
-        }
-    p1 += 7;
-    unsigned int p2 = challenge.find("\"", p1);
-    if (p2 == DOMString::npos)
-        {
-        error("login: unterminated SASL nonce sent by server");
-        return false;
-        }
-    DOMString nonce = challenge.substr(p1, p2-p1);
-    //printf("nonce: '%s'\n", nonce.c_str());
-    char idBuf[7];
-    snprintf(idBuf, 6, "%dsasl", msgId++);
-    DOMString cnonce = Sha1::hashHex((unsigned char *)idBuf, 7);
-    DOMString authzid = username; authzid.append("@"); authzid.append(host);
-    DOMString digest_uri = "xmpp/"; digest_uri.append(host);
-
-    //## Make A1
-    Md5 md5;
-    md5.append(username);
-    md5.append(":");
-    md5.append(realm);
-    md5.append(":");
-    md5.append(password);
-    unsigned char a1tmp[16];
-    md5.finish(a1tmp);
-    md5.init();
-    md5.append(a1tmp, 16);
-    md5.append(":");
-    md5.append(nonce);
-    md5.append(":");
-    md5.append(cnonce);
-    md5.append(":");
-    md5.append(authzid);
-    DOMString a1 = md5.finishHex();
-    status("##a1:'%s'", a1.c_str());
-
-    //# Make A2
-    md5.init();
-    md5.append("AUTHENTICATE:");
-    md5.append(digest_uri);
-    DOMString a2 = md5.finishHex();
-    status("##a2:'%s'", a2.c_str());
-
-    //# Now make the response
-    md5.init();
-    md5.append(a1);
-    md5.append(":");
-    md5.append(nonce);
-    md5.append(":");
-    md5.append("00000001");//nc
-    md5.append(":");
-    md5.append(cnonce);
-    md5.append(":");
-    md5.append("auth");//qop
-    md5.append(":");
-    md5.append(a2);
-    DOMString response = md5.finishHex();
-
-    DOMString resp;
-    resp.append("username=\""); resp.append(username); resp.append("\",");
-    resp.append("realm=\"");    resp.append(realm);    resp.append("\",");
-    resp.append("nonce=\"");    resp.append(nonce);    resp.append("\",");
-    resp.append("cnonce=\"");   resp.append(cnonce);   resp.append("\",");
-    resp.append("nc=00000001,qop=auth,");
-    resp.append("digest-uri=\""); resp.append(digest_uri); resp.append("\"," );
-    resp.append("authzid=\"");  resp.append(authzid);  resp.append("\",");
-    resp.append("response=\""); resp.append(response); resp.append("\",");
-    resp.append("charset=utf-8");
-    status("sending response:'%s'", resp.c_str());
-    resp = Base64Encoder::encode(resp);
-    status("base64 response:'%s'", resp.c_str());
-    fmt =
-    "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>%s</response>\n";
-    if (!write(fmt, resp.c_str()))
-        return false;
-
-    recbuf = readStanza();
-    status("server says:: '%s'", recbuf.c_str());
-    elem = parser.parse(recbuf);
-    //elem->print();
-    b64challenge = elem->getTagValue("challenge");
-    delete elem;
-
-    if (b64challenge.size() < 1)
-        {
-        error("login: no second SASL challenge offered by server");
-        return false;
-        }
-
-    challenge = Base64Decoder::decodeToString(b64challenge);
-    status("challenge: '%s'", challenge.c_str());
-    p1 = challenge.find("rspauth=");
-    if (p1 == DOMString::npos)
-        {
-        error("login: no SASL respauth sent by server\n");
-        return false;
-        }
-
-    fmt =
-    "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>\n";
-    if (!write(fmt))
-        return false;
-
-    recbuf = readStanza();
-    status("server says: '%s", recbuf.c_str());
-    elem = parser.parse(recbuf);
-    //elem->print();
-    b64challenge = elem->getTagValue("challenge");
-    bool success = (elem->findElements("success").size() > 0);
-    delete elem;
-
-    return success;
-}
-
-bool XmppClient::saslPlainAuthenticate()
-{
-    Parser parser;
-
-    DOMString id = username;
-    //id.append("@");
-    //id.append(host);
-    Base64Encoder encoder;
-    encoder.append('\0');
-    encoder.append(id);
-    encoder.append('\0');
-    encoder.append(password);
-    DOMString base64Auth = encoder.finish();
-    //printf("authbuf:%s\n", base64Auth.c_str());
-
-    char *fmt =
-    "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' "
-    "mechanism='PLAIN'>%s</auth>\n";
-    if (!write(fmt, base64Auth.c_str()))
-        return false;
-    DOMString recbuf = readStanza();
-    status("challenge received: '%s'", recbuf.c_str());
-    Element *elem = parser.parse(recbuf);
-
-    bool success = (elem->findElements("success").size() > 0);
-    delete elem;
-
-    return success;
-}
-
-
-
-bool XmppClient::saslAuthenticate()
-{
-    Parser parser;
-
-    DOMString recbuf = readStanza();
-    status("RECV: '%s'\n", recbuf.c_str());
-    Element *elem = parser.parse(recbuf);
-    //elem->print();
-
-    //Check for starttls
-    bool wantStartTls = false;
-    if (elem->findElements("starttls").size() > 0)
-        {
-        wantStartTls = true;
-        if (elem->findElements("required").size() > 0)
-            status("login: STARTTLS required");
-        else
-            status("login: STARTTLS available");
-        }
-
-    if (wantStartTls)
-        {
-        delete elem;
-        char *fmt =
-        "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n";
-        if (!write(fmt))
-            return false;
-        recbuf = readStanza();
-        status("RECV: '%s'\n", recbuf.c_str());
-        elem = parser.parse(recbuf);
-        if (elem->getTagAttribute("proceed", "xmlns").size()<1)
-            {
-            error("Server rejected TLS negotiation");
-            disconnect();
-            return false;
-            }
-        delete elem;
-        if (!sock->startTls())
-            {
-            error("Could not start TLS");
-            disconnect();
-            return false;
-            }
-
-        fmt =
-         "<stream:stream xmlns='jabber:client' "
-         "xmlns:stream='http://etherx.jabber.org/streams' "
-         "to='%s' version='1.0'>\n\n";
-        if (!write(fmt, realm.c_str()))
-            return false;
-
-        recbuf = readStanza();
-        status("RECVx: '%s'", recbuf.c_str());
-        recbuf.append("</stream:stream>");
-        elem = parser.parse(recbuf);
-        bool success =
-        (elem->getTagAttribute("stream:stream", "id").size()>0);
-        if (!success)
-            {
-            error("STARTTLS negotiation failed");
-            disconnect();
-            return false;
-            }
-        delete elem;
-        recbuf = readStanza();
-        status("RECV: '%s'\n", recbuf.c_str());
-        elem = parser.parse(recbuf);
-        }
-
-    //check for sasl authentication mechanisms
-    std::vector<Element *> elems =
-               elem->findElements("mechanism");
-    if (elems.size() < 1)
-        {
-        error("login: no SASL mechanism offered by server");
-        return false;
-        }
-    bool md5Found = false;
-    bool plainFound = false;
-    for (unsigned int i=0 ; i<elems.size() ; i++)
-        {
-        DOMString mech = elems[i]->getValue();
-        if (mech == "DIGEST-MD5")
-            {
-            status("MD5 authentication offered");
-            md5Found = true;
-            }
-        else if (mech == "PLAIN")
-            {
-            status("PLAIN authentication offered");
-            plainFound = true;
-            }
-        }
-    delete elem;
-
-    bool success = false;
-    if (md5Found)
-        {
-        success = saslMd5Authenticate();
-        }
-    else if (plainFound)
-        {
-        success = saslPlainAuthenticate();
-        }
-    else
-        {
-        error("not able to handle sasl authentication mechanisms");
-        return false;
-        }
-
-    if (success)
-        status("###### SASL authentication success\n");
-    else
-        error("###### SASL authentication failure\n");
-
-    return success;
-}
-
-
-
-
-
-bool XmppClient::createSession()
-{
-
-    Parser parser;
-    if (port==443 || port==5223)
-        sock->enableSSL(true);
-    if (!sock->connect(host, port))
-        {
-        return false;
-        }
-
-    char *fmt =
-     "<stream:stream "
-          "to='%s' "
-          "xmlns='jabber:client' "
-          "xmlns:stream='http://etherx.jabber.org/streams' "
-          "version='1.0'>\n\n";
-    if (!write(fmt, realm.c_str()))
-        return false;
-
-    DOMString recbuf = readStanza();
-    //printf("received: '%s'\n", recbuf.c_str());
-    recbuf.append("</stream:stream>");
-    Element *elem = parser.parse(recbuf);
-    //elem->print();
-    bool useSasl = false;
-    DOMString streamId = elem->getTagAttribute("stream:stream", "id");
-    //printf("### StreamID: %s\n", streamId.c_str());
-    DOMString streamVersion = elem->getTagAttribute("stream:stream", "version");
-    if (streamVersion == "1.0")
-        useSasl = true;
-
-    if (useSasl)
-        {
-        if (!saslAuthenticate())
-            return false;
-        fmt =
-          "<stream:stream "
-          "to='%s' "
-          "xmlns='jabber:client' "
-          "xmlns:stream='http://etherx.jabber.org/streams' "
-          "version='1.0'>\n\n";
-
-        if (!write(fmt, realm.c_str()))
-            return false;
-        recbuf = readStanza();
-        recbuf.append("</stream:stream>\n");
-        //printf("now server says:: '%s'\n", recbuf.c_str());
-        elem = parser.parse(recbuf);
-        //elem->print();
-        delete elem;
-
-        recbuf = readStanza();
-        //printf("now server says:: '%s'\n", recbuf.c_str());
-        elem = parser.parse(recbuf);
-        bool hasBind = (elem->findElements("bind").size() > 0);
-        //elem->print();
-        delete elem;
-
-        if (!hasBind)
-            {
-            error("no binding provided by server");
-            return false;
-            }
-
-
-        }
-    else // not SASL
-        {
-        if (!iqAuthenticate(streamId))
-            return false;
-        }
-
-
-    //### Resource binding
-    fmt =
-    "<iq type='set' id='bind%d'>"
-    "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>"
-    "<resource>%s</resource>"
-    "</bind></iq>\n";
-    if (!write(fmt, msgId++, resource.c_str()))
-        return false;
-
-    recbuf = readStanza();
-    status("bind result: '%s'", recbuf.c_str());
-    elem = parser.parse(recbuf);
-    //elem->print();
-    DOMString bindType = elem->getTagAttribute("iq", "type");
-    //printf("##bindType:%s\n", bindType.c_str());
-    delete elem;
-
-    if (bindType != "result")
-        {
-        error("no binding with server failed");
-        return false;
-        }
-
-    fmt =
-    "<iq type='set' id='sess%d'>"
-    "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>"
-    "</iq>\n";
-    if (!write(fmt, msgId++))
-        return false;
-
-    recbuf = readStanza();
-    status("session received: '%s'", recbuf.c_str());
-    elem = parser.parse(recbuf);
-    //elem->print();
-    DOMString sessionType = elem->getTagAttribute("iq", "type");
-    //printf("##sessionType:%s\n", sessionType.c_str());
-    delete elem;
-
-    if (sessionType != "result")
-        {
-        error("no session provided by server");
-        return false;
-        }
-
-    //printf("########## COOL #########\n");
-    //Now that we are bound, we have a valid JID
-    jid = username;
-    jid.append("@");
-    jid.append(realm);
-    jid.append("/");
-    jid.append(resource);
-
-    //We are now done with the synchronous handshaking.  Let's go into
-    //async mode
-
-    fmt =
-     "<iq type='get' id='roster%d'><query xmlns='jabber:iq:roster'/></iq>\n";
-    if (!write(fmt, msgId++))
-        return false;
-
-    fmt =
-     "<iq type='get' id='discoItems%d' to='%s'>"
-     "<query xmlns='http://jabber.org/protocol/disco#items'/></iq>\n";
-    if (!write(fmt, msgId++, realm.c_str()))
-        return false;
-
-    fmt =
-    "<iq type='get' id='discoInfo%d' to='conference.%s'>"
-    "<query xmlns='http://jabber.org/protocol/disco#info'/></iq>\n";
-    if (!write(fmt, msgId++, realm.c_str()))
-        return false;
-
-    fmt =
-     "<presence/>\n";
-    if (!write(fmt))
-        return false;
-
-    /*
-    recbuf = readStanza();
-    status("stream received: '%s'", recbuf.c_str());
-    elem = parser.parse(recbuf);
-    //elem->print();
-    delete elem;
-    */
-
-    //We are now logged in
-    status("Connected");
-    connected = true;
-    XmppEvent evt(XmppEvent::EVENT_CONNECTED);
-    dispatchXmppEvent(evt);
-    //Thread::sleep(1000000);
-
-    sock->setReceiveTimeout(1000);
-    ReceiverThread runner(*this);
-    Thread thread(runner);
-    thread.start();
-
-    return true;
-}
-
-bool XmppClient::connect()
-{
-    if (!createSession())
-        {
-        disconnect();
-        return false;
-        }
-    return true;
-}
-
-
-bool XmppClient::connect(DOMString hostArg, int portArg,
-                         DOMString usernameArg,
-                         DOMString passwordArg,
-                         DOMString resourceArg)
-{
-    host     = hostArg;
-    port     = portArg;
-    password = passwordArg;
-    resource = resourceArg;
-
-    //parse this one
-    setUsername(usernameArg);
-
-    bool ret = connect();
-    return ret;
-}
-
-bool XmppClient::disconnect()
-{
-    if (connected)
-        {
-        char *fmt =
-        "<presence from='%s' type='unavailable'/>\n";
-        write(fmt, jid.c_str());
-        }
-    keepGoing = false;
-    connected = false;
-    Thread::sleep(3000); //allow receiving thread to quit
-    sock->disconnect();
-    roster.clear();
-    groupChatsClear();
-    XmppEvent event(XmppEvent::EVENT_DISCONNECTED);
-    dispatchXmppEvent(event);
-    return true;
-}
-
-//#######################
-//# ROSTER
-//#######################
-
-bool XmppClient::rosterAdd(const DOMString &rosterGroup,
-                           const DOMString &otherJid,
-                           const DOMString &name)
-{
-    if (!checkConnect())
-        return false;
-    char *fmt =
-    "<iq from='%s' type='set' id='roster_%d'>"
-    "<query xmlns='jabber:iq:roster'>"
-    "<item jid='%s' name='%s'><group>%s</group></item>"
-    "</query></iq>\n";
-    if (!write(fmt, jid.c_str(), msgId++, otherJid.c_str(),
-         name.c_str(), rosterGroup.c_str()))
-        {
-        return false;
-        }
-    return true;
-}
-
-bool XmppClient::rosterDelete(const DOMString &otherJid)
-{
-    if (!checkConnect())
-        return false;
-    char *fmt =
-    "<iq from='%s' type='set' id='roster_%d'>"
-    "<query xmlns='jabber:iq:roster'>"
-    "<item jid='%s' subscription='remove'><group>%s</group></item>"
-    "</query></iq>\n";
-    if (!write(fmt, jid.c_str(), msgId++, otherJid.c_str()))
-        {
-        return false;
-        }
-    return true;
-}
-
-
-static bool xmppRosterCompare(const XmppUser& p1, const XmppUser& p2)
-{
-    DOMString s1 = p1.group;
-    DOMString s2 = p2.group;
-    for (unsigned int len=0 ; len<s1.size() && len<s2.size() ; len++)
-        {
-        int comp = tolower(s1[len]) - tolower(s2[len]);
-        if (comp)
-            return (comp<0);
-        }
-
-    s1 = p1.jid;
-    s2 = p2.jid;
-    for (unsigned int len=0 ; len<s1.size() && len<s2.size() ; len++)
-        {
-        int comp = tolower(s1[len]) - tolower(s2[len]);
-        if (comp)
-            return (comp<0);
-        }
-    return false;
-}
-
-std::vector<XmppUser> XmppClient::getRoster()
-{
-    std::vector<XmppUser> ros = roster;
-    std::sort(ros.begin(), ros.end(), xmppRosterCompare);
-    return ros;
-}
-
-void XmppClient::rosterShow(const DOMString &jid, const DOMString &show)
-{
-    DOMString theShow = show;
-    if (theShow == "")
-        theShow = "available";
-    
-    std::vector<XmppUser>::iterator iter;
-    for (iter=roster.begin() ; iter != roster.end() ; iter++)
-        {
-        if (iter->jid == jid)
-            iter->show = theShow;
-        }
-}
-
-//#######################
-//# CHAT (individual)
-//#######################
-
-bool XmppClient::message(const DOMString &user, const DOMString &subj,
-                         const DOMString &msg)
-{
-    if (!checkConnect())
-        return false;
-
-    DOMString xmlSubj = toXml(subj);
-    DOMString xmlMsg  = toXml(msg);
-
-    if (xmlSubj.size() > 0)
-        {
-        char *fmt =
-        "<message from='%s' to='%s' type='chat'>"
-        "<subject>%s</subject><body>%s</body></message>\n";
-        if (!write(fmt, jid.c_str(), user.c_str(),
-                xmlSubj.c_str(), xmlMsg.c_str()))
-            return false;
-        }
-    else
-        {
-        char *fmt =
-        "<message from='%s' to='%s'>"
-        "<body>%s</body></message>\n";
-        if (!write(fmt, jid.c_str(), user.c_str(), xmlMsg.c_str()))
-            return false;
-        }
-    return true;
-}
-
-
-
-bool XmppClient::message(const DOMString &user, const DOMString &msg)
-{
-    return message(user, "", msg);
-}
-
-
-
-bool XmppClient::presence(const DOMString &presence)
-{
-    if (!checkConnect())
-        return false;
-
-    DOMString xmlPres = toXml(presence);
-
-    char *fmt =
-    "<presence from='%s'><show>%s</show></presence>\n";
-    if (!write(fmt, jid.c_str(), xmlPres.c_str()))
-        return false;
-    return true;
-}
-
-//#######################
-//# GROUP  CHAT
-//#######################
-
-bool XmppClient::groupChatCreate(const DOMString &groupJid)
-{
-    std::vector<XmppGroupChat *>::iterator iter;
-    for (iter=groupChats.begin() ; iter!=groupChats.end() ; iter++)
-        {
-        if ((*iter)->getGroupJid() == groupJid)
-            {
-            error("Group chat '%s' already exists", groupJid.c_str());
-            return false;
-            }
-        }
-    XmppGroupChat *chat = new XmppGroupChat(groupJid);
-    groupChats.push_back(chat);
-    return true;
-}
-
-/**
- *
- */
-void XmppClient::groupChatDelete(const DOMString &groupJid)
-{
-    std::vector<XmppGroupChat *>::iterator iter;
-    for (iter=groupChats.begin() ; iter!=groupChats.end() ; )
-        {
-        XmppGroupChat *chat = *iter;
-        if (chat->getGroupJid() == groupJid)
-            {
-            iter = groupChats.erase(iter);
-            delete chat;
-            }
-        else
-            iter++;
-        }
-}
-
-/**
- *
- */
-bool XmppClient::groupChatExists(const DOMString &groupJid)
-{
-    std::vector<XmppGroupChat *>::iterator iter;
-    for (iter=groupChats.begin() ; iter!=groupChats.end() ; iter++)
-        if ((*iter)->getGroupJid() == groupJid)
-            return true;
-    return false;
-}
-
-/**
- *
- */
-void XmppClient::groupChatsClear()
-{
-    std::vector<XmppGroupChat *>::iterator iter;
-    for (iter=groupChats.begin() ; iter!=groupChats.end() ; iter++)
-        delete (*iter);
-    groupChats.clear();
-}
-
-
-/**
- *
- */
-void XmppClient::groupChatUserAdd(const DOMString &groupJid,
-                                  const DOMString &nick,
-                                  const DOMString &jid)
-{
-    std::vector<XmppGroupChat *>::iterator iter;
-    for (iter=groupChats.begin() ; iter!=groupChats.end() ; iter++)
-        {
-        if ((*iter)->getGroupJid() == groupJid)
-            {
-            (*iter)->userAdd(nick, jid);
-            }
-        }
-}
-
-/**
- *
- */
-void XmppClient::groupChatUserShow(const DOMString &groupJid,
-                                   const DOMString &nick,
-                                   const DOMString &show)
-{
-    std::vector<XmppGroupChat *>::iterator iter;
-    for (iter=groupChats.begin() ; iter!=groupChats.end() ; iter++)
-        {
-        if ((*iter)->getGroupJid() == groupJid)
-            {
-            (*iter)->userShow(nick, show);
-            }
-        }
-}
-
-/**
- *
- */
-void XmppClient::groupChatUserDelete(const DOMString &groupJid,
-                                     const DOMString &nick)
-{
-    std::vector<XmppGroupChat *>::iterator iter;
-    for (iter=groupChats.begin() ; iter!=groupChats.end() ; iter++)
-        {
-        if ((*iter)->getGroupJid() == groupJid)
-            {
-            (*iter)->userDelete(nick);
-            }
-        }
-}
-
-static bool xmppUserCompare(const XmppUser& p1, const XmppUser& p2)
-{
-    DOMString s1 = p1.nick;
-    DOMString s2 = p2.nick;
-    int comp = 0;
-    for (unsigned int len=0 ; len<s1.size() && len<s2.size() ; len++)
-        {
-        comp = tolower(s1[len]) - tolower(s2[len]);
-        if (comp)
-            break;
-        }
-    return (comp<0);
-}
-
-
-std::vector<XmppUser> XmppClient::groupChatGetUserList(
-                              const DOMString &groupJid)
-{
-    if (!checkConnect())
-        {
-        std::vector<XmppUser> dummy;
-        return dummy;
-        }
-
-    std::vector<XmppGroupChat *>::iterator iter;
-    for (iter=groupChats.begin() ; iter!=groupChats.end() ; iter++)
-        {
-        if ((*iter)->getGroupJid() == groupJid )
-            {
-            std::vector<XmppUser> uList = (*iter)->getUserList();
-            std::sort(uList.begin(), uList.end(), xmppUserCompare);
-            return uList;
-            }
-        }
-    std::vector<XmppUser> dummy;
-    return dummy;
-}
-
-bool XmppClient::groupChatJoin(const DOMString &groupJid,
-                               const DOMString &nick,
-                               const DOMString &pass)
-{
-    if (!checkConnect())
-        return false;
-
-    DOMString user = nick;
-    if (user.size()<1)
-        user = username;
-
-    char *fmt =
-    "<presence to='%s/%s'>"
-    "<x xmlns='http://jabber.org/protocol/muc'/></presence>\n";
-    if (!write(fmt, groupJid.c_str(), user.c_str()))
-        return false;
-    return true;
-}
-
-
-bool XmppClient::groupChatLeave(const DOMString &groupJid,
-                                const DOMString &nick)
-{
-    if (!checkConnect())
-        return false;
-
-    DOMString user = nick;
-    if (user.size()<1)
-        user = username;
-
-    char *fmt =
-    "<presence to='%s/%s' type='unavailable'>"
-    "<x xmlns='http://jabber.org/protocol/muc'/></presence>\n";
-    if (!write(fmt, groupJid.c_str(), user.c_str()))
-        return false;
-    return true;
-}
-
-
-bool XmppClient::groupChatMessage(const DOMString &groupJid,
-                                  const DOMString &msg)
-{
-    if (!checkConnect())
-        {
-        return false;
-        }
-
-    DOMString xmlMsg = toXml(msg);
-
-    char *fmt =
-    "<message from='%s' to='%s' type='groupchat'>"
-    "<body>%s</body></message>\n";
-    if (!write(fmt, jid.c_str(), groupJid.c_str(), xmlMsg.c_str()))
-        return false;
-    return true;
-}
-
-bool XmppClient::groupChatPrivateMessage(const DOMString &groupJid,
-                                         const DOMString &toNick,
-                                         const DOMString &msg)
-{
-    if (!checkConnect())
-        return false;
-
-    DOMString xmlMsg = toXml(msg);
-
-    char *fmt =
-    "<message from='%s' to='%s/%s' type='chat'>"
-    "<body>%s</body></message>\n";
-    if (!write(fmt, jid.c_str(), groupJid.c_str(),
-               toNick.c_str(), xmlMsg.c_str()))
-        return false;
-    return true;
-}
-
-bool XmppClient::groupChatPresence(const DOMString &groupJid,
-                                   const DOMString &myNick,
-                                   const DOMString &presence)
-{
-    if (!checkConnect())
-        return false;
-
-    DOMString user = myNick;
-    if (user.size()<1)
-        user = username;
-
-    DOMString xmlPresence = toXml(presence);
-
-    char *fmt =
-    "<presence from='%s' to='%s/%s' type='unavailable'>"
-    "<x xmlns='http://jabber.org/protocol/muc'/></presence>\n";
-    if (!write(fmt, jid.c_str(), groupJid.c_str(), user.c_str(), xmlPresence.c_str()))
-        return true;
-    return true;
-}
-
-
-
-//#######################
-//# S T R E A M S
-//#######################
-
-
-/**
- *
- */
-int XmppClient::outputStreamOpen(const DOMString &destId,
-                                 const DOMString &streamIdArg)
-{
-    int i;
-    for (i=0; i<outputStreamCount ; i++)
-        if (outputStreams[i]->getState() == STREAM_AVAILABLE)
-            break;
-    if (i>=outputStreamCount)
-        {
-        error("No available output streams");
-        return -1;
-        }
-    int streamNr = i;
-    XmppStream *outs = outputStreams[streamNr];
-
-    outs->setState(STREAM_OPENING);
-
-    char buf[32];
-    snprintf(buf, 31, "inband%d", getMsgId());
-    DOMString iqId = buf;
-
-    DOMString streamId = streamIdArg;
-    if (streamId.size()<1)
-        {
-        snprintf(buf, 31, "stream%d", getMsgId());
-        DOMString streamId = buf;
-        }
-    outs->setIqId(iqId);
-    outs->setStreamId(streamId);
-    outs->setPeerId(destId);
-
-    char *fmt =
-    "<iq type='set' from='%s' to='%s' id='%s'>"
-    "<open sid='%s' block-size='4096'"
-    " xmlns='http://jabber.org/protocol/ibb'/></iq>\n";
-    if (!write(fmt, jid.c_str(),
-              destId.c_str(), iqId.c_str(),
-              streamId.c_str()))
-        {
-        outs->reset();
-        return -1;
-        }
-
-    int state = outs->getState();
-    for (int tim=0 ; tim<20 ; tim++)
-        {
-        if (state == STREAM_OPEN)
-            break;
-        else if (state == STREAM_ERROR)
-            {
-            printf("ERROR\n");
-            outs->reset();
-            return -1;
-            }
-        Thread::sleep(1000);
-        state = outs->getState();
-        }
-    if (state != STREAM_OPEN)
-        {
-        printf("TIMEOUT ERROR\n");
-        outs->reset();
-        return -1;
-        }
-
-    return streamNr;
-}
-
-/**
- *
- */
-int XmppClient::outputStreamWrite(int streamNr,
-                      const unsigned char *buf, unsigned long len)
-{
-    XmppStream *outs = outputStreams[streamNr];
-
-    unsigned long outLen = 0;
-    unsigned char *p = (unsigned char *)buf;
-
-    while (outLen < len)
-        {
-        unsigned long chunksize = 1024;
-        if (chunksize + outLen > len)
-            chunksize = len - outLen;
-
-        Base64Encoder encoder;
-        encoder.append(p, chunksize);
-        DOMString b64data = encoder.finish();
-        p      += chunksize;
-        outLen += chunksize;
-
-        char *fmt =
-        "<message from='%s' to='%s' id='msg%d'>"
-        "<data xmlns='http://jabber.org/protocol/ibb' sid='%s' seq='%d'>"
-        "%s"
-        "</data>"
-        "<amp xmlns='http://jabber.org/protocol/amp'>"
-        "<rule condition='deliver-at' value='stored' action='error'/>"
-        "<rule condition='match-resource' value='exact' action='error'/>"
-        "</amp>"
-        "</message>\n";
-        if (!write(fmt, jid.c_str(),
-              outs->getPeerId().c_str(),
-              getMsgId(),
-              outs->getStreamId().c_str(),
-              outs->getSeqNr(),
-              b64data.c_str()))
-            {
-            outs->reset();
-            return -1;
-            }
-        pause(5000);
-        }
-    return outLen;
-}
-
-/**
- *
- */
-int XmppClient::outputStreamClose(int streamNr)
-{
-    XmppStream *outs = outputStreams[streamNr];
-
-    char buf[32];
-    snprintf(buf, 31, "inband%d", getMsgId());
-    DOMString iqId = buf;
-    outs->setIqId(iqId);
-
-    outs->setState(STREAM_CLOSING);
-    char *fmt =
-    "<iq type='set' from='%s' to='%s' id='%s'>"
-    "<close sid='%s' xmlns='http://jabber.org/protocol/ibb'/></iq>\n";
-    if (!write(fmt, jid.c_str(),
-                    outs->getPeerId().c_str(),
-                    iqId.c_str(),
-                    outs->getStreamId().c_str()))
-        return false;
-
-    int state = outs->getState();
-    for (int tim=0 ; tim<20 ; tim++)
-        {
-        if (state == STREAM_CLOSED)
-            break;
-        else if (state == STREAM_ERROR)
-            {
-            printf("ERROR\n");
-            outs->reset();
-            return -1;
-            }
-        Thread::sleep(1000);
-        state = outs->getState();
-        }
-    if (state != STREAM_CLOSED)
-        {
-        printf("TIMEOUT ERROR\n");
-        outs->reset();
-        return -1;
-        }
-
-    outs->reset();
-    return 1;
-}
-
-
-/**
- *
- */
-int XmppClient::inputStreamOpen(const DOMString &fromJid, const DOMString &streamId,
-                                const DOMString &iqId)
-{
-    int i;
-    for (i=0 ; i<inputStreamCount ; i++)
-        {
-        if (inputStreams[i]->getState() == STREAM_AVAILABLE)
-            break;
-        }
-    if (i>=inputStreamCount)
-        {
-        error("No available input streams");
-        return -1;
-        }
-    int streamNr = i;
-    XmppStream *ins = inputStreams[streamNr];
-    ins->reset();
-    ins->setPeerId(fromJid);
-    ins->setState(STREAM_CLOSED);
-    ins->setStreamId(streamId);
-
-    int state = ins->getState();
-    for (int tim=0 ; tim<20 ; tim++)
-        {
-        if (state == STREAM_OPENING)
-            break;
-        else if (state == STREAM_ERROR)
-            {
-            printf("ERROR\n");
-            ins->reset();
-            return -1;
-            }
-        Thread::sleep(1000);
-        state = ins->getState();
-        }
-    if (state != STREAM_OPENING)
-        {
-        printf("TIMEOUT ERROR\n");
-        ins->reset();
-        return -1;
-        }
-    char *fmt =
-    "<iq type='result' from='%s' to='%s' id='%s'/>\n";
-    if (!write(fmt, jid.c_str(),  fromJid.c_str(), ins->getIqId().c_str()))
-        {
-        return -1;
-        }
-
-    ins->setState(STREAM_OPEN);
-    return streamNr;
-}
-
-/**
- *
- */
-int XmppClient::inputStreamAvailable(int streamNr)
-{
-    XmppStream *ins = inputStreams[streamNr];
-    return ins->available();
-}
-
-/**
- *
- */
-std::vector<unsigned char> XmppClient::inputStreamRead(int streamNr)
-{
-    XmppStream *ins = inputStreams[streamNr];
-    return ins->read();
-}
-
-/**
- *
- */
-bool XmppClient::inputStreamClosing(int streamNr)
-{
-    XmppStream *ins = inputStreams[streamNr];
-    if (ins->getState() == STREAM_CLOSING)
-        return true;
-    return false;
-}
-
-
-/**
- *
- */
-int XmppClient::inputStreamClose(int streamNr)
-{
-    int ret=1;
-    XmppStream *ins = inputStreams[streamNr];
-    if (ins->getState() == STREAM_CLOSING)
-        {
-        char *fmt =
-        "<iq type='result' from='%s' to='%s' id='%s'/>\n";
-        if (!write(fmt, jid.c_str(),  ins->getPeerId().c_str(),
-                    ins->getIqId().c_str()))
-            {
-            ret = -1;
-            }
-        }
-    ins->reset();
-    return ret;
-}
-
-
-
-
-//#######################
-//# FILE   TRANSFERS
-//#######################
-
-
-/**
- *
- */
-bool XmppClient::fileSend(const DOMString &destJidArg,
-                          const DOMString &offeredNameArg,
-                          const DOMString &fileNameArg,
-                          const DOMString &descriptionArg)
-{
-    DOMString destJid     = destJidArg;
-    DOMString offeredName = offeredNameArg;
-    DOMString fileName    = fileNameArg;
-    DOMString description = descriptionArg;
-
-    int i;
-    for (i=0; i<fileSendCount ; i++)
-        if (fileSends[i]->getState() == STREAM_AVAILABLE)
-            break;
-    if (i>=fileSendCount)
-        {
-        error("No available file send streams");
-        return false;
-        }
-    int fileSendNr = i;
-    XmppStream *outf = fileSends[fileSendNr];
-
-    outf->setState(STREAM_OPENING);
-
-    struct stat finfo;
-    if (stat(fileName.c_str(), &finfo)<0)
-        {
-        error("Cannot stat file '%s' for sending", fileName.c_str());
-        return false;
-        }
-    long fileLen = finfo.st_size;
-    if (!fileLen > 1000000)
-        {
-        error("'%s' too large", fileName.c_str());
-        return false;
-        }
-    if (!S_ISREG(finfo.st_mode))
-        {
-        error("'%s' is not a regular file", fileName.c_str());
-        return false;
-        }
-    FILE *f = fopen(fileName.c_str(), "rb");
-    if (!f)
-        {
-        error("cannot open '%s' for sending", fileName.c_str());
-        return false;
-        }
-    unsigned char *sendBuf = (unsigned char *)malloc(fileLen+1);
-    if (!sendBuf)
-        {
-        error("cannot cannot allocate send buffer for %s", fileName.c_str());
-        return false;
-        }
-    for (long i=0 ; i<fileLen && !feof(f); i++)
-        {
-        sendBuf[i] = fgetc(f);
-        }
-    fclose(f);
-
-    //## get the last path segment from the whole path
-    if (offeredName.size()<1)
-        {
-        int slashPos = -1;
-        for (unsigned int i=0 ; i<fileName.size() ; i++)
-            {
-            int ch = fileName[i];
-            if (ch == '/' || ch == '\\')
-                slashPos = i;
-            }
-        if (slashPos>=0 && slashPos<=(int)(fileName.size()-1))
-            {
-            offeredName = fileName.substr(slashPos+1,
-                                          fileName.size()-slashPos-1);
-            printf("offeredName:%s\n", offeredName.c_str());
-            }
-        }
-
-    char buf[32];
-    snprintf(buf, 31, "file%d", getMsgId());
-    DOMString iqId = buf;
-    outf->setIqId(iqId);
-
-    snprintf(buf, 31, "stream%d", getMsgId());
-    DOMString streamId = buf;
-    //outf->setStreamId(streamId);
-
-    DOMString hash = Md5::hashHex(sendBuf, fileLen);
-    printf("Hash:%s\n", hash.c_str());
-
-    outf->setPeerId(destJid);
-
-    char dtgBuf[81];
-    struct tm *timeVal = gmtime(&(finfo.st_mtime));
-    strftime(dtgBuf, 80, "%Y-%m-%dT%H:%M:%Sz", timeVal);
-
-    char *fmt =
-    "<iq type='set' id='%s' to='%s'>"
-    "<si xmlns='http://jabber.org/protocol/si' id='%s'"
-      " mime-type='text/plain'"
-      " profile='http://jabber.org/protocol/si/profile/file-transfer'>"
-    "<file xmlns='http://jabber.org/protocol/si/profile/file-transfer'"
-          " name='%s' size='%d' hash='%s' date='%s'><desc>%s</desc></file>"
-    "<feature xmlns='http://jabber.org/protocol/feature-neg'>"
-    "<x xmlns='jabber:x:data' type='form'>"
-    "<field var='stream-method' type='list-single'>"
-    //"<option><value>http://jabber.org/protocol/bytestreams</value></option>"
-    "<option><value>http://jabber.org/protocol/ibb</value></option>"
-    "</field></x></feature></si></iq>\n";
-    if (!write(fmt, iqId.c_str(), destJid.c_str(),
-         streamId.c_str(), offeredName.c_str(), fileLen,
-         hash.c_str(), dtgBuf, description.c_str()))
-        {
-        free(sendBuf);
-        return false;
-        }
-
-    int state = outf->getState();
-    for (int tim=0 ; tim<20 ; tim++)
-        {
-        printf("##### waiting for open\n");
-        if (state == STREAM_OPEN)
-            {
-            outf->reset();
-            break;
-            }
-        else if (state == STREAM_ERROR)
-            {
-            printf("ERROR\n");
-            outf->reset();
-            return false;
-            }
-        Thread::sleep(1000);
-        state = outf->getState();
-        }
-    if (state != STREAM_OPEN)
-        {
-        printf("TIMEOUT ERROR\n");
-        outf->reset();
-        return false;
-        }
-
-    //free up this reqource
-    outf->reset();
-
-    int  streamNr = outputStreamOpen(destJid, streamId);
-    if (streamNr<0)
-        {
-        error("cannot open output stream %s", streamId.c_str());
-        outf->reset();
-        return false;
-        }
-
-    int ret = outputStreamWrite(streamNr, sendBuf, fileLen);
-
-    if (ret<0)
-        {
-        }
-
-    outputStreamClose(streamNr);
-
-    free(sendBuf);
-    return true;
-}
-
-
-class FileSendThread : public Thread
-{
-public:
-
-    FileSendThread(XmppClient &par,
-                   const DOMString &destJidArg,
-                   const DOMString &offeredNameArg,
-                   const DOMString &fileNameArg,
-                   const DOMString &descriptionArg) : client(par)
-        {
-        destJid     = destJidArg;
-        offeredName = offeredNameArg;
-        fileName    = fileNameArg;
-        description = descriptionArg;
-        }
-
-    virtual ~FileSendThread() {}
-
-    void run()
-      {
-      client.fileSend(destJid, offeredName,
-                      fileName, description);
-      }
-
-private:
-
-    XmppClient &client;
-    DOMString destJid;
-    DOMString offeredName;
-    DOMString fileName;
-    DOMString description;
-};
-
-/**
- *
- */
-bool XmppClient::fileSendBackground(const DOMString &destJid,
-                                    const DOMString &offeredName,
-                                    const DOMString &fileName,
-                                    const DOMString &description)
-{
-    FileSendThread thread(*this, destJid, offeredName,
-                           fileName, description);
-    thread.start();
-    return true;
-}
-
-
-/**
- *
- */
-bool XmppClient::fileReceive(const DOMString &fromJid,
-                             const DOMString &iqId,
-                             const DOMString &streamId,
-                             const DOMString &fileName,
-                             long  fileSize,
-                             const DOMString &fileHash)
-{
-    char *fmt =
-    "<iq type='result' to='%s' id='%s'>"
-    "<si xmlns='http://jabber.org/protocol/si'>"
-    "<file xmlns='http://jabber.org/protocol/si/profile/file-transfer'/>"
-    "<feature xmlns='http://jabber.org/protocol/feature-neg'>"
-    "<x xmlns='jabber:x:data' type='submit'>"
-    "<field var='stream-method'>"
-    "<value>http://jabber.org/protocol/ibb</value>"
-    "</field></x></feature></si></iq>\n";
-    if (!write(fmt, fromJid.c_str(), iqId.c_str()))
-        {
-        return false;
-        }
-
-    int streamNr = inputStreamOpen(fromJid, streamId, iqId);
-    if (streamNr < 0)
-        {
-        return false;
-        }
-
-
-    Md5 md5;
-    FILE *f = fopen(fileName.c_str(), "wb");
-    if (!f)
-        {
-        return false;
-        }
-
-    while (true)
-        {
-        if (inputStreamAvailable(streamNr)<1)
-            {
-            if (inputStreamClosing(streamNr))
-                break;
-            pause(100);
-            continue;
-            }
-        std::vector<unsigned char> ret = inputStreamRead(streamNr);
-        std::vector<unsigned char>::iterator iter;
-        for (iter=ret.begin() ; iter!=ret.end() ; iter++)
-            {
-            unsigned char ch = *iter;
-            md5.append(&ch, 1);
-            fwrite(&ch, 1, 1, f);
-            }
-        }
-
-    inputStreamClose(streamNr);
-    fclose(f);
-
-    DOMString hash = md5.finishHex();
-    printf("received file hash:%s\n", hash.c_str());
-
-    return true;
-}
-
-
-
-class FileReceiveThread : public Thread
-{
-public:
-
-    FileReceiveThread(XmppClient &par,
-                      const DOMString &fromJidArg,
-                      const DOMString &iqIdArg,
-                      const DOMString &streamIdArg,
-                      const DOMString &fileNameArg,
-                      long  fileSizeArg,
-                      const DOMString &fileHashArg) : client(par)
-        {
-        fromJid     = fromJidArg;
-        iqId        = iqIdArg;
-        streamId    = streamIdArg;
-        fileName    = fileNameArg;
-        fileSize    = fileSizeArg;
-        fileHash    = fileHashArg;
-        }
-
-    virtual ~FileReceiveThread() {}
-
-    void run()
-      {
-      client.fileReceive(fromJid, iqId, streamId,
-                        fileName, fileSize, fileHash);
-      }
-
-private:
-
-    XmppClient &client;
-    DOMString fromJid;
-    DOMString iqId;
-    DOMString streamId;
-    DOMString fileName;
-    long      fileSize;
-    DOMString fileHash;
-};
-
-/**
- *
- */
-bool XmppClient::fileReceiveBackground(const DOMString &fromJid,
-                                       const DOMString &iqId,
-                                       const DOMString &streamId,
-                                       const DOMString &fileName,
-                                       long  fileSize,
-                                       const DOMString &fileHash)
-{
-    FileReceiveThread thread(*this, fromJid, iqId, streamId,
-                  fileName, fileSize, fileHash);
-    thread.start();
-    return true;
-}
-
-
-
-//########################################################################
-//# X M P P    G R O U P    C H A T
-//########################################################################
-
-/**
- *
- */
-XmppGroupChat::XmppGroupChat(const DOMString &groupJidArg)
-{
-    groupJid = groupJidArg;
-}
-
-/**
- *
- */
-XmppGroupChat::XmppGroupChat(const XmppGroupChat &other)
-{
-    groupJid = other.groupJid;
-    userList = other.userList;
-}
-
-/**
- *
- */
-XmppGroupChat::~XmppGroupChat()
-{
-}
-
-
-/**
- *
- */
-DOMString XmppGroupChat::getGroupJid()
-{
-    return groupJid;
-}
-
-
-void XmppGroupChat::userAdd(const DOMString &nick, 
-                            const DOMString &jid)
-{
-    std::vector<XmppUser>::iterator iter;
-    for (iter= userList.begin() ; iter!=userList.end() ; iter++)
-        {
-        if (iter->nick == nick)
-            return;
-        }
-    XmppUser user(jid, nick);
-    userList.push_back(user);
-}
-
-void XmppGroupChat::userShow(const DOMString &nick, 
-                             const DOMString &show)
-{
-    DOMString theShow = show;
-    if (theShow == "")
-        theShow = "available"; // a join message will now have a show
-    std::vector<XmppUser>::iterator iter;
-    for (iter= userList.begin() ; iter!=userList.end() ; iter++)
-        {
-        if (iter->nick == nick)
-            iter->show = theShow;
-        }
-}
-
-void XmppGroupChat::userDelete(const DOMString &nick)
-{
-    std::vector<XmppUser>::iterator iter;
-    for (iter= userList.begin() ; iter!=userList.end() ; )
-        {
-        if (iter->nick == nick)
-            iter = userList.erase(iter);
-        else
-            iter++;
-        }
-}
-
-std::vector<XmppUser> XmppGroupChat::getUserList() const
-{
-    return userList;
-}
-
-
-
-
-
-
-} //namespace Pedro
-//########################################################################
-//# E N D    O F     F I L E
-//########################################################################
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/jabber_whiteboard/pedroxmpp.h b/src/jabber_whiteboard/pedroxmpp.h
deleted file mode 100644 (file)
index d938a25..0000000
+++ /dev/null
@@ -1,1040 +0,0 @@
-#ifndef __XMPP_H__
-#define __XMPP_H__
-/*
- * API for the Pedro mini-XMPP client.
- *
- * Authors:
- *   Bob Jamison
- *
- * Copyright (C) 2005 Bob Jamison
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <stdio.h>
-#include <vector>
-
-#include <string>
-
-#include "pedrodom.h"
-
-namespace Pedro
-{
-
-typedef std::string DOMString;
-
-
-//########################################################################
-//# X M P P    E V E N T
-//########################################################################
-class XmppUser
-{
-public:
-    XmppUser()
-        {
-        }
-    XmppUser(const DOMString &jidArg, const DOMString &nickArg)
-        {
-        jid  = jidArg;
-        nick = nickArg;
-        }
-    XmppUser(const DOMString &jidArg,          const DOMString &nickArg,
-             const DOMString &subscriptionArg, const DOMString &groupArg)
-        {
-        jid          = jidArg;
-        nick         = nickArg;
-        subscription = subscriptionArg;
-        group        = groupArg;
-        }
-    XmppUser(const XmppUser &other)
-        {
-        jid          = other.jid;
-        nick         = other.nick;
-        subscription = other.subscription;
-        group        = other.group;
-        show         = other.show;
-        }
-    XmppUser &operator=(const XmppUser &other)
-        {
-        jid          = other.jid;
-        nick         = other.nick;
-        subscription = other.subscription;
-        group        = other.group;
-        show         = other.show;
-        return *this;
-        }
-    virtual ~XmppUser()
-        {}
-    DOMString jid;
-    DOMString nick;
-    DOMString subscription;
-    DOMString group;
-    DOMString show;
-};
-
-class XmppEvent
-{
-
-public:
-
-typedef enum
-    {
-    EVENT_NONE,
-    EVENT_STATUS,
-    EVENT_ERROR,
-    EVENT_CONNECTED,
-    EVENT_DISCONNECTED,
-    EVENT_PRESENCE,
-    EVENT_ROSTER,
-    EVENT_MESSAGE,
-    EVENT_MUC_JOIN,
-    EVENT_MUC_LEAVE,
-    EVENT_MUC_PRESENCE,
-    EVENT_MUC_MESSAGE,
-    EVENT_STREAM_RECEIVE_INIT,
-    EVENT_STREAM_RECEIVE,
-    EVENT_STREAM_RECEIVE_CLOSE,
-    EVENT_FILE_ACCEPTED,
-    EVENT_FILE_RECEIVE
-    } XmppEventType;
-
-
-    /**
-     *
-     */
-    XmppEvent(int type);
-
-    /**
-     *
-     */
-    XmppEvent(const XmppEvent &other);
-
-    /**
-     *
-     */
-    virtual XmppEvent &operator=(const XmppEvent &other);
-
-    /**
-     *
-     */
-    virtual ~XmppEvent();
-
-    /**
-     *
-     */
-    virtual void assign(const XmppEvent &other);
-
-    /**
-     *
-     */
-    virtual int getType() const;
-
-
-    /**
-     *
-     */
-    virtual DOMString getIqId() const;
-
-
-    /**
-     *
-     */
-    virtual void setIqId(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual DOMString getStreamId() const;
-
-
-    /**
-     *
-     */
-    virtual void setStreamId(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual bool getPresence() const;
-
-
-    /**
-     *
-     */
-    virtual void setPresence(bool val);
-
-    /**
-     *
-     */
-    virtual DOMString getShow() const;
-
-
-    /**
-     *
-     */
-    virtual void setShow(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual DOMString getStatus() const;
-
-    /**
-     *
-     */
-    virtual void setStatus(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual DOMString getTo() const;
-
-    /**
-     *
-     */
-    virtual void setTo(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual DOMString getFrom() const;
-
-    /**
-     *
-     */
-    virtual void setFrom(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual DOMString getGroup() const;
-
-    /**
-     *
-     */
-    virtual void setGroup(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual Element *getDOM() const;
-
-
-    /**
-     *
-     */
-    virtual void setDOM(const Element *val);
-
-    /**
-     *
-     */
-    virtual std::vector<XmppUser> getUserList() const;
-
-    /**
-     *
-     */
-    virtual void setUserList(const std::vector<XmppUser> &userList);
-
-    /**
-     *
-     */
-    virtual DOMString getFileName() const;
-
-
-    /**
-     *
-     */
-    virtual void setFileName(const DOMString &val);
-
-
-    /**
-     *
-     */
-    virtual DOMString getFileDesc() const;
-
-
-    /**
-     *
-     */
-    virtual void setFileDesc(const DOMString &val);
-
-
-    /**
-     *
-     */
-    virtual long getFileSize() const;
-
-
-    /**
-     *
-     */
-    virtual void setFileSize(long val);
-
-    /**
-     *
-     */
-    virtual DOMString getFileHash() const;
-
-    /**
-     *
-     */
-    virtual void setFileHash(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual DOMString getData() const;
-
-
-    /**
-     *
-     */
-    virtual void setData(const DOMString &val);
-
-private:
-
-    int eventType;
-
-    DOMString iqId;
-
-    DOMString streamId;
-
-    bool      presence;
-
-    DOMString show;
-
-    DOMString status;
-
-    DOMString to;
-
-    DOMString from;
-
-    DOMString group;
-
-    DOMString data;
-
-    DOMString fileName;
-    DOMString fileDesc;
-    long      fileSize;
-    DOMString fileHash;
-
-    Element *dom;
-
-    std::vector<XmppUser>userList;
-
-};
-
-
-//########################################################################
-//# X M P P    E V E N T    L I S T E N E R
-//########################################################################
-
-class XmppEventListener
-{
-public:
-
-    /**
-     *
-     */
-    XmppEventListener()
-        {}
-
-    /**
-     *
-     */
-    XmppEventListener(const XmppEventListener &other)
-        {}
-
-
-    /**
-     *
-     */
-    virtual ~XmppEventListener()
-        {}
-
-    /**
-     *
-     */
-    virtual void processXmppEvent(const XmppEvent &event)
-        {}
-
-};
-
-
-
-//########################################################################
-//# X M P P    E V E N T    T A R G E T
-//########################################################################
-
-class XmppEventTarget
-{
-public:
-
-    /**
-     *
-     */
-    XmppEventTarget();
-
-    /**
-     *
-     */
-    XmppEventTarget(const XmppEventTarget &other);
-
-    /**
-     *
-     */
-    virtual ~XmppEventTarget();
-
-
-    //###########################
-    //# M E S S A G E S
-    //###########################
-
-
-    /**
-     * Send an error message to all subscribers
-     */
-    void error(char *fmt, ...);
-
-
-    /**
-     * Send a status message to all subscribers
-     */
-    void status(char *fmt, ...);
-
-    //###########################
-    //# LISTENERS
-    //###########################
-
-    /**
-     *
-     */
-    virtual void dispatchXmppEvent(const XmppEvent &event);
-
-    /**
-     *
-     */
-    virtual void addXmppEventListener(const XmppEventListener &listener);
-
-    /**
-     *
-     */
-    virtual void removeXmppEventListener(const XmppEventListener &listener);
-
-    /**
-     *
-     */
-    virtual void clearXmppEventListeners();
-
-    /**
-     *
-     */
-    void eventQueueEnable(bool val);
-
-    /**
-     *
-     */
-    int eventQueueAvailable();
-
-    /**
-     *
-     */
-    XmppEvent eventQueuePop();
-
-
-private:
-
-    std::vector<XmppEventListener *> listeners;
-
-    std::vector<XmppEvent> eventQueue;
-    bool eventQueueEnabled;
-
-    static const int targetWriteBufLen = 2048;
-
-    char targetWriteBuf[targetWriteBufLen];
-};
-
-
-
-
-
-//########################################################################
-//# X M P P    C L I E N T
-//########################################################################
-
-
-class TcpSocket;
-class XmppChat;
-class XmppGroupChat;
-class XmppStream;
-
-class XmppClient : public XmppEventTarget
-{
-
-public:
-
-    //###########################
-    //# CONSTRUCTORS
-    //###########################
-
-    /**
-     *
-     */
-    XmppClient();
-
-    /**
-     *
-     */
-    XmppClient(const XmppClient &other);
-
-    /**
-     *
-     */
-    void assign(const XmppClient &other);
-
-    /**
-     *
-     */
-    virtual ~XmppClient();
-
-
-    //###########################
-    //# UTILITY
-    //###########################
-
-    /**
-     *
-     */
-    virtual bool pause(unsigned long millis);
-
-    /**
-     *
-     */
-    DOMString toXml(const DOMString &str);
-
-    //###########################
-    //# CONNECTION
-    //###########################
-
-    /**
-     *
-     */
-    virtual bool connect();
-
-    /**
-     *
-     */
-    virtual bool connect(DOMString host, int port,
-                         DOMString userName,
-                         DOMString password,
-                         DOMString resource);
-
-    /**
-     *
-     */
-    virtual bool disconnect();
-
-
-    /**
-     *
-     */
-    virtual bool write(char *fmt, ...);
-
-    /**
-     *
-     */
-    virtual bool isConnected()
-        { return connected; }
-
-    /**
-     *
-     */
-    virtual DOMString getHost()
-        { return host; }
-
-    /**
-     *
-     */
-    virtual void setHost(const DOMString &val)
-        { host = val; }
-
-    /**
-     *
-     */
-    virtual DOMString getRealm()
-        { return realm; }
-
-    /**
-     *
-     */
-    virtual void setRealm(const DOMString &val)
-        { realm = val; }
-
-    /**
-     *
-     */
-    virtual int getPort()
-        { return port; }
-
-    /**
-     *
-     */
-    virtual void setPort(int val)
-        { port = val; }
-
-    /**
-     *
-     */
-    virtual DOMString getUsername();
-
-    /**
-     *
-     */
-    virtual void setUsername(const DOMString &val);
-
-    /**
-     *
-     */
-    virtual DOMString getPassword()
-        { return password; }
-
-    /**
-     *
-     */
-    virtual void setPassword(const DOMString &val)
-        { password = val; }
-
-    /**
-     *
-     */
-    virtual DOMString getResource()
-        { return resource; }
-
-    /**
-     *
-     */
-    virtual void setResource(const DOMString &val)
-        { resource = val; }
-
-    /**
-     *
-     */
-    virtual DOMString getJid()
-        { return jid; }
-    /**
-     *
-     */
-    virtual int getMsgId()
-        { return msgId++; }
-
-    /**
-     *
-     */
-    bool processMessage(Element *root);
-
-    /**
-     *
-     */
-    bool processPresence(Element *root);
-
-    /**
-     *
-     */
-    bool processIq(Element *root);
-
-    /**
-     *
-     */
-    virtual bool receiveAndProcess();
-
-    /**
-     *
-     */
-    virtual bool receiveAndProcessLoop();
-
-    //#######################
-    //# ROSTER
-    //#######################
-
-    /**
-     *
-     */
-    bool rosterAdd(const DOMString &rosterGroup,
-                   const DOMString &otherJid,
-                   const DOMString &name);
-
-    /**
-     *
-     */
-    bool rosterDelete(const DOMString &otherJid);
-
-    /**
-     *
-     */
-    std::vector<XmppUser> getRoster();
-
-    /**
-     *
-     */
-    virtual void rosterShow(const DOMString &jid, const DOMString &show);
-    
-    //#######################
-    //# CHAT (individual)
-    //#######################
-
-    /**
-     *
-     */
-    virtual bool message(const DOMString &user, const DOMString &subj,
-                         const DOMString &text);
-
-    /**
-     *
-     */
-    virtual bool message(const DOMString &user, const DOMString &text);
-
-    /**
-     *
-     */
-    virtual bool presence(const DOMString &presence);
-
-    //#######################
-    //# GROUP CHAT
-    //#######################
-
-    /**
-     *
-     */
-    virtual bool groupChatCreate(const DOMString &groupJid);
-
-    /**
-     *
-     */
-    virtual void groupChatDelete(const DOMString &groupJid);
-
-    /**
-     *
-     */
-    bool groupChatExists(const DOMString &groupJid);
-
-    /**
-     *
-     */
-    virtual void groupChatsClear();
-
-    /**
-     *
-     */
-    virtual void groupChatUserAdd(const DOMString &groupJid,
-                                  const DOMString &nick,
-                                  const DOMString &jid);
-    /**
-     *
-     */
-    virtual void groupChatUserShow(const DOMString &groupJid,
-                                   const DOMString &nick,
-                                   const DOMString &show);
-
-    /**
-     *
-     */
-    virtual void groupChatUserDelete(const DOMString &groupJid,
-                                     const DOMString &nick);
-
-    /**
-     *
-     */
-    virtual std::vector<XmppUser>
-          XmppClient::groupChatGetUserList(const DOMString &groupJid);
-
-    /**
-     *
-     */
-    virtual bool groupChatJoin(const DOMString &groupJid,
-                               const DOMString &nick,
-                               const DOMString &pass);
-
-    /**
-     *
-     */
-    virtual bool groupChatLeave(const DOMString &groupJid,
-                                const DOMString &nick);
-
-    /**
-     *
-     */
-    virtual bool groupChatMessage(const DOMString &groupJid,
-                                  const DOMString &msg);
-
-    /**
-     *
-     */
-    virtual bool groupChatPrivateMessage(const DOMString &groupJid,
-                                         const DOMString &toNick,
-                                         const DOMString &msg);
-
-    /**
-     *
-     */
-    virtual bool groupChatPresence(const DOMString &groupJid,
-                                   const DOMString &nick,
-                                   const DOMString &presence);
-
-
-    //#######################
-    //# STREAMS
-    //#######################
-
-    typedef enum
-        {
-        STREAM_AVAILABLE,
-        STREAM_OPENING,
-        STREAM_OPEN,
-        STREAM_CLOSING,
-        STREAM_CLOSED,
-        STREAM_ERROR
-        } StreamStates;
-
-    /**
-     *
-     */
-    virtual int outputStreamOpen(const DOMString &jid,
-                                 const DOMString &streamId);
-
-    /**
-     *
-     */
-    virtual int outputStreamWrite(int streamId,
-                          const unsigned char *buf, unsigned long len);
-
-    /**
-     *
-     */
-    virtual int outputStreamClose(int streamId);
-
-    /**
-     *
-     */
-    virtual int inputStreamOpen(const DOMString &jid,
-                                const DOMString &streamId,
-                                const DOMString &iqId);
-
-    /**
-     *
-     */
-    virtual int inputStreamAvailable(int streamId);
-
-    /**
-     *
-     */
-    virtual std::vector<unsigned char> inputStreamRead(int streamId);
-
-    /**
-     *
-     */
-    virtual bool inputStreamClosing(int streamId);
-
-    /**
-     *
-     */
-    virtual int inputStreamClose(int streamId);
-
-
-    //#######################
-    //# FILE   TRANSFERS
-    //#######################
-
-    /**
-     *
-     */
-    virtual bool fileSend(const DOMString &destJid,
-                          const DOMString &offeredName,
-                          const DOMString &fileName,
-                          const DOMString &description);
-
-    /**
-     *
-     */
-    virtual bool fileSendBackground(const DOMString &destJid,
-                                    const DOMString &offeredName,
-                                    const DOMString &fileName,
-                                    const DOMString &description);
-
-    /**
-     *
-     */
-    virtual bool fileReceive(const DOMString &fromJid,
-                             const DOMString &iqId,
-                             const DOMString &streamId,
-                             const DOMString &fileName,
-                             long  fileSize,
-                             const DOMString &fileHash);
-    /**
-     *
-     */
-    virtual bool fileReceiveBackground(const DOMString &fromJid,
-                                       const DOMString &iqId,
-                                       const DOMString &streamId,
-                                       const DOMString &fileName,
-                                       long  fileSize,
-                                       const DOMString &fileHash);
-
-
-private:
-
-    void init();
-
-    DOMString host;
-
-    /**
-     * will be same as host, unless username is
-     * user@realm
-     */
-    DOMString realm;
-
-    int port;
-
-    DOMString username;
-
-    DOMString password;
-
-    DOMString resource;
-
-    DOMString jid;
-
-    int msgId;
-
-    TcpSocket *sock;
-
-    bool connected;
-
-    bool createSession();
-
-    bool checkConnect();
-
-    DOMString readStanza();
-
-    bool saslMd5Authenticate();
-
-    bool saslPlainAuthenticate();
-
-    bool saslAuthenticate();
-
-    bool iqAuthenticate(const DOMString &streamId);
-
-    bool keepGoing;
-
-    static const int writeBufLen = 2048;
-
-    unsigned char writeBuf[writeBufLen];
-
-    std::vector<XmppGroupChat *>groupChats;
-
-    static const int outputStreamCount = 16;
-
-    XmppStream *outputStreams[outputStreamCount];
-
-    static const int inputStreamCount = 16;
-
-    XmppStream *inputStreams[inputStreamCount];
-
-    static const int fileSendCount = 16;
-
-    XmppStream *fileSends[fileSendCount];
-
-    std::vector<XmppUser>roster;
-};
-
-
-
-
-//########################################################################
-//# X M P P    G R O U P    C H A T
-//########################################################################
-
-/**
- *
- */
-class XmppGroupChat
-{
-public:
-
-    /**
-     *
-     */
-    XmppGroupChat(const DOMString &groupJid);
-
-    /**
-     *
-     */
-    XmppGroupChat(const XmppGroupChat &other);
-
-    /**
-     *
-     */
-    virtual ~XmppGroupChat();
-
-    /**
-     *
-     */
-    virtual DOMString getGroupJid();
-
-    /**
-     *
-     */
-    virtual void userAdd(const DOMString &nick, 
-                         const DOMString &jid);
-    /**
-     *
-     */
-    virtual void userShow(const DOMString &nick,
-                          const DOMString &show);
-
-    /**
-     *
-     */
-    virtual void userDelete(const DOMString &nick);
-
-    /**
-     *
-     */
-    virtual std::vector<XmppUser> getUserList() const;
-
-
-private:
-
-    DOMString groupJid;
-
-    std::vector<XmppUser>userList;
-
-};
-
-
-
-
-
-
-
-
-
-
-} //namespace Pedro
-
-#endif /* __XMPP_H__ */
-
-//########################################################################
-//# E N D    O F     F I L E
-//########################################################################
-
diff --git a/src/jabber_whiteboard/serializer.cpp b/src/jabber_whiteboard/serializer.cpp
deleted file mode 100644 (file)
index 0949442..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-/**
- * Inkboard message -> XML::Event* serializer
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "xml/attribute-record.h"
-
-#include "jabber_whiteboard/serializer.h"
-
-#include "util/list.h"
-#include "util/share.h"
-
-#include "jabber_whiteboard/message-utilities.h"
-#include "jabber_whiteboard/message-tags.h"
-#include "jabber_whiteboard/typedefs.h"
-#include "jabber_whiteboard/node-tracker.h"
-#include "jabber_whiteboard/node-utilities.h"
-#include "jabber_whiteboard/node-tracker-observer.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-void
-Serializer::notifyChildAdded(XML::Node& node, XML::Node& child, XML::Node* prev)
-{
-       // do not recurse upon initial notification
-       this->_newObjectEventHelper(node, child, prev, false);
-       this->_nn.insert(&child);
-}
-
-void
-Serializer::_newObjectEventHelper(XML::Node& node, XML::Node& child, XML::Node* prev, bool recurse)
-{
-       // 1.  Check if we are tracking the parent node,
-       // and issue it an ID if we are not.
-       std::string parentid = this->_findOrGenerateNodeID(node);
-
-       // 2.  Check if the child node is a special node.
-       // Special nodes are nodes that should appear only once in a document.
-       // If it is, we do not want to generate a new ID for the child; we will use
-       // the existing ID.  Otherwise, we will generate a new ID for it, since we 
-       // have not yet seen it.
-       std::string childid;
-       if (this->_xnt->isSpecialNode(child.name())) {
-               childid = this->_xnt->get(child);
-       } else {
-               // If the child id already exists in the new node buffer, then we've already seen it.
-               if (!this->actions.tryToTrack(&child, NODE_ADD)) {
-                               return;
-               } else {
-                       childid = this->_xnt->generateKey();
-//                     childid = this->_findOrGenerateNodeID(child);
-               }
-       }
-
-       // 3.  Find this node's previous node, and, if it has one, retrieve its ID.
-       std::string previd;
-       if (prev) {
-               previd = this->_findOrGenerateNodeID(*prev);
-       }
-
-       // 4.  Serialize.
-       Glib::ustring childmsg = MessageUtilities::makeTagWithContent(MESSAGE_CHILD, childid);
-       Glib::ustring parentmsg = MessageUtilities::makeTagWithContent(MESSAGE_PARENT, parentid);
-       Glib::ustring namemsg = MessageUtilities::makeTagWithContent(MESSAGE_NAME, child.name());
-       Glib::ustring nodetype = MessageUtilities::makeTagWithContent(MESSAGE_NODETYPE, NodeUtilities::nodeTypeToString(child));
-
-       Glib::ustring prevmsg;
-       if (!previd.empty()) {
-               prevmsg = MessageUtilities::makeTagWithContent(MESSAGE_REF, previd);
-       }
-
-       Glib::ustring buf = MessageUtilities::makeTagWithContent(MESSAGE_NEWOBJ, childmsg + parentmsg + prevmsg + namemsg + nodetype);
-
-
-       this->_events.push_back(buf);
-
-       // 5.  Add the child node to the new nodes buffers.
-       this->newnodes.push_back(SerializedEventNodeAction(KeyNodePair(childid, &child), NODE_ADD));
-       this->newkeys[&child] = childid;
-       this->_parent_child_map[&child] = &node;
-
-       // 6.  Scan attributes and content.
-       Inkscape::Util::List<Inkscape::XML::AttributeRecord const> attrlist = child.attributeList();
-
-       for(; attrlist; attrlist++) {
-               this->notifyAttributeChanged(child, attrlist->key, Util::ptr_shared<char>(), attrlist->value);
-       }
-       
-       if (child.content()) {
-               this->notifyContentChanged(child, Util::ptr_shared<char>(), Util::share_string(child.content()));
-       }
-
-       this->_attributes_scanned.insert(childid);
-
-       // 7.  Repeat this process for each child of this child.
-       if (recurse && child.childCount() > 0) {
-               XML::Node* prev = child.firstChild();
-               for(XML::Node* ch = child.firstChild(); ch; ch = ch->next()) {
-                       if (ch == child.firstChild()) {
-                               // No prev node in this case.
-                               this->_newObjectEventHelper(child, *ch, NULL, true);
-                       } else {
-                               this->_newObjectEventHelper(child, *ch, prev, true);
-                               prev = ch;
-                       }
-               }
-       }
-
-       return;
-}
-
-
-void
-Serializer::notifyChildRemoved(XML::Node& node, XML::Node& child, XML::Node* prev)
-{
-       // 1.  Get the ID of the child.
-       std::string childid;
-
-       _pc_map_type::iterator i = this->_parent_child_map.find(&child);
-       if (i != this->_parent_child_map.end() && i->second != &node) {
-               // Don't look in local! Go for the tracker.
-               childid = this->_xnt->get(child);
-       } else if (i == this->_parent_child_map.end()) {
-               childid = this->_findOrGenerateNodeID(child);
-       } else if (i->second == &node) {
-               childid = this->_findOrGenerateNodeID(child);
-               this->_parent_child_map.erase(i);
-       } else {
-               childid = this->_findOrGenerateNodeID(child);
-       }
-       
-       // 2.  Double-deletes don't make any sense.  If we've seen this node already and if it's
-       // marked for deletion, return.
-       if (!this->actions.tryToTrack(&child, NODE_REMOVE)) {
-                       return;
-       } else {
-               // 2a.  Although we do not have to remove all child nodes of this subtree,
-               // we _do_ have to mark each child node as deleted.
-               this->_recursiveMarkAsRemoved(child);
-       }
-
-       // 2.  Mark this node as deleted.  We don't want to be faced with the possibility of 
-       // generating a new key for this deleted node, so insert it into both maps.
-       this->newnodes.push_back(SerializedEventNodeAction(KeyNodePair(childid, &child), NODE_REMOVE));
-       this->newkeys[&child] = childid;
-       this->_nn.erase(&child);
-       std::string parentid = this->_findOrGenerateNodeID(node);
-
-
-       // 4.  Serialize the event.
-       this->_attributes_scanned.erase(childid);
-       Glib::ustring childidmsg = MessageUtilities::makeTagWithContent(MESSAGE_CHILD, childid);
-       Glib::ustring parentidmsg = MessageUtilities::makeTagWithContent(MESSAGE_PARENT, parentid);
-       this->_events.push_back(MessageUtilities::makeTagWithContent(MESSAGE_DELETE, childidmsg + parentidmsg));
-}
-
-
-void
-Serializer::notifyChildOrderChanged(XML::Node& node, XML::Node& child, XML::Node* old_prev, XML::Node* new_prev)
-{
-       // 1.  Find the ID of the node, or generate it if it does not exist.
-       std::string nodeid = this->_findOrGenerateNodeID(child);
-       
-       // 2.  Find the ID of the parent of this node, or generate it if it does not exist.
-       std::string parentid = this->_findOrGenerateNodeID(*(child.parent()));
-
-       // 3.  Get the ID for the new child reference node, or generate it if it does not exist.
-       std::string newprevid = this->_findOrGenerateNodeID(*new_prev);
-
-       // 4.  Get the ID for the old child reference node, or generate it if it does not exist.
-       std::string oldprevid = this->_findOrGenerateNodeID(*old_prev);
-
-       // 5.  Serialize the event.
-       Glib::ustring nodeidmsg = MessageUtilities::makeTagWithContent(MESSAGE_ID, nodeid);
-       Glib::ustring parentidmsg = MessageUtilities::makeTagWithContent(MESSAGE_PARENT, parentid);
-       Glib::ustring oldprevidmsg = MessageUtilities::makeTagWithContent(MESSAGE_OLDVAL, oldprevid);
-       Glib::ustring newprevidmsg = MessageUtilities::makeTagWithContent(MESSAGE_NEWVAL, newprevid);
-
-       this->_events.push_back(MessageUtilities::makeTagWithContent(MESSAGE_ORDERCHANGE, nodeidmsg + parentidmsg + oldprevidmsg + newprevidmsg));
-}
-
-void
-Serializer::notifyContentChanged(XML::Node& node, Util::ptr_shared<char> old_content, Util::ptr_shared<char> new_content)
-{
-       // 1.  Find the ID of the node, or generate it if it does not exist.
-       std::string nodeid = this->_findOrGenerateNodeID(node);
-
-       std::string oldvalmsg, newvalmsg;
-
-       // 2.  If the old and new content are identical, don't send out this change.
-       // (identical meaning "same string" or "same string content")
-       if (old_content == new_content) {
-               return;
-       }
-
-       if (old_content.pointer() != NULL && new_content.pointer() != NULL) {
-               if (strcmp(old_content.pointer(), new_content.pointer()) == 0) {
-                       return;
-               }
-       }
-
-       // 3.  Serialize the event.
-       if (old_content.pointer() != NULL) {
-               oldvalmsg = MessageUtilities::makeTagWithContent(MESSAGE_OLDVAL, old_content.pointer());
-       }
-
-       if (new_content.pointer() != NULL) {
-               newvalmsg = MessageUtilities::makeTagWithContent(MESSAGE_NEWVAL, new_content.pointer());
-       }
-
-       Glib::ustring nodeidmsg = MessageUtilities::makeTagWithContent(MESSAGE_ID, nodeid);
-       this->_events.push_back(MessageUtilities::makeTagWithContent(MESSAGE_NODECONTENT, nodeidmsg + oldvalmsg + newvalmsg));
-}
-
-void
-Serializer::notifyAttributeChanged(XML::Node& node, GQuark name, Util::ptr_shared<char> old_value, Util::ptr_shared<char> new_value)
-{
-       // 1.  Find the ID of the node that has had an attribute modified, or generate it if it
-       // does not exist.
-       std::string nodeid = this->_findOrGenerateNodeID(node);
-
-       // Proceed with 2-4 if the node has not already been scanned by notifyChildAdded.
-       if (this->_attributes_scanned.find(nodeid) == this->_attributes_scanned.end()) {
-               // 2.  Convert the key to a string.
-               Glib::ustring key = g_quark_to_string(name);
-
-               // 3.  If oldval == newval, don't echo this change.
-               if (new_value.pointer() != NULL && old_value.pointer() != NULL) {
-                       if (strcmp(new_value.pointer(), old_value.pointer()) == 0) {
-                               return;
-                       }
-               }
-
-               // 4.  Serialize the event.
-               Glib::ustring keymsg = MessageUtilities::makeTagWithContent(MESSAGE_KEY, key);
-               Glib::ustring oldvalmsg, newvalmsg;
-
-               if (old_value.pointer() != NULL) {
-                       oldvalmsg = MessageUtilities::makeTagWithContent(MESSAGE_OLDVAL, old_value.pointer());
-               }
-
-               if (new_value.pointer() != NULL) {
-                       newvalmsg = MessageUtilities::makeTagWithContent(MESSAGE_NEWVAL, new_value.pointer());
-               }
-
-               Glib::ustring nodeidmsg = MessageUtilities::makeTagWithContent(MESSAGE_ID, nodeid);
-
-               this->_events.push_back(MessageUtilities::makeTagWithContent(MESSAGE_CHANGE, nodeidmsg + keymsg + oldvalmsg + newvalmsg));
-       }
-}
-
-void
-Serializer::synthesizeChildNodeAddEvents()
-{
-       _New_nodes_type::iterator i = this->_nn.begin();
-       for(; i != this->_nn.end(); ++i) {
-               XML::Node* parent = *i;
-               // The root of the subtree defined by parent has already been considered; now,
-               // recursively look at the rest of the tree.
-               XML::Node* prev = parent->firstChild();
-               for(XML::Node* ch = parent->firstChild(); ch; ch = ch->next()) {
-                       if (ch == parent->firstChild()) {
-                               this->_newObjectEventHelper(*parent, *ch, NULL, true);
-                       } else {
-                               this->_newObjectEventHelper(*parent, *ch, prev, true);
-                               prev = ch;
-                       }
-               }
-       }
-}
-
-
-void
-Serializer::_recursiveMarkAsRemoved(XML::Node& node)
-{
-       this->actions.tryToTrack(&node, NODE_REMOVE);
-
-       for(XML::Node* ch = node.firstChild(); ch; ch = ch->next()) {
-               this->_recursiveMarkAsRemoved(*ch);
-       }
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/serializer.h b/src/jabber_whiteboard/serializer.h
deleted file mode 100644 (file)
index 2884d43..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * Inkboard message -> XML::Event* serializer
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_MESSAGE_SERIALIZER_H__
-#define __WHITEBOARD_MESSAGE_SERIALIZER_H__
-
-#include "xml/node-observer.h"
-
-#include "util/share.h"
-
-#include "jabber_whiteboard/node-tracker.h"
-#include "jabber_whiteboard/typedefs.h"
-#include "jabber_whiteboard/node-tracker-observer.h"
-
-#include <map>
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-class Serializer : public NodeTrackerObserver {
-public:
-       Serializer(XMLNodeTracker* xnt) : NodeTrackerObserver(xnt) { }
-       ~Serializer() { }
-
-    void notifyChildAdded(XML::Node &node, XML::Node &child, XML::Node *prev);
-
-    void notifyChildRemoved(XML::Node &node, XML::Node &child, XML::Node *prev);
-
-    void notifyChildOrderChanged(XML::Node &node, XML::Node &child,
-                                         XML::Node *old_prev, XML::Node *new_prev);
-
-    void notifyContentChanged(XML::Node &node,
-                                      Util::ptr_shared<char> old_content,
-                                      Util::ptr_shared<char> new_content);
-
-    void notifyAttributeChanged(XML::Node &node, GQuark name,
-                                        Util::ptr_shared<char> old_value,
-                                        Util::ptr_shared<char> new_value);
-
-       void synthesizeChildNodeAddEvents();
-
-       SerializedEventList& getEventList()
-       {
-               return this->_events;
-       }
-
-       SerializedEventList getEventListCopy()
-       {
-               return this->_events;
-       }
-
-       SerializedEventList getAndClearEventList()
-       {
-               SerializedEventList ret = this->_events;
-               this->_events.clear();
-               return ret;
-       }
-
-       void clearEventList()
-       {
-               this->_events.clear();
-       }
-
-       void clearAttributesScannedBuffer()
-       {
-               this->_attributes_scanned.clear();
-       }
-
-       // Convenience method for resetting all stateful aspects of the serializer
-       void reset()
-       {       
-               g_log(NULL, G_LOG_LEVEL_DEBUG, "Clearing serializer buffers");
-               this->clearEventList();
-               this->_parent_child_map.clear();
-               this->_nn.clear();
-               this->clearNodeBuffers();
-               this->clearAttributesScannedBuffer();
-       }
-
-private:
-       typedef std::set< XML::Node* > _New_nodes_type;
-       typedef std::map< XML::Node*, XML::Node* > _pc_map_type;
-
-       SerializedEventList _events;
-       AttributesScannedSet _attributes_scanned;
-
-       _New_nodes_type _nn;
-       _pc_map_type _parent_child_map;
-
-       void _newObjectEventHelper(XML::Node& parent, XML::Node& child, XML::Node* prev, bool recurse);
-       void _recursiveMarkAsRemoved(XML::Node& node);
-};
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/session-file-player.cpp b/src/jabber_whiteboard/session-file-player.cpp
deleted file mode 100644 (file)
index cc4842e..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * Whiteboard session file playback mechanism
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-
-#include <glibmm.h>
-#include <glibmm/i18n.h>
-
-#include <gtkmm/textbuffer.h>
-
-#include "desktop-handles.h"
-#include "document.h"
-
-#include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/session-file.h"
-#include "jabber_whiteboard/session-file-player.h"
-#include "jabber_whiteboard/session-manager.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-SessionFilePlayer::SessionFilePlayer(unsigned int bufsz, SessionManager* sm) 
-{
-       this->_sm = sm;
-       this->_delay = 100;
-       this->_playing = false;
-       this->_curdir = FORWARD;
-
-       this->_current = this->_next = 0;
-       this->_sf = NULL;
-
-       if (sm->session_file() != NULL) {
-               this->_sf = sm->session_file();
-       } else {
-               g_warning("Cannot operate on NULL SessionFile.");
-       }
-}
-
-SessionFilePlayer::~SessionFilePlayer()
-{
-
-}
-
-void
-SessionFilePlayer::load(SessionFile* sm)
-{
-       this->stop();
-       if (this->_sm != NULL) {
-               this->_sf = sm;
-               this->_current = this->_next = 0;
-               this->_visited.clear();
-       }
-}
-
-SessionFile*
-SessionFilePlayer::unload()
-{
-       SessionFile* sf = this->_sf;
-       this->stop();
-       this->_sf = NULL;
-       return sf;
-}
-
-Glib::ustring const&
-SessionFilePlayer::filename()
-{
-       return this->_sf->filename();
-}
-
-Glib::ustring const&
-SessionFilePlayer::curmsg()
-{
-       return this->_curmsg;
-}
-
-void
-SessionFilePlayer::start()
-{
-       this->_playback_dispatcher = Glib::signal_timeout().connect(sigc::bind< 0 > (sigc::mem_fun(*(this), &SessionFilePlayer::step), this->_curdir), this->_delay);
-       this->_playing = true;
-}
-
-void
-SessionFilePlayer::stop()
-{
-       this->_playback_dispatcher.disconnect();
-       this->_playing = false;
-}
-
-void
-SessionFilePlayer::setDelay(unsigned int delay)
-{
-       this->_delay = delay;
-       if (this->_playing) {
-               this->stop();
-               this->start();
-       }
-}
-
-void
-SessionFilePlayer::setMessageOutputWidget(Glib::RefPtr<Gtk::TextBuffer> const& widgetptr)
-{
-       this->_outputwidget = widgetptr;
-}
-
-bool
-SessionFilePlayer::step(unsigned short dir)
-{
-       switch (dir) {
-               case FORWARD: {
-               //      Glib::ustring buf;
-                       this->_current = this->_next;
-                       this->_next = this->_sf->nextMessageFrom(this->_current, this->_curmsg);
-               if (this->_next == this->_current) {
-                               return false;
-                       } else {
-                               this->_visited.push_front(std::make_pair< gint64, gint64 >(this->_current, this->_curmsg.bytes()));
-                               this->_outputMessageToWidget();
-                               this->_sm->receiveChange(this->_curmsg);
-                               sp_document_done(sp_desktop_document(this->_sm->desktop()));
-                               this->_curdir = FORWARD;
-                               return true;
-                       }
-                       break;
-                                         }
-               case BACKWARD:
-                       if (this->_current == 0) {
-                               return false;
-                       } else {
-                               this->_visited.pop_front();
-                               std::pair< gint64, gint64 > last = this->_visited.front();
-                               this->_current = last.first;
-                               this->_next = last.first + last.second;
-                               this->_sf->nextMessageFrom(this->_current, this->_curmsg);
-                               this->_outputMessageToWidget();
-                               sp_document_undo(sp_desktop_document(this->_sm->desktop()));
-                               this->_curdir = BACKWARD;
-                               return true;
-                       }
-                       break;
-               default:
-                       return true;
-                       break;
-       }
-}
-
-void
-SessionFilePlayer::_outputMessageToWidget()
-{
-       if (this->_outputwidget) {
-               this->_outputwidget->set_text(this->_curmsg);
-       }
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/session-file-player.h b/src/jabber_whiteboard/session-file-player.h
deleted file mode 100644 (file)
index aa2e2b4..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * Whiteboard session file playback mechanism
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_SESSION_FILE_PLAYER_H__
-#define __WHITEBOARD_SESSION_FILE_PLAYER_H__
-
-#include <list>
-#include <glibmm/refptr.h>
-#include <glibmm/ustring.h>
-#include <gtkmm/textbuffer.h>
-#include <sigc++/sigc++.h>
-
-struct SPDesktop;
-
-namespace Inkscape {
-    namespace UI {
-       namespace Dialog {
-           class SessionPlaybackDialogImpl;
-       }
-    }
-    namespace Whiteboard {
-
-class SessionFile;
-class SessionManager;
-
-class SessionFilePlayer {
-friend class UI::Dialog::SessionPlaybackDialogImpl;
-
-public:
-       SessionFilePlayer(unsigned int bufsz, SessionManager* sm);
-       ~SessionFilePlayer();
-
-       void load(SessionFile* sm);
-       SessionFile* unload();
-
-       Glib::ustring const& filename();
-       Glib::ustring const& curmsg();
-
-       void start();
-       void stop();
-       void setDelay(unsigned int delay);
-       void setMessageOutputWidget(Glib::RefPtr<Gtk::TextBuffer> const& widgetptr);
-
-       static unsigned short const BACKWARD = 0;
-       static unsigned short const FORWARD = 1;
-
-private:
-       bool step(unsigned short dir);
-       void _outputMessageToWidget();
-
-       SessionManager* _sm;
-       SessionFile* _sf;
-
-       // Output widget refptr
-       Glib::RefPtr<Gtk::TextBuffer> _outputwidget;
-
-       // Playback signal
-       sigc::connection _playback_dispatcher;
-
-       // trackers
-       unsigned int _delay;
-       unsigned short _curdir;
-       bool _playing;
-       Glib::ustring _curmsg;
-
-       // (position, msgsize)
-       std::list< std::pair< gint64, gint64 > > _visited;
-       gint64 _current;
-       gint64 _next;
-
-       // noncopyable, nonassignable
-       SessionFilePlayer(SessionFilePlayer const&);
-       void operator=(SessionFilePlayer const&);
-};
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 85a3a3ec11212aa2ad231198e3a3b723b9c876af..854d61d107151bcc0b6a0dca58c5cdfe8710f43a 100644 (file)
@@ -9,11 +9,12 @@
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
+#include <glibmm.h>
+#include <gtkmm.h>
+
 #include "session-file-selector.h"
 
 #include <glibmm/i18n.h>
-#include <gtkmm/filechooserdialog.h>
-#include <gtkmm/stock.h>
 
 namespace Inkscape {
 
index fe097e4abb493868d9b933e96f8aef87bf5fe41c..4b1f70375305b7dfd0a4fe6ea76d1ecd2864ea23 100644 (file)
 #ifndef __WHITEBOARD_SESSION_FILE_SELECTOR_BOX_H__
 #define __WHITEBOARD_SESSION_FILE_SELECTOR_BOX_H__
 
-#include <glibmm/ustring.h>
-#include <gtkmm/checkbutton.h>
-#include <gtkmm/entry.h>
-#include <gtkmm/box.h>
+#include <glibmm.h>
+#include <gtkmm.h>
 
 namespace Inkscape {
 
diff --git a/src/jabber_whiteboard/session-file.cpp b/src/jabber_whiteboard/session-file.cpp
deleted file mode 100644 (file)
index 137e565..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- * Whiteboard session file object
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <glibmm.h>
-#include <glibmm/i18n.h>
-
-#include "util/list-container.h"
-
-#include "jabber_whiteboard/message-utilities.h"
-#include "jabber_whiteboard/node-utilities.h"
-#include "jabber_whiteboard/typedefs.h"
-
-#include "jabber_whiteboard/session-file.h"
-
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-SessionFile::SessionFile(Glib::ustring const& filename, bool reading, bool compress) : _filename(filename), _compress(compress), _reading(reading)
-{
-       try {
-
-               if (!reading) {
-                       this->fptr = Glib::IOChannel::create_from_file(filename, "w+");
-               } else {
-                       this->fptr = Glib::IOChannel::create_from_file(filename, "r");
-               }
-               this->_ateof = false;
-       } catch (Glib::FileError) {
-               throw;
-       }
-}
-
-SessionFile::~SessionFile() 
-{
-       if (!this->_reading) {
-               this->commit();
-       }
-       this->close();
-}
-
-gint64
-SessionFile::nextMessageFrom(gint64 from, Glib::ustring& buf)
-{
-       try {
-               Glib::ustring line;
-               Glib::IOStatus st;
-               Node part;
-
-               gint64 accum = from;
-               buf = "";
-               this->fptr->seek(accum, Glib::SEEK_TYPE_SET);
-
-               while(part.tag != MESSAGE_COMMIT) {
-                       st = this->fptr->read_line(line);
-                       if (st == Glib::IO_STATUS_EOF) {
-                               break;
-                       } else {
-                               accum += line.bytes();
-                               this->fptr->seek(accum);
-                               MessageUtilities::getFirstMessageTag(part, line);
-                               buf += line;
-                               line.clear();
-                       }
-               } 
-               
-               if (st == Glib::IO_STATUS_NORMAL) {
-                       // reset eof flag if successful
-                       this->_ateof = false;
-                       return from + buf.bytes();
-               } else {
-                       if (st == Glib::IO_STATUS_EOF) {
-                               this->_ateof = true;
-                       }
-                       return from;
-               }
-       } catch (Glib::IOChannelError e) {
-               g_warning("Could not read next message due to I/O error (error: %s)!", e.what().data());
-       } catch (Glib::ConvertError e) {
-               g_warning("Could not read next message due to charset conversion error (error: %s)!", e.what().data());
-       }
-
-       return from;
-}
-
-void
-SessionFile::addMessage(Glib::ustring const& message)
-{
-       Glib::ustring msg = message;
-       this->changes.push_back(msg);
-}
-
-void
-SessionFile::commit()
-{
-       if (!this->_reading) {
-               SessionQueue::iterator i = changes.begin();
-               for(; i != changes.end(); i++) {
-                       try {
-                               fptr->write(*i);
-                               changes.erase(i);
-                       } catch (Glib::IOChannelError e) {
-                               g_warning("Caught I/O exception (error string: %s) while committing change to session file %s.  Attempting to commit remaining changes; session file will be inconsistent with whiteboard session history.", e.what().c_str(), this->_filename.c_str());
-                       } catch (Glib::ConvertError e) {
-                               g_warning("Caught character set conversion error (error string: %s) while committing change to session file %s.  Attempting to commit remaining changes; session file will be inconsistent with whiteboard session history.", e.what().c_str(), this->_filename.c_str());
-                       }
-               }
-               fptr->write("\n");
-       }
-}
-
-void
-SessionFile::close()
-{
-       fptr->close(true);
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/session-file.h b/src/jabber_whiteboard/session-file.h
deleted file mode 100644 (file)
index 926d27a..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * Whiteboard session file object
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_SESSION_FILE_H__
-#define __WHITEBOARD_SESSION_FILE_H__
-
-#include <glibmm.h>
-#include "util/list-container.h"
-
-struct SPDesktop;
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-typedef Glib::RefPtr< Glib::IOChannel > SessionFilePtr;
-typedef Util::ListContainer< Glib::ustring const > SessionQueue;
-
-class SessionFile {
-public:
-       SessionFile(Glib::ustring const& filename, bool reading, bool compress);
-       ~SessionFile();
-
-       gint64 nextMessageFrom(gint64 from, Glib::ustring& buf);
-
-       void addMessage(Glib::ustring const& message);
-       void commit();
-       void close();
-
-       Glib::ustring const& filename()
-       {
-               return this->_filename;
-       }
-
-       bool isReadOnly()
-       {
-               return this->_reading;
-       }
-
-       bool eof()
-       {
-               return this->_ateof;
-       }
-
-private:
-       SessionQueue changes;
-       SessionFilePtr fptr;
-       Glib::ustring _filename;
-
-       bool _ateof;
-       bool _compress;
-       bool _reading;
-};
-
-}      
-
-}
-#endif
-
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 9ead6b60b70857f30049447faa9430a4363cd800..f8ca94612fcb80e99d798fcf72243104da4a4aea 100644 (file)
  *
  * Authors:
  * David Yip <yipdw@rose-hulman.edu>
+ * Bob Jamison (Pedro port)
  *
  * Copyright (c) 2005 Authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
-/*
-#include "inkscape.h"
-*/
-
-#include <cstring>
+#include <functional>
+#include <algorithm>
+#include <iostream>
 
+#include <gtkmm.h>
 #include <glibmm/i18n.h>
-#include <gtkmm/dialog.h>
-#include <gtkmm/messagedialog.h>
-#include <gtkmm/filechooserdialog.h>
-#include <gtkmm/stock.h>
-
-#include "gc-anchored.h"
 
-#include "prefs-utils.h"
-
-#include "xml/repr.h"
 #include "xml/node-observer.h"
 
-#include "util/ucompose.hpp"
-
-#include "message-context.h"
-#include "message-stack.h"
-#include "desktop-handles.h"
 #include "document.h"
-#include "document-private.h"
-#include "verbs.h"
+#include "desktop.h"
+#include "desktop-handles.h"
 
-#include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/typedefs.h"
-#include "jabber_whiteboard/deserializer.h"
-#include "jabber_whiteboard/message-utilities.h"
-#include "jabber_whiteboard/message-handler.h"
-#include "jabber_whiteboard/node-tracker.h"
-#include "jabber_whiteboard/jabber-handlers.h"
-#include "jabber_whiteboard/callbacks.h"
-#include "jabber_whiteboard/chat-handler.h"
-#include "jabber_whiteboard/session-file.h"
-#include "jabber_whiteboard/session-file-player.h"
+#include "jabber_whiteboard/message-verifier.h"
 #include "jabber_whiteboard/session-manager.h"
-#include "jabber_whiteboard/message-aggregator.h"
-#include "jabber_whiteboard/undo-stack-observer.h"
-#include "jabber_whiteboard/serializer.h"
-
-//#include "jabber_whiteboard/pedro/pedroxmpp.h"
+#include "jabber_whiteboard/inkboard-document.h"
+#include "jabber_whiteboard/new-inkboard-document.h"
 
-#include "jabber_whiteboard/message-node.h"
-#include "jabber_whiteboard/message-queue.h"
+#define INKBOARD_XMLNS "http://inkscape.org/inkboard"
 
 namespace Inkscape {
 
 namespace Whiteboard {
 
-SessionData::SessionData(SessionManager *sm)
-{
-       this->_sm = sm;
-       this->recipient = NULL;
-       this->connection = NULL;
-       this->ssl = NULL;
-       this->ignoreFurtherSSLErrors = false;
-       this->send_queue = new SendMessageQueue(sm);
-       this->sequence_number = 1;
-}
+//#########################################################################
+//# S E S S I O N    M A N A G E R
+//#########################################################################
 
-SessionData::~SessionData()
-{
-       this->receive_queues.clear();
+SessionManager *sessionManagerInstance = NULL;
 
-       if (this->send_queue) {
-               delete this->send_queue;
-       }
+void SessionManager::showClient()
+{
+       SessionManager::instance().gui.show();
 }
 
-SessionManager::SessionManager(::SPDesktop *desktop) 
+SessionManager&
+SessionManager::instance()
 {
-
-       // Initialize private members to NULL to facilitate deletion in destructor
-       this->_myDoc = NULL;
-       this->session_data = NULL;
-       this->_myCallbacks = NULL;
-       this->_myTracker = NULL;
-       this->_myChatHandler = NULL;
-       this->_mySessionFile = NULL;
-       this->_mySessionPlayer = NULL;
-       this->_myMessageHandler = NULL;
-       this->_myUndoObserver = NULL;
-       this->_mySerializer = NULL;
-       this->_myDeserializer = NULL;
-
-       this->setDesktop(desktop);
-
-       if (this->_myDoc == NULL) {
-               g_error("Initializing SessionManager on null document object!");
-       }
-
-
-#ifdef WIN32
-    //# lm_initialize() must be called before any network code
-/*
-    if (!lm_initialize_called) {
-        lm_initialize();
-        lm_initialize_called = true;
-       }
-*/
-#endif
-
-       this->_setVerbSensitivity(INITIAL);
+    if (!sessionManagerInstance)
+        sessionManagerInstance = new SessionManager();
+       return *sessionManagerInstance;
 }
 
-SessionManager::~SessionManager()
+SessionManager::SessionManager() 
 {
+    sequenceNumber = 0L;
+    getClient().addXmppEventListener(*this);
 
-       if (this->session_data) {
-               if (this->session_data->status[IN_WHITEBOARD]) {
-                       // also calls closeSession
-                       this->disconnectFromDocument();
-               }
-               this->disconnectFromServer();
-
-               if (this->session_data->status[LOGGED_IN]) {
-                       // TODO: unref message handlers
-               }
-       }
-
-       if (this->_mySessionFile) {
-               delete this->_mySessionPlayer;
-               delete this->_mySessionFile;
-       }
-
-       delete this->_myChatHandler;
-
-
-       // Deletion of _myTracker is done in closeSession;
-       // no need to do it here.
-
-       // Deletion is handled separately from session teardown and server disconnection
-       // because some teardown methods (e.g. closeSession) require access to members that we will
-       // be deleting. Separating deletion from teardown means that we do not have
-       // to worry (as much) about proper ordering of the teardown sequence.  (We still need
-       // to ensure that destructors in each object being deleted have access to all the
-       // members they need, though.)
-
-       // Stop dispatchers
-       if (this->_myCallbacks) {
-               this->stopSendQueueDispatch();
-               this->stopReceiveQueueDispatch();
-               delete this->_myCallbacks;
-       }
-
-       delete this->_myMessageHandler;
-
-       delete this->session_data;
-
-       Inkscape::GC::release(this->_myDoc);
-
+       this->_check_pending_invitations = Glib::signal_timeout().connect(sigc::mem_fun(*this, &SessionManager::_checkInvitationQueue), 50);
+       this->_check_invitation_responses = Glib::signal_timeout().connect(sigc::mem_fun(*this, &SessionManager::_checkInvitationResponseQueue), 50);
 }
 
-void
-SessionManager::setDesktop(::SPDesktop* desktop)
+SessionManager::~SessionManager()
 {
-       this->_myDesktop = desktop;
-       if (this->_myDoc != NULL) {
-               Inkscape::GC::release(this->_myDoc);
-       }
-       if (sp_desktop_document(desktop) != NULL) {
-               this->_myDoc = sp_desktop_document(desktop);
-               Inkscape::GC::anchor(this->_myDoc);
-       }
+    getClient().removeXmppEventListener(*this);
+    getClient().disconnect();
 }
 
-int
-SessionManager::initializeConnection(Glib::ustring const& server, Glib::ustring const& port, bool usessl)
+unsigned long SessionManager::getSequenceNumber()
 {
-       GError* error = NULL;
-
-       if (!this->session_data) {
-               this->session_data = new SessionData(this);
-       }
-
-       if (!this->_myMessageHandler) {
-               this->_myMessageHandler = new MessageHandler(this);
-       }
-
-       // Connect to server
-       // We need to check to see if this object already exists, because
-       // the user may be reusing an old connection that failed due to e.g.
-       // authentication failure.
-       if (this->session_data->connection) {
-               lm_connection_close(this->session_data->connection, &error);
-               lm_connection_unref(this->session_data->connection);
-       }
-
-       this->session_data->connection = lm_connection_new(server.c_str());
-       this->session_data->chat_server = server;
-
-       lm_connection_set_port(this->session_data->connection, atoi(port.c_str()));
-
-        g_log(NULL, G_LOG_LEVEL_DEBUG, "Opened connection to %s at port %s.  Connecting...",
-                    server.c_str(), port.c_str());
-
-       if (usessl) {
-               if (lm_ssl_is_supported()) {
-                       this->session_data->ssl = lm_ssl_new(NULL, ssl_error_handler, reinterpret_cast< gpointer >(this), NULL);
-
-                       lm_ssl_ref(this->session_data->ssl);
-               } else {
-                       return SSL_INITIALIZATION_ERROR;
-               }
-               lm_connection_set_ssl(this->session_data->connection, this->session_data->ssl);
-       }
-
-       // Send authorization
-       //lm_connection_set_jid(this->session_data->connection, jid.c_str());
-
-       //      TODO:
-       //      Asynchronous connection and authentication would be nice,
-       //      but it's a huge mess of mixing C callbacks and C++ method calls.
-       //      I've tried to do it and only managed to severely destabilize the Jabber
-       //      server connection routines.
-       //
-       //      This, of course, is an invitation to anyone more capable than me
-       //      to convert this from synchronous to asynchronous Loudmouth calls.
-       if (!lm_connection_open_and_block(this->session_data->connection, &error)) {
-               if (error != NULL) {
-                       std::cout << "Failed to open: " <<  error->message << std::endl;
-               }
-               return FAILED_TO_CONNECT;
-       }
-
-       //On successful connect, remember info
-       prefs_set_string_attribute("whiteboard.server", "name", server.c_str());
-       prefs_set_string_attribute("whiteboard.server", "port", port.c_str());
-       prefs_set_int_attribute("whiteboard.server", "ssl", (usessl) ? 1 : 0);
-
-       return CONNECT_SUCCESS;
+    return sequenceNumber++;
 }
 
-std::vector<Glib::ustring>
-SessionManager::getRegistrationInfo()
-{
-       GError* error = NULL;
-       xmlDoc *doc = NULL;
-       xmlNode *root_element = NULL;
-       xmlNode *cur_node = NULL;
-
-       LmMessage *reply,*request;
-       LmMessageNode  *n;
-
-       std::vector<Glib::ustring> registerelements; 
-
-       request = lm_message_new_with_sub_type(NULL,LM_MESSAGE_TYPE_IQ,LM_MESSAGE_SUB_TYPE_GET);
-       n = lm_message_node_add_child (request->node, "query", NULL);
-       lm_message_node_set_attributes (n, "xmlns", "jabber:iq:register", NULL);
-
-       reply = lm_connection_send_with_reply_and_block(this->session_data->connection, request, &error);
-       if (error != NULL) {
-               return registerelements;
-       }
-
-       n = lm_message_get_node(reply);
-
-       Glib::ustring content = static_cast< Glib::ustring >(lm_message_node_to_string(lm_message_node_get_child(n,"query")));
-       doc = xmlReadMemory(content.c_str(),content.size(), "noname.xml", NULL, 0);
-
-       if (doc == NULL) {
-               g_warning("Failed to parse document\n");
-               return registerelements;
-       }
-
-       root_element = xmlDocGetRootElement(doc);
-
-       for (cur_node = root_element->children; cur_node; cur_node = cur_node->next) {
-               Glib::ustring name = static_cast< Glib::ustring >((char const *)cur_node->name);
-               if (cur_node->type == XML_ELEMENT_NODE && name != "instructions" 
-                       && name != "username" && name != "password" ) {
-                       registerelements.push_back(name);
-               }
-       }
-
-       xmlFreeDoc(doc);
-       xmlCleanupParser();
-
-       return registerelements;
+bool
+SessionManager::send(const Glib::ustring &destJid, 
+                                        const MessageType type,
+                     const Glib::ustring &data)
+{
+    Pedro::DOMString xmlData = Pedro::Parser::encode(data);
+    char *fmt=
+    "<message type='chat' from='%s' to='%s' id='ink_%d'>"
+    "<inkboard xmlns='%s' "
+    "protocol='%d' type='%d' seq='%d'><x:inkboard-data>%s</x:inkboard-data></inkboard>"
+    "<body></body>"
+    "</message>";
+    if (!getClient().write(fmt, 
+                           getClient().getJid().c_str(),
+                           destJid.c_str(),
+                           getClient().getMsgId(),
+                           INKBOARD_XMLNS,
+                           2,
+                           (MessageType)type,
+                           getSequenceNumber(),
+                           xmlData.c_str()
+                           ))
+        {
+        return false;
+        }
+        
+    return true;
 }
 
-int
-SessionManager::registerWithServer(Glib::ustring const& username, Glib::ustring const& pw, 
-                               std::vector<Glib::ustring> key, std::vector<Glib::ustring> val)
-{
-
-       GError* error = NULL;
-       
-       LmMessage *request,*reply;
-       LmMessageNode  *n;
-
-       request = lm_message_new_with_sub_type(NULL,LM_MESSAGE_TYPE_IQ,LM_MESSAGE_SUB_TYPE_SET);
-       n = lm_message_node_add_child (request->node, "query", NULL);
-       lm_message_node_set_attributes (n, "xmlns", "jabber:iq:register", NULL);
-
-       lm_message_node_add_child(n,"username",username.c_str());
-       lm_message_node_add_child(n,"password",pw.c_str());
-
-       for(unsigned i=0;i<key.size();i++)
-       {       
-               lm_message_node_add_child(n, (key[i]).c_str(),(val[i]).c_str());
-       }
-       
-       
-       reply = lm_connection_send_with_reply_and_block(this->session_data->connection, request, &error);
-       if (error != NULL || lm_message_get_type(reply) != LM_MESSAGE_SUB_TYPE_RESULT) {
-               return INVALID_AUTH;
-       }
-
-       this->session_data->jid = username + "@" + (this->session_data->chat_server.c_str()) + "/" + RESOURCE_NAME;
-
-       prefs_set_string_attribute("whiteboard.server", "username", username.c_str());
-
-       return this->finaliseConnection();
+bool
+SessionManager::sendGroup(const Glib::ustring &groupJid,
+                                                 const MessageType type,
+                          const Glib::ustring &data)
+{
+    Pedro::DOMString xmlData = Pedro::Parser::encode(data);
+    char *fmt=
+    "<message type='groupchat' from='%s' to='%s' id='ink_%d'>"
+    "<inkboard xmlns='%s' "
+    "protocol='%d' type='%d' seq='%d'><x:inkboard-data>%s</x:inkboard-data></inkboard>"
+    "<body></body>"
+    "</message>";
+    if (!getClient().write(fmt,
+                           getClient().getJid().c_str(),
+                           groupJid.c_str(),
+                           getClient().getMsgId(),
+                           INKBOARD_XMLNS,
+                           2,
+                           type,
+                           getSequenceNumber(),
+                           xmlData.c_str()
+                           ))
+        {
+        return false;
+        }
+        
+    return true;
 }
 
-int
-SessionManager::connectToServer(Glib::ustring const& server, Glib::ustring const& port, 
-                               Glib::ustring const& entered_username, Glib::ustring const& pw, bool usessl)
-{
-       GError* error = NULL;
-       Glib::ustring username;
-       Glib::ustring jid;
-
-       initializeConnection(server,port,usessl);
-
-       Glib::ustring::size_type atPos = entered_username.find('@');
-
-     if (atPos != Glib::ustring::npos) {
-               jid += entered_username;
-               username = entered_username.substr(0, atPos);
-       } else {
-               jid += entered_username + "@" + server + "/" + RESOURCE_NAME;
-               username = entered_username;
-       }
-       this->session_data->jid = jid;
-
-       if (!lm_connection_authenticate_and_block(this->session_data->connection, username.c_str(), pw.c_str(), RESOURCE_NAME, &error)) {
-               if (error != NULL) {
-                       g_warning("Failed to authenticate: %s", error->message);
-               }
-               lm_connection_close(this->session_data->connection, NULL);
-               lm_connection_unref(this->session_data->connection);
-               this->session_data->connection = NULL;
-               return INVALID_AUTH;
-       }
-
-        g_log(NULL, G_LOG_LEVEL_DEBUG, "Successfully authenticated.");
-
-       return this->finaliseConnection();
+void
+SessionManager::processXmppEvent(const Pedro::XmppEvent &event)
+{
+    int type = event.getType();
+
+    switch (type) {
+        case Pedro::XmppEvent::EVENT_STATUS:
+            {
+            break;
+            }
+        case Pedro::XmppEvent::EVENT_ERROR:
+            {
+            break;
+            }
+        case Pedro::XmppEvent::EVENT_CONNECTED:
+            {
+            break;
+            }
+        case Pedro::XmppEvent::EVENT_DISCONNECTED:
+            {
+            break;
+            }
+        case Pedro::XmppEvent::EVENT_MESSAGE:
+            {
+            printf("## SM message:%s\n", event.getFrom().c_str());
+            Pedro::Element *root = event.getDOM();
+
+            if (root)
+                {
+                if (root->getTagAttribute("inkboard", "xmlns") ==
+                               INKBOARD_XMLNS)
+                    {
+                        _processInkboardEvent(event);
+                    }
+                }
+            break;
+            }
+        case Pedro::XmppEvent::EVENT_PRESENCE:
+            {
+            break;
+            }
+        case Pedro::XmppEvent::EVENT_MUC_MESSAGE:
+            {
+            printf("## SM MUC message:%s\n", event.getFrom().c_str());
+            Pedro::Element *root = event.getDOM();
+            if (root)
+                {
+                if (root->getTagAttribute("inkboard", "xmlns") ==
+                               INKBOARD_XMLNS)
+                    {
+                        _processInkboardEvent(event);
+                    }
+                }
+            break;
+            }
+        case Pedro::XmppEvent::EVENT_MUC_JOIN:
+            {
+            break;
+            }
+        case Pedro::XmppEvent::EVENT_MUC_LEAVE:
+            {
+            break;
+            }
+        case Pedro::XmppEvent::EVENT_MUC_PRESENCE:
+            {
+            break;
+            }
+        default:
+            {
+            break;
+            }
+    }
 }
 
-int 
-SessionManager::finaliseConnection()
+/**
+ * Initiates a shared session with a user or conference room.
+ * 
+ * \param to The recipient to which this desktop will be linked, specified as a JID.
+ * \param type Type of the session; i.e. private message or group chat.
+ */
+void
+SessionManager::doShare(Glib::ustring const& to, SessionType type)
 {
-
-       GError* error = NULL;
-       LmMessage* m;
-       LmMessageHandler* mh;
-
-       // Register message handler for presence messages
-       mh = lm_message_handler_new((LmHandleMessageFunction)presence_handler, reinterpret_cast< gpointer >(this->_myMessageHandler), NULL);
-       lm_connection_register_message_handler(this->session_data->connection, mh, LM_MESSAGE_TYPE_PRESENCE, LM_HANDLER_PRIORITY_NORMAL);
-
-       // Register message handler for stream error messages
-       mh = lm_message_handler_new((LmHandleMessageFunction)stream_error_handler, reinterpret_cast< gpointer >(this->_myMessageHandler), NULL);
-       lm_connection_register_message_handler(this->session_data->connection, mh, LM_MESSAGE_TYPE_STREAM_ERROR, LM_HANDLER_PRIORITY_NORMAL);
-
-       // Register message handler for chat messages
-       mh = lm_message_handler_new((LmHandleMessageFunction)default_handler, reinterpret_cast< gpointer >(this->_myMessageHandler), NULL);
-       lm_connection_register_message_handler(this->session_data->connection, mh, LM_MESSAGE_TYPE_MESSAGE, LM_HANDLER_PRIORITY_NORMAL);
-
-       // Send presence message to server
-       m = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_PRESENCE, LM_MESSAGE_SUB_TYPE_NOT_SET);
-       if (!lm_connection_send(this->session_data->connection, m, &error)) {
-               if (error != NULL) {
-                       g_warning("Presence message could not be sent: %s", error->message);
+    SPDesktop* dt = createInkboardDesktop(to, type);
+       if (dt != NULL) {
+               InkboardDocument* doc = dynamic_cast< InkboardDocument* >(sp_desktop_document(dt)->rdoc);
+               if (doc != NULL) {
+                       doc->startSessionNegotiation();
                }
-               lm_connection_close(this->session_data->connection, NULL);
-               lm_connection_unref(this->session_data->connection);
-               this->session_data->connection = NULL;
-               return FAILED_TO_CONNECT;
        }
-
-       this->session_data->status.set(LOGGED_IN, 1);
-
-       this->_myCallbacks = new Callbacks(this);
-
-       lm_message_unref(m);
-
-       this->_setVerbSensitivity(ESTABLISHED_CONNECTION);
-
-       return CONNECT_SUCCESS;
 }
 
-LmSSLResponse
-SessionManager::handleSSLError(LmSSL* ssl, LmSSLStatus status)
+/**
+ * Clone of sp_file_new and all related subroutines and functions,
+ * with appropriate modifications to use the Inkboard document class.
+ *
+ * \param to The JID to which this Inkboard document will be connected.
+ * \return A pointer to the created desktop, or NULL if a new desktop could not be created.
+ */
+SPDesktop*
+SessionManager::createInkboardDesktop(Glib::ustring const& to, SessionType type)
 {
-       if (this->session_data->ignoreFurtherSSLErrors) {
-               return LM_SSL_RESPONSE_CONTINUE;
-       }
-
-       Glib::ustring msg;
-
-       // TODO: It'd be nice to provide the user with additional information in some cases,
-       // like fingerprints, hostname, etc.
-       switch(status) {
-               case LM_SSL_STATUS_NO_CERT_FOUND:
-                       msg = _("No SSL certificate was found.");
-                       break;
-               case LM_SSL_STATUS_UNTRUSTED_CERT:
-                       msg = _("The SSL certificate provided by the Jabber server is untrusted.");
-                       break;
-               case LM_SSL_STATUS_CERT_EXPIRED:
-                       msg = _("The SSL certificate provided by the Jabber server is expired.");
-                       break;
-               case LM_SSL_STATUS_CERT_NOT_ACTIVATED:
-                       msg = _("The SSL certificate provided by the Jabber server has not been activated.");
-                       break;
-               case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH:
-                       msg = _("The SSL certificate provided by the Jabber server contains a hostname that does not match the Jabber server's hostname.");
-                       break;
-               case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH:
-                       msg = _("The SSL certificate provided by the Jabber server contains an invalid fingerprint.");
-                       break;
-               case LM_SSL_STATUS_GENERIC_ERROR:
-                       msg = _("An unknown error occurred while setting up the SSL connection.");
-                       break;
-       }
+// Create document (sp_repr_document_new clone)
+    SPDocument* doc = makeInkboardDocument(g_quark_from_static_string("xml"), "svg:svg", type, to);
+    g_return_val_if_fail(doc != NULL, NULL);
 
-       // TRANSLATORS: %1 is the message that describes the specific error that occurred when
-       // establishing the SSL connection.
-       Glib::ustring mainmsg = String::ucompose(_("<span weight=\"bold\" size=\"larger\">%1</span>\n\nDo you wish to continue connecting to the Jabber server?"), msg);
-
-       Gtk::MessageDialog dlg(mainmsg, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE, false);
-       dlg.add_button(_("Continue connecting and ignore further errors"), 0);
-       dlg.add_button(_("Continue connecting, but warn me of further errors"), 1);
-       dlg.add_button(_("Cancel connection"), 2);
-
-       switch(dlg.run()) {
-               case 0:
-                       this->session_data->ignoreFurtherSSLErrors = true;
-                        /* FALL-THROUGH */
-               case 1:
-                       return LM_SSL_RESPONSE_CONTINUE;
+    InkboardDocument* inkdoc = dynamic_cast< InkboardDocument* >(doc->rdoc);
+    if (inkdoc == NULL) { // this shouldn't ever happen...
+        return NULL;
+    }
 
-               default:
-                       return LM_SSL_RESPONSE_STOP;
-       }
+// Create desktop and attach document
+    SPDesktop *dt = makeInkboardDesktop(doc);
+    _inkboards.push_back(Inkboard_record_type(to, inkdoc));
+    return dt;
 }
 
 void
-SessionManager::disconnectFromServer()
-{
-       if (this->session_data->connection) 
-       {
-               GError* error = NULL;
-
-               LmMessage *m;
-               this->disconnectFromDocument();
-               m = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_PRESENCE, LM_MESSAGE_SUB_TYPE_UNAVAILABLE);
-               if (!lm_connection_send(this->session_data->connection, m, &error)) {
-                       g_warning("Could not send unavailable presence message: %s", error->message);
-               }
-
-               lm_message_unref(m);
-               lm_connection_close(this->session_data->connection, NULL);
-               lm_connection_unref(this->session_data->connection);
-               if (this->session_data->ssl) {
-                       lm_ssl_unref(this->session_data->ssl);
-               }
+SessionManager::terminateInkboardSession(Glib::ustring const& to)
+{
+       std::cout << "Terminating Inkboard session to " << to << std::endl;
+    Inkboards_type::iterator i = _inkboards.begin();
+    for(; i != _inkboards.end(); ++i) {
+        if ((*i).first == to) {
+            break;
+        }
+    }
 
-               this->session_data->connection = NULL;
-               this->session_data->ssl = NULL;
-               this->_setVerbSensitivity(INITIAL);
-       }
+    if (i != _inkboards.end()) {
+               std::cout << "Erasing Inkboard session to " << to << std::endl;
+        (*i).second->terminateSession();
+        _inkboards.erase(i);
+    }
 }
 
-void
-SessionManager::disconnectFromDocument()
+InkboardDocument*
+SessionManager::getInkboardSession(Glib::ustring const& to)
 {
-       if (this->session_data->status[IN_WHITEBOARD] || !this->session_data->status[IN_CHATROOM]) {
-               this->sendMessage(DISCONNECTED_FROM_USER_SIGNAL, 0, "", this->session_data->recipient, false);
-       }
-       this->closeSession();
-       this->_setVerbSensitivity(DISCONNECTED_FROM_SESSION);
+    Inkboards_type::iterator i = _inkboards.begin();
+    for(; i != _inkboards.end(); ++i) {
+        if ((*i).first == to) {
+            return (*i).second;
+        }
+    }
+    return NULL;
 }
 
 void
-SessionManager::closeSession()
+SessionManager::_processInkboardEvent(Pedro::XmppEvent const& event)
 {
+    Pedro::Element* root = event.getDOM();
 
-       if (this->session_data->status[IN_WHITEBOARD]) {
-               this->session_data->status.set(IN_WHITEBOARD, 0);
-               this->session_data->receive_queues.clear();
-               this->session_data->send_queue->clear();
-               this->stopSendQueueDispatch();
-               this->stopReceiveQueueDispatch();
-       }
-
-       if (this->_myUndoObserver) {
-               this->_myDoc->removeUndoObserver(*this->_myUndoObserver);
+       if (root == NULL) {
+               g_warning("Received null DOM; ignoring message.");
+               return;
        }
 
-       delete this->_myUndoObserver;
-       delete this->_mySerializer;
-       delete this->_myDeserializer;
-
-       this->_myUndoObserver = NULL;
-       this->_mySerializer = NULL;
-       this->_myDeserializer = NULL;
-
-       if (this->_myTracker) {
-               delete this->_myTracker;
-               this->_myTracker = NULL;
-       }
+    Pedro::DOMString type = root->getTagAttribute("inkboard", "type");
+    Pedro::DOMString seq = root->getTagAttribute("inkboard", "seq");
+    Pedro::DOMString protover = root->getTagAttribute("inkboard", "protocol");
 
+    if (type.empty() || seq.empty() || protover.empty()) {
+        g_warning("Received incomplete Inkboard message (missing type, protocol, or sequence number); ignoring message.");
+        return;
+    }
 
-       this->setRecipient(NULL);
-}
+    MessageType mtype = static_cast< MessageType >(atoi(type.c_str()));
 
-void
-SessionManager::setRecipient(char const* recipientJID)
-{
-       if (this->session_data->recipient) {
-               free(const_cast< gchar* >(this->session_data->recipient));
-       }
-
-       if (recipientJID == NULL) {
-               this->session_data->recipient = NULL;
-       } else {
-               this->session_data->recipient = g_strdup(recipientJID);
-       }
-}
+       // Messages that deal with the creation and destruction of sessions should be handled
+       // here in the SessionManager.  
+       //
+       // These events are listed below, along with rationale.
+       //
+       // - CONNECT_REQUEST_USER: when we begin to process this message, we will not have an 
+       //   Inkboard session available to send the message to.  Therefore, this message needs
+       //   to be handled by the SessionManager.
+       // 
+       // - CONNECT_REQUEST_REFUSED_BY_PEER: this message means that the recipient of a 
+       //   private invitation refused the invitation.  In this case, we need to destroy the
+       //   Inkboard desktop, document, and session associated with that invitation.
+       //   Destruction of these components seems to be more naturally done in the SessionManager
+       //   than in the Inkboard document itself (especially since the document may be associated
+       //   with multiple desktops).
+       //
+       // - UNSUPPORTED_PROTOCOL_VERSION: this message means that the recipient of an invitation
+       //   does not support the version of the Inkboard protocol we are using.  In this case,
+       //   we have to destroy the Inkboard desktop, document, and session associated with that
+       //   invitation.  The rationale for doing it in the SessionManager is the same as that
+       //   given above.
+       //
+       // - ALREADY_IN_SESSION: similar rationale to above.
+       //
+       // - DISCONNECTED_FROM_USER_SIGNAL: similar rationale to above.
+       //
+       //
+        // All other events can be handled inside an Inkboard session.
+       
+       // The message we are handling will have come from some Jabber ID.  We need to verify
+       // that the Inkboard session associated with that JID is in the correct state for the
+       // incoming message (or, in some cases, that the session correctly exists / does not
+       // exist).
+       InkboardDocument* doc = getInkboardSession(event.getFrom());
 
-void
-SessionManager::sendChange(Glib::ustring const& msg, MessageType type, std::string const& recipientJID, bool chatroom)
-{
-       if (!this->session_data->status[IN_WHITEBOARD]) {
-               return;
-       }
+//      NOTE: This line refers to a class that hasn't been written yet
+//     MessageValidityTestResult res = MessageVerifier::verifyMessageValidity(event, mtype, doc);
 
-       std::string& recipient = const_cast< std::string& >(recipientJID);
-       if (recipient.empty()) {
-               recipient = this->session_data->recipient;
-       }
-               
+       MessageValidityTestResult res = RESULT_INVALID;
 
-       switch (type) {
-               case DOCUMENT_BEGIN:
-               case DOCUMENT_END:
-               case CHANGE_NOT_REPEATABLE:
-               case CHANGE_REPEATABLE:
-               case CHANGE_COMMIT:
+       switch (res) {
+               case RESULT_VALID:
                {
-                       MessageNode *newNode = new MessageNode(this->session_data->sequence_number++, this->session_data->jid, recipient, msg, type, false, chatroom);
-                       this->session_data->send_queue->insert(newNode);
-                       Inkscape::GC::release(newNode);
+                       switch (mtype) {
+                               case CONNECT_REQUEST_USER:
+                               case CONNECT_REQUEST_REFUSED_BY_PEER:
+                               case UNSUPPORTED_PROTOCOL_VERSION:
+                               case ALREADY_IN_SESSION:
+                                       _handleSessionEvent(mtype, event);
+                                       break;
+                               case DISCONNECTED_FROM_USER_SIGNAL:
+                                       break;
+                               default:
+                                       if (doc != NULL) {
+                                               unsigned int seqnum = atoi(seq.c_str());
+                                               doc->processInkboardEvent(mtype, seqnum, event.getData());
+                                       }
+                                       break;
+                       }
                        break;
                }
+               case RESULT_INVALID:
                default:
-                       g_warning("Cannot insert MessageNode with unknown change type into send queue; discarding message.  This may lead to desynchronization!");
+                       // FIXME: better warning message
+                       g_warning("Received message in invalid context.");
                        break;
        }
 }
 
-
-// FIXME:
-// This method needs a massive, massive, massive overhaul.
-int
-SessionManager::sendMessage(MessageType msgtype, unsigned int sequence, Glib::ustring const& msg, char const* recipientJID, bool chatroom)
+void
+SessionManager::_handleSessionEvent(MessageType mtype, Pedro::XmppEvent const& event)
 {
-       LmMessage* m;
-       GError* error = NULL;
-       char* type, * seq;
-
-       if (recipientJID == NULL || recipientJID == "") {
-               g_warning("Null recipient JID specified; not sending message.");
-               return NO_RECIPIENT_JID;
-       } else {
-       }
-
-       // create message
-       m = lm_message_new(recipientJID, LM_MESSAGE_TYPE_MESSAGE);
-
-       // add sender
-       lm_message_node_set_attribute(m->node, "from", this->session_data->jid.c_str());
-
-       // set message subtype according to whether or not this is
-       // destined for a chatroom
-       if (chatroom) {
-               lm_message_node_set_attribute(m->node, "type", "groupchat");
-       } else {
-               lm_message_node_set_attribute(m->node, "type", "chat");
-       }
-
-       // set protocol version;
-       // we are currently fixed at version 1
-       lm_message_node_add_child(m->node, MESSAGE_PROTOCOL_VER, MESSAGE_PROTOCOL_V1);
-
-       // add message type
-       type = (char *)calloc(TYPE_FIELD_SIZE, sizeof(char));
-       snprintf(type, TYPE_FIELD_SIZE, "%i", msgtype);
-       lm_message_node_add_child(m->node, MESSAGE_TYPE, type);
-       free(type);
-
-       // add message body
-       if (!msg.empty()) {
-               lm_message_node_add_child(m->node, MESSAGE_BODY, msg.c_str());
-       } else {
-       }
-
-       // add sequence number
-       switch(msgtype) {
-               case CHANGE_REPEATABLE:
-               case CHANGE_NOT_REPEATABLE:
-               case DUMMY_CHANGE:
-               case CHANGE_COMMIT:
-               case DOCUMENT_BEGIN:
-               case DOCUMENT_END:
-               case CONNECT_REQUEST_RESPONSE_CHAT:
-               case CONNECT_REQUEST_RESPONSE_USER:
-               case CHATROOM_SYNCHRONIZE_RESPONSE:
-                       seq = (char* )calloc(SEQNUM_FIELD_SIZE, sizeof(char));
-                       sprintf(seq, "%u", sequence);
-                       lm_message_node_add_child(m->node, MESSAGE_SEQNUM, seq);
-                       free(seq);
-                       break;
-
+       switch (mtype) {
                case CONNECT_REQUEST_USER:
-               case CONNECTED_SIGNAL:
-               case DISCONNECTED_FROM_USER_SIGNAL:
+                       _handleIncomingInvitation(event.getFrom());
                        break;
-
-               // Error messages and synchronization requests do not need a sequence number
-               case CHATROOM_SYNCHRONIZE_REQUEST:
                case CONNECT_REQUEST_REFUSED_BY_PEER:
-               case UNSUPPORTED_PROTOCOL_VERSION:
+                       _handleInvitationResponse(event.getFrom(), DECLINE_INVITATION);
+                       break;
                case ALREADY_IN_SESSION:
+                       _handleInvitationResponse(event.getFrom(), PEER_ALREADY_IN_SESSION);
+                       break;
+               case UNSUPPORTED_PROTOCOL_VERSION:
+                       _handleInvitationResponse(event.getFrom(), UNSUPPORTED_PROTOCOL);
                        break;
-
                default:
-                       g_warning("Outgoing message type not recognized; not sending.");
-                       lm_message_unref(m);
-                       return UNKNOWN_OUTGOING_TYPE;
-       }
-
-       // We want to log messages even if they were not successfully sent,
-       // since the user may opt to re-synchronize a session using the session
-       // file record.
-       if (!msg.empty()) {
-               this->_log(msg);
-               this->_commitLog();
-       }
-
-       // send message
-
-       if (!lm_connection_send(this->session_data->connection, m, &error)) {
-               g_warning("Send failed: %s", error->message);
-               lm_message_unref(m);
-               return CONNECTION_ERROR;
-       }
-
-       lm_message_unref(m);
-       return SEND_SUCCESS;
-}
-
-void
-SessionManager::connectionError(Glib::ustring const& errmsg)
-{
-       Gtk::MessageDialog dlg(errmsg, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE);
-       dlg.run();
-//     sp_whiteboard_connect_dialog(const_cast< gchar* >(errmsg));
-}
-
-void
-SessionManager::resendDocument(char const* recipientJID, KeyToNodeMap& newidsbuf, NodeToKeyMap& newnodesbuf)
-{
-       Glib::ustring docbegin = MessageUtilities::makeTagWithContent(MESSAGE_DOCBEGIN, "");
-       this->sendChange(docbegin, DOCUMENT_BEGIN, recipientJID, false);
-
-       Inkscape::XML::Node* root = sp_document_repr_root(this->_myDoc);
-
-       if(root == NULL) {
-               return;
-    }
-
-       NewChildObjectMessageList newchildren;
-       MessageAggregator& agg = MessageAggregator::instance();
-       Glib::ustring buf;
-
-    for ( Inkscape::XML::Node *child = root->firstChild() ; child != NULL ; child = child->next() ) {
-               // TODO: replace with Serializer methods
-               MessageUtilities::newObjectMessage(&buf, newidsbuf, newnodesbuf, newchildren, this->_myTracker, child);
-
-               NewChildObjectMessageList::iterator j = newchildren.begin();
-               Glib::ustring aggbuf;
-
-               for(; j != newchildren.end(); j++) {
-                       if (!agg.addOne(*j, aggbuf)) {
-                               this->sendChange(aggbuf, CHANGE_REPEATABLE, recipientJID, false);
-                               aggbuf.clear();
-                               agg.addOne(*j, aggbuf);
-                       }
-               }
-
-               // send remaining changes
-               if (!aggbuf.empty()) {
-                       this->sendChange(aggbuf, CHANGE_REPEATABLE, recipientJID, false);
-                       aggbuf.clear();
-               }
-
-               newchildren.clear();
-               buf.clear();
-    }
-
-       Glib::ustring commit = MessageUtilities::makeTagWithContent(MESSAGE_COMMIT, "");
-       this->sendChange(commit, CHANGE_COMMIT, recipientJID, false);
-       Glib::ustring docend = MessageUtilities::makeTagWithContent(MESSAGE_DOCEND, "");
-       this->sendChange(docend, DOCUMENT_END, recipientJID, false);
-}
-
-void
-SessionManager::receiveChange(Glib::ustring const& changemsg)
-{
-
-       struct Node part;
-
-       Glib::ustring msgcopy = changemsg.c_str();
-
-
-       while(MessageUtilities::getFirstMessageTag(part, msgcopy) != false) {
-               // TODO:
-               // Yikes.  This is ugly.
-               if (part.tag == MESSAGE_CHANGE) {
-                       this->_myDeserializer->deserializeEventChgAttr(part.data);
-                       msgcopy.erase(0, part.next_pos);
-
-               } else if (part.tag == MESSAGE_NEWOBJ) {
-                       this->_myDeserializer->deserializeEventAdd(part.data);
-                       msgcopy.erase(0, part.next_pos);
-
-               } else if (part.tag == MESSAGE_DELETE) {
-                       this->_myDeserializer->deserializeEventDel(part.data);
-                       msgcopy.erase(0, part.next_pos);
-
-               } else if (part.tag == MESSAGE_DOCUMENT) {
-                       // no special handler, just keep going with the rest of the message
-                       msgcopy.erase(0, part.next_pos);
-
-               } else if (part.tag == MESSAGE_NODECONTENT) {
-                       this->_myDeserializer->deserializeEventChgContent(part.data);
-                       msgcopy.erase(0, part.next_pos);
-
-               } else if (part.tag == MESSAGE_ORDERCHANGE) {
-                       this->_myDeserializer->deserializeEventChgOrder(part.data);
-                       msgcopy.erase(0, part.next_pos);
-
-               } else if (part.tag == MESSAGE_COMMIT) {
-                       // Retrieve the deserialized event log, node actions, and nodes with updated attributes
-                       XML::Event* log = this->_myDeserializer->getEventLog();
-                       KeyToNodeActionList& node_changes = this->_myDeserializer->getNodeTrackerActions();
-                       AttributesUpdatedSet& updated = this->_myDeserializer->getUpdatedAttributeNodeSet();
-
-                       // Make document insensitive to undo
-                       gboolean saved = sp_document_get_undo_sensitive(this->_myDoc);
-                       sp_document_set_undo_sensitive(this->_myDoc, FALSE);
-
-                       // Replay the log and push it onto the undo stack
-                       sp_repr_replay_log(log);
-
-                       // Call updateRepr on changed nodes
-                       // This is required for some tools to function properly, i.e. text tool
-                       // (TODO: we don't need to update _all_ changed nodes, just their parents)
-                       AttributesUpdatedSet::iterator i = updated.begin();
-                       for(; i != updated.end(); i++) {
-                               SPObject* updated = this->_myDoc->getObjectByRepr(*i);
-                               if (updated) {
-                                       updated->updateRepr();
-                               }
-                       }
-
-                       // merge the events generated by updateRepr
-                       sp_repr_coalesce_log(this->_myDoc->priv->partial, log);
-                       this->_myDoc->priv->partial = NULL;
-
-                       this->_myDoc->priv->undo = g_slist_prepend(this->_myDoc->priv->undo, log);
-
-                       // Restore undo sensitivity
-                       sp_document_set_undo_sensitive(this->_myDoc, saved);
-
-                       // Add or delete nodes to/from the tracker
-                       this->_myTracker->process(node_changes);
-
-                       // Reset deserializer state
-                       this->_myDeserializer->reset();
                        break;
-
-               } else if (part.tag == MESSAGE_UNDO) {
-                       this->_myUndoObserver->lockObserverFromSending(UndoStackObserver::UNDO_EVENT);
-                       sp_document_undo(this->_myDoc);
-                       this->_myUndoObserver->unlockObserverFromSending(UndoStackObserver::UNDO_EVENT);
-                       msgcopy.erase(0, part.next_pos);
-
-               } else if (part.tag == MESSAGE_REDO) {
-                       this->_myUndoObserver->lockObserverFromSending(UndoStackObserver::REDO_EVENT);
-                       sp_document_redo(this->_myDoc);
-                       this->_myUndoObserver->unlockObserverFromSending(UndoStackObserver::REDO_EVENT);
-                       msgcopy.erase(0, part.next_pos);
-
-               } else if (part.tag == MESSAGE_DOCBEGIN) {
-                       msgcopy.erase(0, part.next_pos);
-
-               } else if (part.tag == MESSAGE_DOCEND) {
-                       // Set this to be the new original state of the document
-                       sp_document_done(this->document());
-                       sp_document_clear_redo(this->document());
-                       sp_document_clear_undo(this->document());
-                       this->setupCommitListener();
-                       msgcopy.erase(0, part.next_pos);
-
-               } else {
-                       msgcopy.erase(0, part.next_pos);
-
-               }
-       }
-
-       this->_log(changemsg);
-
-       this->_commitLog();
-}
-
-bool
-SessionManager::isPlayingSessionFile()
-{
-       return this->session_data->status[PLAYING_SESSION_FILE];
-}
-
-void
-SessionManager::loadSessionFile(Glib::ustring filename)
-{
-       if (!this->session_data || !this->session_data->status[IN_WHITEBOARD]) {
-               try {
-                       if (this->_mySessionFile) {
-                               delete this->_mySessionFile;
-                       }
-                       this->_mySessionFile = new SessionFile(filename, true, false);
-
-                       // Initialize objects needed for session playback
-                       if (this->_mySessionPlayer == NULL) {
-                               this->_mySessionPlayer = new SessionFilePlayer(16, this);
-                       } else {
-                               this->_mySessionPlayer->load(this->_mySessionFile);
-                       }
-
-                       if (this->_myTracker == NULL) {
-                               this->_myTracker = new XMLNodeTracker(this);
-                       } else {
-                               this->_myTracker->reset();
-                       }
-
-                       if (!this->session_data) {
-                               this->session_data = new SessionData(this);
-                       }
-
-                       if (!this->_myDeserializer) {
-                               this->_myDeserializer = new Deserializer(this->node_tracker());
-                       }
-
-                       if (!this->_myUndoObserver) {
-                               this->setupCommitListener();
-                       }
-
-                       this->session_data->status.set(PLAYING_SESSION_FILE, 1);
-
-
-               } catch (Glib::FileError e) {
-                       g_warning("Could not load session file: %s", e.what().data());
-               }
-       }
-}
-
-void
-SessionManager::userConnectedToWhiteboard(gchar const* JID)
-{
-       sp_desktop_message_stack(this->_myDesktop)->flashF(Inkscape::INFORMATION_MESSAGE, _("Established whiteboard session with <b>%s</b>."), JID);
-}
-
-
-void
-SessionManager::userDisconnectedFromWhiteboard(std::string const& JID)
-{
-
-       sp_desktop_message_stack(this->_myDesktop)->flashF(Inkscape::INFORMATION_MESSAGE, _("<b>%s</b> has <b>left</b> the whiteboard session."), JID.c_str());
-
-       // Inform the user
-       // TRANSLATORS: %1 is the name of the user that disconnected, %2 is the name of the user whom the disconnected user disconnected from.
-       // This message is not used in a chatroom context.
-       Glib::ustring primary = String::ucompose(_("<span weight=\"bold\" size=\"larger\">The user <b>%1</b> has left the whiteboard session.</span>\n\n"), JID);
-       // TRANSLATORS: %1 and %2 are userids
-       Glib::ustring secondary = String::ucompose(_("You are still connected to a Jabber server as <b>%2</b>, and may establish a new session to <b>%1</b> or a different user."), JID, this->session_data->jid);
-
-       // TODO: parent this dialog to the active desktop
-       Gtk::MessageDialog dialog(primary + secondary, true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, false);
-       /*
-       dialog.set_message(primary, true);
-       dialog.set_secondary_text(secondary, true);
-       */
-       dialog.run();
-}
-
-void
-SessionManager::startSendQueueDispatch()
-{
-       this->_send_queue_dispatcher = Glib::signal_timeout().connect(sigc::mem_fun(*(this->_myCallbacks), &Callbacks::dispatchSendQueue), SEND_TIMEOUT);
-}
-
-void
-SessionManager::stopSendQueueDispatch()
-{
-       if (this->_send_queue_dispatcher) {
-               this->_send_queue_dispatcher.disconnect();
-       }
-}
-
-void
-SessionManager::startReceiveQueueDispatch()
-{
-       this->_receive_queue_dispatcher = Glib::signal_timeout().connect(sigc::mem_fun(*(this->_myCallbacks), &Callbacks::dispatchReceiveQueue), SEND_TIMEOUT);
-}
-
-void
-SessionManager::stopReceiveQueueDispatch()
-{
-       if (this->_receive_queue_dispatcher) {
-               this->_receive_queue_dispatcher.disconnect();
-       }
-}
-
-void
-SessionManager::clearDocument()
-{
-       // clear all layers, definitions, and metadata
-       XML::Node* rroot = this->_myDoc->rroot;
-
-       // clear definitions
-       XML::Node* defs = SP_OBJECT_REPR((SPDefs*)SP_DOCUMENT_DEFS(this->_myDoc));
-       g_assert(SP_ROOT(this->_myDoc->root)->defs);
-
-       for(XML::Node* child = defs->firstChild(); child; child = child->next()) {
-               defs->removeChild(child);
-       }
-
-       // clear layers
-       for(XML::Node* child = rroot->firstChild(); child; child = child->next()) {
-               if (strcmp(child->name(), "svg:g") == 0) {
-                       rroot->removeChild(child);
-               }
        }
-
-       // clear metadata
-       for(XML::Node* child = rroot->firstChild(); child; child = child->next()) {
-               if (strcmp(child->name(), "svg:metadata") == 0) {
-                       rroot->removeChild(child);
-               }
-       }
-
-//     sp_document_done(this->_myDoc);
 }
 
 void
-SessionManager::setupInkscapeInterface()
+SessionManager::_handleIncomingInvitation(Glib::ustring const& from)
 {
-       this->session_data->status.set(IN_WHITEBOARD, 1);
-       this->startSendQueueDispatch();
-       this->startReceiveQueueDispatch();
-       if (!this->_myTracker) {
-               this->_myTracker = new XMLNodeTracker(this);
-       }
-
-       this->_mySerializer = new Serializer(this->node_tracker());
-       this->_myDeserializer = new Deserializer(this->node_tracker());
-
-       // We're in a whiteboard session now, so set verb sensitivity accordingly
-       this->_setVerbSensitivity(ESTABLISHED_SESSION);
-}
-
-void
-SessionManager::setupCommitListener()
-{
-       this->_myUndoObserver = new Whiteboard::UndoStackObserver(this);
-       this->_myDoc->addUndoObserver(*this->_myUndoObserver);
-}
-
-::SPDesktop*
-SessionManager::desktop()
-{
-       return this->_myDesktop;
-}
-
-::SPDocument*
-SessionManager::document()
-{
-       return this->_myDoc;
-}
-
-Callbacks*
-SessionManager::callbacks()
-{
-       return this->_myCallbacks;
-}
-
-Whiteboard::UndoStackObserver*
-SessionManager::undo_stack_observer()
-{
-       return this->_myUndoObserver;
-}
-
-Serializer*
-SessionManager::serializer()
-{
-       return this->_mySerializer;
-}
-
-XMLNodeTracker*
-SessionManager::node_tracker()
-{
-       return this->_myTracker;
-}
-
-
-ChatMessageHandler*
-SessionManager::chat_handler()
-{
-       return this->_myChatHandler;
-}
-
-SessionFilePlayer*
-SessionManager::session_player()
-{
-       return this->_mySessionPlayer;
-}
-
-SessionFile*
-SessionManager::session_file()
-{
-       return this->_mySessionFile;
-}
-
-void
-SessionManager::_log(Glib::ustring const& message)
-{
-       if (this->_mySessionFile && !this->_mySessionFile->isReadOnly()) {
-               this->_mySessionFile->addMessage(message);
-       }
-}
-
-void
-SessionManager::_commitLog()
-{
-       if (this->_mySessionFile && !this->_mySessionFile->isReadOnly()) {
-               this->_mySessionFile->commit();
+       // don't insert duplicate invitations
+       if (std::find(_pending_invitations.begin(), _pending_invitations.end(), from) != _pending_invitations.end()) {
+               return;
        }
-}
 
-void
-SessionManager::_closeLog()
-{
-       if (this->_mySessionFile) {
-               this->_mySessionFile->close();
-       }
-}
+       // We need to do the invitation confirm/deny dialog elsewhere --
+       // when this method is called, we're still executing in Pedro's context,
+       // which causes issues when we run a dialog main loop.
+       //
+       // The invitation handling is done in a poller timeout that executes approximately
+       // every 50ms.  It calls _checkInvitationQueue.
+       _pending_invitations.push_back(from);
 
-void
-SessionManager::startLog(Glib::ustring filename)
-{
-       try {
-               this->_mySessionFile = new SessionFile(filename, false, false);
-       } catch (Glib::FileError e) {
-               g_warning("Caught I/O error %s while attemping to open file %s for session recording.", e.what().c_str(), filename.c_str());
-               throw;
-       }
 }
 
 void
-SessionManager::_tryToStartLog()
+SessionManager::_handleInvitationResponse(Glib::ustring const& from, InvitationResponses resp)
 {
-       if (this->session_data) {
-               if (!this->session_data->sessionFile.empty()) {
-                       bool undecided = true;
-                       while(undecided) {
-                               try {
-                                       this->startLog(this->session_data->sessionFile);
-                                       undecided = false;
-                               } catch (Glib::FileError e) {
-                                       undecided = true;
-                                       Glib::ustring msg = String::ucompose(_("Could not open file %1 for session recording.\nThe error encountered was: %2.\n\nYou may select a different location to record the session, or you may opt to not record this session."), this->session_data->sessionFile, e.what());
-                                       Gtk::MessageDialog dlg(msg, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_NONE, false);
-                                       dlg.add_button(_("Choose a different location"), 0);
-                                       dlg.add_button(_("Skip session recording"), 1);
-                                       switch (dlg.run()) {
-                                               case 0:
-                                               {
-                                                       Gtk::FileChooserDialog sessionfiledlg(_("Select a location and filename"), Gtk::FILE_CHOOSER_ACTION_SAVE);
-                                                       sessionfiledlg.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
-                                                       sessionfiledlg.add_button(_("Set filename"), Gtk::RESPONSE_OK);
-                                                       int result = sessionfiledlg.run();
-                                                       switch (result) {
-                                                               case Gtk::RESPONSE_OK:
-                                                               {
-                                                                       this->session_data->sessionFile = sessionfiledlg.get_filename();
-                                                                       break;
-                                                               }
-                                                               case Gtk::RESPONSE_CANCEL:
-                                                               default:
-                                                                       undecided = false;
-                                                                       break;
-                                                       }
-                                                       break;
-                                               }
-                                               case 1:
-                                               default:
-                                                       undecided = false;
-                                                       break;
-                                       }
-                               }
-                       }
-               }
+       // only handle one response per invitation sender
+       //
+       // TODO: this could have one huge bug: say that Alice sends an invite to Bob, but
+       // Bob is doing something else at the moment and doesn't want to get in an Inkboard
+       // session.  Eve intercepts Bob's "reject invitation" message and passes a
+       // "accept invitation" message to Alice that comes before Bob's "reject invitation"
+       // message. 
+       //
+       // Does XMPP prevent this sort of attack?  Need to investigate that.
+       if (std::find_if(_invitation_responses.begin(), _invitation_responses.end(), CheckInvitationSender(from)) != _invitation_responses.end()) {
+               return;
        }
-}
-
-void
-SessionManager::_setVerbSensitivity(SensitivityMode mode)
-{
-       return;
-
-       switch (mode) {
-               case ESTABLISHED_CONNECTION:
-                       // Upon successful connection, we can disconnect from the server.
-                       // We can also start sharing a document with a user or chatroom.
-                       // We cannot, however, connect to a new server without first disconnecting.
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_CONNECT)->sensitive(this->_myDoc, false);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SERVER)->sensitive(this->_myDoc, true);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_SHAREWITHUSER)->sensitive(this->_myDoc, true);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_SHAREWITHCHAT)->sensitive(this->_myDoc, true);
-                       break;
 
-               case ESTABLISHED_SESSION:
-                       // When we have established a session, we should not permit the user to go and
-                       // establish another session from the same document without first disconnecting.
-                       //
-                       // TODO: Well, actually, we probably _should_, but there's no real reconnection logic just yet.
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_SHAREWITHUSER)->sensitive(this->_myDoc, false);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_SHAREWITHCHAT)->sensitive(this->_myDoc, false);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SESSION)->sensitive(this->_myDoc, true);
-                       break;
-               case DISCONNECTED_FROM_SESSION:
-                       // Upon disconnecting from a session, we can establish a new session and disconnect
-                       // from the server, but we cannot disconnect from a session (since we just left it.)
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SESSION)->sensitive(this->_myDoc, false);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_SHAREWITHUSER)->sensitive(this->_myDoc, true);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_SHAREWITHCHAT)->sensitive(this->_myDoc, true);
-
-               case INITIAL:
-               default:
-                       // Upon construction, there is no active connection, so we cannot do the following:
-                       // (1) disconnect from a session
-                       // (2) disconnect from a server
-                       // (3) share with a user 
-                       // (4) share with a chatroom
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_CONNECT)->sensitive(this->_myDoc, true);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_SHAREWITHUSER)->sensitive(this->_myDoc, false);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_SHAREWITHCHAT)->sensitive(this->_myDoc, false);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SESSION)->sensitive(this->_myDoc, false);
-                       Inkscape::Verb::get(SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SERVER)->sensitive(this->_myDoc, false);
-                       break;
-       };
-}
-
-/*
-void
-SessionManager::Listener::processXmppEvent(Pedro::XmppEvent const& event)
-{
-       int type = event.getType();
-
-       switch (type) {
-               case Pedro::XmppEvent::EVENT_STATUS:
-                       break;
-               case Pedro::XmppEvent::EVENT_ERROR:
-                       break;
-               case Pedro::XmppEvent::EVENT_CONNECTED:
-                       break;
-               case Pedro::XmppEvent::EVENT_DISCONNECTED:
-                       break;
-               case Pedro::XmppEvent::EVENT_MESSAGE:
-                       break;
-               case Pedro::XmppEvent::EVENT_PRESENCE:
-                       break;
-               case Pedro::XmppEvent::EVENT_MUC_MESSAGE:
-                       break;
-               case Pedro::XmppEvent::EVENT_MUC_JOIN:
-                       break;
-               case Pedro::XmppEvent::EVENT_MUC_LEAVE:
-                       break;
-               case Pedro::XmppEvent::EVENT_MUC_PRESENCE:
-                       break;
-       }
-}
-*/
+       // We need to do the invitation confirm/deny dialog elsewhere --
+       // when this method is called, we're still executing in Pedro's context,
+       // which causes issues when we run a dialog main loop.
+       //
+       // The invitation handling is done in a poller timeout that executes approximately
+       // every 50ms.  It calls _checkInvitationResponseQueue.
+       _invitation_responses.push_back(Invitation_response_type(from, resp));
 
 }
 
-}
+}  // namespace Whiteboard
+}  // namespace Inkscape
 
 
 /*
index a273fef4dedf9c3d6b76856e54b4e5cc72dd6db0..75fd84a44cfce45f1a3065cc2e4e4a2b2b48c944 100644 (file)
  *
  * Authors: 
  * David Yip <yipdw@rose-hulman.edu>
+ * Bob Jamison (Pedro port)
  *
  * Copyright (c) 2005 Authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
-#ifndef __SESSION_MANAGER_H__
-#define __SESSION_MANAGER_H__
+#ifndef __INKSCAPE_WHITEBOARD_SESSION_MANAGER_H__
+#define __INKSCAPE_WHITEBOARD_SESSION_MANAGER_H__
 
-#include <glibmm.h>
-#include <set>
-#include <bitset>
-
-#include <libxml/parser.h>
-#include <libxml/tree.h>
+#include "pedro/pedrogui.h"
 
-#include <vector>
+#include <glibmm.h>
 
-extern "C" {
-#include <loudmouth/loudmouth.h>
-}
+#include <list>
+#include <bitset>
 
-#include "jabber_whiteboard/typedefs.h"
+#include "jabber_whiteboard/message-queue.h"
 #include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/buddy-list-manager.h"
+#include "jabber_whiteboard/internal-constants.h"
+#include "jabber_whiteboard/inkboard-session.h"
 
 #include "gc-alloc.h"
 
-struct SPDesktop;
-struct SPDocument;
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
+class SPDesktop;
 
 namespace Inkscape {
 
 namespace Whiteboard {
 
-class ReceiveMessageQueue;
-class SendMessageQueue;
-class XMLNodeTracker;
-class SessionManager;
-class MessageHandler;
-class ChatMessageHandler;
-class Callbacks;
-class SessionFile;
-class SessionFilePlayer;
-class UndoStackObserver;
-class Serializer;
-class Deserializer;
-
-/// Jabber resource name
-#define RESOURCE_NAME  "Inkboard"
-
-/// connectToServer return values
-#define CONNECT_SUCCESS                0
-#define FAILED_TO_CONNECT      1
-#define INVALID_AUTH           2
-#define SSL_INITIALIZATION_ERROR       3
-
-/// sendMessage return values
-#define SEND_SUCCESS                   0
-#define CONNECTION_ERROR               1
-#define UNKNOWN_OUTGOING_TYPE  2
-#define NO_RECIPIENT_JID               3
-
-/**
- * Structure grouping data items pertinent to a whiteboard session.
- *
- * SessionData holds all session data for both 1:1 and chatroom conferences.
- * Access to members should be controlled by first querying the status bitset
- * to see if useful data will actually exist in that member -- i.e. checking
- * status[IN_CHATROOM] to see if the chatters set will contain anything.
- * It usually won't hurt to do a straight query -- there are very few members
- * that remain uninitialized for very long -- but it's a good idea to check.
- */
-struct SessionData {
-public:
-       /**
-        * Constructor.
-        *
-        * \param sm The SessionManager with which a SessionData instance should be
-        * associated with.
-        */
-       SessionData(SessionManager *sm);
-
-       ~SessionData();
-
-       /**
-        * The JID of the recipient: either another user JID or the JID of a chatroom.
-        */
-       gchar const* recipient;
-
-       /**
-        * Pointer to Loudmouth connection structure.
-        * Used for Loudmouth calls that require it.
-        */
-       LmConnection* connection;
-
-       /**
-        * SSL information structure for SSL connections.
-        */
-       LmSSL* ssl;
-
-       /**
-        * Flag indicating whether or not we should ignore further SSL errors for a given session.
-        */
-       bool ignoreFurtherSSLErrors;
-
-
-       /**
-        * A user's handle in a Jabber chatroom.
-        */
-       Glib::ustring chat_handle;
-
-       /**
-        * The Users Jid.
-        */
-       Glib::ustring jid;
-
-       /**
-        * Name of the chatroom that a user in a chatroom is connected to.
-        */
-       Glib::ustring chat_name;
-
-       /**
-        * Name of the conference server.
-        */
-       Glib::ustring chat_server;
-
-       // Message queues
-       
-       /**
-        * Map associating senders to receive queues.
-        */
-       RecipientToReceiveQueueMap receive_queues;
-
-       /**
-        * Map associating senders to commit events sent by those committers.
-        */
-       CommitsQueue recipients_committed_queue;
-
-       /**
-        * Pointer to queue for messages to be sent.
-        */
-       SendMessageQueue* send_queue;
-
-       // Message sequence numbers
-       
-       /**
-        * The sequence number of the latest message sent by this client in a given session.
-        * Used for determining the sequence number of the next message.
-        */
-       unsigned int sequence_number;
-
-       //unsigned int latest_sent_transaction;
-       //RecipientToLatestTransactionMap latest_processed_transactions;
-
-
-       // Status tracking
-       /**
-        * Session state and status flags.
-        */
-       std::bitset< NUM_FLAGS > status;
-       
-       /**
-        * Jabber buddy list data.
-        */
-       BuddyListManager buddyList;
-
-       /**
-        * List of participants in a Jabber chatroom.
-        */
-       ChatterList chatters;
-
-       /**
-        * Session file filename; blank if no session file is to be
-        * recorded.
-        */
-       Glib::ustring sessionFile;
-
-private:
-       // access to containing class
-       SessionManager *_sm;
-
-       // noncopyable, nonassignable
-       SessionData(SessionData const&);
-       SessionData& operator=(SessionData const&);
+enum SessionType {
+    INKBOARD_PRIVATE,
+    INKBOARD_MUC
 };
 
+class SessionManager;
+class InkboardDocument;
 
-// TODO: This class is huge.  It might be best to refactor it into smaller,
-// more coherent chunks.
-//
-// TODO: convert to pass-by-reference where appropriate.  In particular, a lot of the
-// string buffers passed to methods in the argument list can be made into references
-// appropriately and easily.
-
-/**
- * Session management class for Inkboard.
- *
- * By "session management", we refer to the management of all events that an Inkboard
- * session may need to handle: negotiating a connection to a Jabber server, negotiating
- * sessions with users and chatrooms, sending, receiving, and parsing messages, and so
- * forth.
- *
- * SessionManager instances are associated with Inkscape desktop objects on a 1:1 basis.
- */
-class SessionManager {
+class SessionManager : public Pedro::XmppEventListener {
 public:
-       /**
-        * Constructor.
-        *
-        * \param desktop The desktop with which this SessionManager is associated.  */
-       SessionManager(::SPDesktop *desktop);
-       ~SessionManager();
-
-       // Session tracking data
-       
-       /** 
-        * Pointer to SessionData structure.
-        */
-       struct SessionData *session_data;
-
-       // Inkscape interface
-       
-       /**
-        * Set the desktop with which this SessionManager is associated.
-        *
-        * @param desktop the desktop with which this SessionManager should be associated
-        */
-       void setDesktop(::SPDesktop* desktop);
-       
-       // Session management
-       
-       /**
-        * Connect to a Jabber server.
-        *
-        * @param server Jabber server URL
-        * @param entered_username Jabber username provided by user (may also be full JID)
-        * @param pw password for Jabber account
-        * @param usessl use SSL for connection
-        *
-        * @return CONNECT_SUCCESS if connection successful; FAILED_TO_CONNECT if connection failed or INVALID_AUTH
-        * if authentication invalid
-        */
-       int connectToServer(Glib::ustring const& server, Glib::ustring const& port, Glib::ustring const& entered_username, Glib::ustring const& pw, bool usessl);
-       
-       /**
-        * Register with a Jabber server.
-        *
-        * @param username Jabber username
-        * @param pw password for Jabber account
-        * @param key A list of string elements required for registration
-        * @param val The respective list of value of elements required for registration
-        * @param usessl use SSL for connection
-        *
-        * @return CONNECT_SUCCESS if connection successful; FAILED_TO_CONNECT if connection failed or INVALID_AUTH
-        * if authentication invalid
-        */
-       int registerWithServer(Glib::ustring const& username,Glib::ustring const& pw, std::vector<Glib::ustring> key, std::vector<Glib::ustring> val);
 
-       /**
-        * Query the Registration information required for a jabber server
-        *
-        * @param server Jabber server URL
-        * @param username Jabber username
-        * @param pw password for Jabber account
-        * @param key A list of string elements required for registration
-        * @param val The respective list of value of elements required for registration
-        * @param usessl use SSL for connection
-        *
-        * @return CONNECT_SUCCESS if connection successful; FAILED_TO_CONNECT if connection failed or INVALID_AUTH
-        * if authentication invalid
-        */
-       std::vector<Glib::ustring> getRegistrationInfo();
-       
-       int finaliseConnection();
-       int initializeConnection(Glib::ustring const& server, Glib::ustring const& port, bool usessl);
-       /**
-        * Handle an SSL error by prompting the user for feedback, and continuing or aborting the connection
-        * process based on that feedback.
-        *
-        * @param ssl pointer to LmSSL structure
-        * @param status The error message
-        *
-        * @return LM_SSL_RESPONSE_CONTINUE if user wishes to continue establishing the connection or LM_SSL_RESPONSE_STOP if user wishes to abort connection
-        */
-       LmSSLResponse handleSSLError(LmSSL* ssl, LmSSLStatus status);
+    /**
+     *
+     */
+    SessionManager();
+    
+    /**
+     *
+     */
+    virtual ~SessionManager();
+        
+        
+    static void showClient();
+    static SessionManager& instance();
+    
+    /**
+     *
+     */
+    unsigned long getSequenceNumber();
+
+    /**
+     *
+     */
+    virtual Pedro::XmppClient &getClient()
+        { return gui.client; }
+
+    /**
+     *
+     */
+    virtual bool send(const Glib::ustring &destJid, 
+                      const MessageType type,
+                      const Glib::ustring &data);
+
+    /**
+     *
+     */
+    virtual bool sendGroup(const Glib::ustring &destJid,
+                          const MessageType type,
+                           const Glib::ustring &data);
+    /**
+     *
+     */
+    virtual void processXmppEvent(const Pedro::XmppEvent &event);
+
+    /**
+     * The session handling has been broken out into a subclass of XML::Session.  See
+     * Whiteboard::InkboardSession and Whiteboard::InkboardDocument, both of which
+     * are still under heavy construction.  Don't expect them to work just yet.
+     *
+     * This (should) allow us to substitute an InkboardDocument for an
+     * XML::SimpleDocument (InkboardDocument uses InkboardSession), which, I think, should 
+     * lead to a very clean way of integrating Inkboard.  It should also
+     * give us a cleaner way of handling node tracking.  Finally,
+     * it'll let us experiment with data models that may be more appropriate for Inkboard.
+     *
+     * SessionManager still manages sessions insofar as it receives XMPP data from Pedro and
+     * sends it off to the correct InkboardSession.  I'd like to have it still manage
+     * user sessions, which is what the user sees; however, that can be confusing from
+     * a programmer's standpoint.  This class might therefore need to be renamed 
+     * or something.
+     *
+     * Creation of an Inkboard session should be handled in some fashion similar
+     * to this:
+     *
+     * (1) The user chooses a chat room or user with which she wants to share a whiteboard.
+     *
+     * (2) This invokes the appropriate doShare() method in Pedro's GUI.
+     *
+     * (3) doShare() invokes code to create a new Inkscape desktop with a blank document.
+     * This desktop will use InkboardDocument (and hence InkboardSession) for transaction
+     * management.
+        *
+     * (4) Inkboard setup and operation proceeds as it did in the Loudmouth-based code.
+     *
+     * (3) and (4) will probably need tweaking (for example, it's probably a bad idea to
+     * open up a new desktop if an invitation is refused).   Actually, really, nothing
+     * here is set in stone.  Feel free to modify.             -- dwyip 2005-11-21
+     * 
+     */
+
+    /**
+     * Initiates a shared session with a user or conference room.
+     * 
+     * \param to The recipient to which this desktop will be linked, specified as a JID.
+     * \param type Type of the session; i.e. private message or group chat.
+     */
+    virtual void doShare(Glib::ustring const& to, SessionType type);
+
+    /**
+     * Creates a new desktop with an InkboardDocument.
+     *
+     * An InkboardDocument (and hence desktop)
+     * is identified by the recipient of the document, be it a 
+     * conference room or another user.  If an existing document is found, it will be
+     * returned.
+     *
+     * \param to The recipient to which this desktop will be linked, specified as a JID.
+     * \param type Type of the session; i.e. private message or group chat.
+     * \return A pointer to the created SPDesktop.
+     */
+    virtual SPDesktop* createInkboardDesktop(Glib::ustring const& to, SessionType type);
+
+    /**
+     * Terminates an Inkboard session to a given recipient.  If the session to be
+     * terminated does not exist, does nothing.
+     *
+     * \param to The recipient JID identifying the session to be terminated.
+     */
+    virtual void terminateInkboardSession(Glib::ustring const& to);
+
+    /**
+     * Locates an Inkboard session by recipient JID.  
+     *
+     * \param to The recipient JID identifying the session to be located.
+     * \return A pointer to the InkboardDocument associated with the Inkboard session,
+     * or NULL if no such session exists.
+     */
+    InkboardDocument* getInkboardSession(Glib::ustring const& to);
+
+       void operator=(XmppEventListener const& other) {
 
-       /**
-        * Disconnect from a Jabber server.  
-        *
-        * This invokes disconnectFromDocument().
-        *
-        * \see Inkscape::Whiteboard::SessionManager::disconnectFromDocument
-        */
-       void disconnectFromServer();
-
-       /**
-        * Disconnect from a document session.  The connection to the Jabber server is not 
-        * broken, and may be reused to connect to a new document session.
-        *
-        */
-       void disconnectFromDocument();
-
-       /**
-        * Perform session teardown.  This method by itself does not disconnect from a document or 
-        * a Jabber server.
-        *
-        */
-       void closeSession();
-
-       /**
-        * Set the recipient for Inkboard messages.
-        *
-        * @param recipientJID the recipient's JID
-        */
-       void setRecipient(char const* recipientJID);
-
-       // Message sending utilities
-       
-       /**
-        * Put an Inkboard message into the send queue.
-        * This method does not actually send anything to an Inkboard client.
-        *
-        * \see Inkscape::Whiteboard::SessionManager::sendMessage
-        *
-        *
-        * @param msg the message to send
-        * @param type the type of message (only CHANGE_* types permitted)
-        * @param chatroom whether or not this message is destined for a chatroom
-        */
-       void sendChange(Glib::ustring const& msg, MessageType type, std::string const& recipientJID, bool chatroom);
-
-       /**
-        * Send a message to an Inkboard client.
-        *
-        *
-        * @param msgtype the type of message to send
-        * @param sequence message sequence number
-        * @param msg the message to send
-        * @param recipientJID the JID of the recipient
-        * @param chatroom whether or not this message is destined for a chatroom
-        *
-        * @return SEND_SUCCESS if successful; otherwise: UNKNOWN_OUTGOING_TYPE if msgtype is not recognized, NO_RECIPIENT_JID if recipientJID is NULL or blank, CONNECTION_ERROR if Jabber connection error occurred
-        */
-       int sendMessage(MessageType msgtype, unsigned int sequence, Glib::ustring const& msg, char const* recipientJID, bool chatroom);
-
-       /**
-        * Inform the user of a connection error via a Gtk::MessageDialog.
-        *
-        * @param errmsg message to display
-        */
-       void connectionError(Glib::ustring const& errmsg);
-
-       /**
-        * Stream the contents of the document with which this SessionManager is associated with to the given recipient.
-        * 
-        * @param recipientJID the JID of the recipient
-        * @param newidsbuf buffer to store IDs of new nodes 
-        * @param newnodesbuf buffer to store address of new nodes 
-        */
-       void resendDocument(char const* recipientJID, KeyToNodeMap& newidsbuf, NodeToKeyMap& newnodesbuf);
-       
-       
-       /**
-        * Send a connection request to another Inkboard client.
-        *
-        *
-        * @param recipientJID the JID to connect to
-        * @param document document message to send
-        */
-       void sendRequestToUser(std::string const& recipientJID);
-
-       /**
-        * Send a connection request to chatroom.
-        * 
-        * @param server server to connect to
-        * @param chatroom name of chatroom
-        * @param handle chatroom handle to use
-        * @param password chatroom password; leave NULL if no password
-        */
-       void sendRequestToChatroom(Glib::ustring const& server, Glib::ustring const& chatroom, Glib::ustring const& handle, Glib::ustring const& password);
-
-       /**
-        * Send a connection request response to a user who requested to connect to us.
-        *
-        * @param requesterJID the JID of the user whom sent us the request
-        * @param accepted_request whether or not we accepted the request
-        */
-       void sendConnectRequestResponse(char const* requesterJID, gboolean accepted_request); 
-
-       /**
-        * Method called when a connection request is received.  This method produces a dialog
-        * that asks the user whether or not s/he would like to accept the request.
-        *
-        *
-        * @param requesterJID the JID of the user whom sent us the request
-        * @param msg the message associated with this request
-        */
-       void receiveConnectRequest(gchar const* requesterJID);
-
-       /**
-        * Method called when a response to a connection request is received.
-        * This method performs any necessary session setup/teardown and user notification
-        * depending on the response received.
-        *
-        *
-        * @param msg the message associated with this request
-        * @param response the response code
-        * @param sender the JID of the user whom responded to our request
-        */
-       void receiveConnectRequestResponse(InvitationResponses response, std::string& sender);
-
-       /**
-        * Method called when a document synchronization request is received from a new conference
-        * member in a chatroom.
-        *
-        * \param recipient the recipient JID
-        */
-       void receiveConnectRequestResponseChat(gchar const* recipient);
-
-       // Message parsing and passing
-       
-       /**
-        * Processes a group of document change messages.
-        *
-        * \param changemsg The change message group to process.
-        */
-       void receiveChange(Glib::ustring const& changemsg);
-
-       // Logging and session file handling
-       /**
-        * Start a session log with the given filename.
-        *
-        * \param filename Full path to the file that the session log should be written to.
-        * \throw Glib::FileError Thrown if an exception is thrown during session file creation.
-        */
-       void startLog(Glib::ustring filename);
-
-       /**
-        * Load a session file for playback.
-        *
-        * \param filename Full path to the session file that is to be loaded.
-        */
-       void loadSessionFile(Glib::ustring filename);
-
-       /**
-        * Returns whether or not the session is in session file playback mode.
-        *
-        * \return Whether or not the session is in session file playback mode.
-        */
-       bool isPlayingSessionFile();
-
-       // User event notification
-       
-       /**
-        * Method to notify the user that a whiteboard session to another user has been successfully
-        * established.
-        *
-        * \param JID The JID with whom the user established a session.
-        */
-       void userConnectedToWhiteboard(gchar const* JID);
-
-       /**
-        * Method to notify the user that the other user in a user-to-user whiteboard session
-        * has disconnected.
-        *
-        * \param JID The JID of the user who left the whiteboard session.
-        */
-       void userDisconnectedFromWhiteboard(std::string const& JID);
-
-       // Queue dispatching and UI setup
-       
-       /**
-        * Start the send queue for this session.
-        */
-       void startSendQueueDispatch();
-
-       /**
-        * Stop the send queue for this session.
-        */
-       void stopSendQueueDispatch();
-
-       /**
-        * Start the receive queue for this session.
-        */
-       void startReceiveQueueDispatch();
-
-       /**
-        * Stop the receive queue for this session.
-        */
-       void stopReceiveQueueDispatch();
-
-       /**
-        * Clear all layers, definitions, and metadata from the document with which a
-        * SessionManager instance is associated. 
-        *
-        * Documents are cleared to assist synchronization between two clients
-        * or a client and a chatroom.
-        */
-       void clearDocument();
-
-       /**
-        * Set up objects for handling actions generated by the user interacting with
-        * Inkscape.  This includes marking the active session as being in a whiteboard session,
-        * starting send and receive queues, and creating an event serializer and deserializer.
-        *
-        * \see Inkscape::Whiteboard::SendMessageQueue
-        * \see Inkscape::Whiteboard::ReceiveMessageQueue
-        * \see Inkscape::Whiteboard::Serializer
-        * \see Inkscape::Whiteboard::Deserializer
-        */
-       void setupInkscapeInterface();
-
-       /**
-        * Reset whiteboard verbs to INITIAL state.
-        */
-       void setInitialVerbSensitivity() {
-               this->_setVerbSensitivity(INITIAL);
        }
-
-       /**
-        * Set up the event commit listener.
-        *
-        * The event commit listener watches for events that are committed to the document's undo log,
-        * serializes those events, and then adds them to the message send queue.
-        *
-        * \see Inkscape::Whiteboard::SendMessageQueue
-        * \see Inkscape::Whiteboard::UndoStackObserver
-        */
-       void setupCommitListener();
-
-       // Private object retrieval
-       ::SPDesktop* desktop();
-       ::SPDocument* document();
-       Callbacks* callbacks();
-       Whiteboard::UndoStackObserver* undo_stack_observer();
-       Serializer* serializer();
-       XMLNodeTracker* node_tracker();
-       Deserializer* deserializer();
-       ChatMessageHandler* chat_handler();
-       SessionFilePlayer* session_player();
-       SessionFile* session_file();
-
 private:
-       // Internal logging methods
-       void _log(Glib::ustring const& message);
-       void _commitLog();
-       void _closeLog();
-       void _tryToStartLog();
-
-       enum SensitivityMode {
-                       INITIAL,
-                       ESTABLISHED_CONNECTION,
-                       ESTABLISHED_SESSION,
-                       DISCONNECTED_FROM_SESSION
+       // types
+    typedef std::pair< Glib::ustring, InkboardDocument* > Inkboard_record_type;
+    typedef std::vector< Inkboard_record_type, GC::Alloc< Inkboard_record_type, GC::MANUAL > > Inkboards_type;
+
+       typedef std::list< Glib::ustring > Pending_invitations_type;
+
+       typedef std::pair< Glib::ustring, InvitationResponses > Invitation_response_type;
+       typedef std::list< Invitation_response_type > Invitation_responses_type;
+
+       // functors
+       struct CheckInvitationSender {
+       public:
+               CheckInvitationSender(Glib::ustring const& x) : x(x) { }
+               ~CheckInvitationSender() { }
+
+               bool operator()(SessionManager::Invitation_response_type const& y) const {
+                       return (x == y.first);
+               }
+       private:
+               Glib::ustring const& x;
        };
 
-       void _setVerbSensitivity(SensitivityMode mode);
-
-       bool _pollReceiveConnectRequest(Glib::ustring const recipient);
-
-       ::SPDesktop* _myDesktop;
-       ::SPDocument* _myDoc;
-       Whiteboard::UndoStackObserver* _myUndoObserver;
-       XMLNodeTracker* _myTracker;
-       ChatMessageHandler* _myChatHandler;
-       Callbacks* _myCallbacks;
-       SessionFile* _mySessionFile;
-       SessionFilePlayer* _mySessionPlayer;
-       MessageHandler* _myMessageHandler;
-       Serializer* _mySerializer;
-       Deserializer* _myDeserializer; 
-
-       sigc::connection _send_queue_dispatcher;
-       sigc::connection _receive_queue_dispatcher;
-       sigc::connection _notify_incoming_request;
-
-       // noncopyable, nonassignable
-       SessionManager(SessionManager const&);
-       SessionManager& operator=(SessionManager const&);
+       // objects 
+    Pedro::PedroGui gui;
+    SendMessageQueue sendMessageQueue;
+    ReceiveMessageQueue receiveMessageQueue;
+
+       // members
+    unsigned long sequenceNumber;
+    Inkboards_type _inkboards;
+       Pending_invitations_type _pending_invitations;
+       Invitation_responses_type _invitation_responses;
+
+       sigc::connection _check_pending_invitations;
+       sigc::connection _check_invitation_responses;
+
+       // methods
+    void _processInkboardEvent(Pedro::XmppEvent const& event);
+       void _handleSessionEvent(MessageType mtype, Pedro::XmppEvent const& event);
+    void _handleIncomingInvitation(Glib::ustring const& from);
+       void _handleInvitationResponse(Glib::ustring const& from, InvitationResponses resp);
+
+       // methods handled externally
+       bool _checkInvitationQueue();
+       bool _checkInvitationResponseQueue();
 };
 
-}
+}  // namespace Whiteboard
 
-}
+}  // namespace Inkscape
 
-#endif
+#endif  /* __SESSION_MANAGER_H__ */
 
 /*
   Local Variables:
index bbaf527ced5b7df14396af88ffa6639100031b94..120c4d00ed0329acb16d8ccc64313a115835c444 100644 (file)
@@ -86,9 +86,9 @@ private:
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
index 10adbdaf89a279075a181637a590b3480cd53377..363a686064a82bf825cc3c369abfb0ea4bda1b05 100644 (file)
 #ifndef __WHITEBOARD_TYPEDEFS_H__
 #define __WHITEBOARD_TYPEDEFS_H__
 
-extern "C" {
-#include <loudmouth/loudmouth.h>
-}
-
 #include <algorithm>
 #include <cstring>
 #include <string>
 #include <map>
 #include <set>
 #include <bitset>
+#include <vector>
 
 #include <glibmm.h>
 #include <sigc++/sigc++.h>
 
 #include "jabber_whiteboard/defines.h"
+#include "jabber_whiteboard/keynode.h"
 
 #include "gc-alloc.h"
 
@@ -87,11 +85,11 @@ namespace Whiteboard {
 
 /// Associates node keys to pointers to XML::Nodes.
 /// \see Inkscape::Whiteboard::XMLNodeTracker
-typedef std::map< std::string, XML::Node*, std::less< std::string >, GC::Alloc< std::pair< const std::string, XML::Node* >, GC::MANUAL > > KeyToTrackerNodeMap;
+typedef std::map< std::string, XML::Node*, std::less< std::string >, GC::Alloc< std::pair< std::string, XML::Node* >, GC::MANUAL > > KeyToTrackerNodeMap;
 
 /// Associates pointers to XML::Nodes with node keys.
 /// \see Inkscape::Whiteboard::XMLNodeTracker
-typedef std::map< XML::Node*, std::string, std::less< XML::Node* >, GC::Alloc< std::pair< XML::Node* const, std::string >, GC::MANUAL > > TrackerNodeToKeyMap;
+typedef std::map< XML::Node*, std::string, std::less< XML::Node* >, GC::Alloc< std::pair< XML::Node*, std::string >, GC::MANUAL > > TrackerNodeToKeyMap;
 
 
 // TODO: Clean up these typedefs.  I'm sure quite a few of these aren't used anymore; additionally,
@@ -100,7 +98,6 @@ typedef std::map< XML::Node*, std::string, std::less< XML::Node* >, GC::Alloc< s
 // Temporary storage of new object messages and new nodes in said messages
 typedef std::list< Glib::ustring > NewChildObjectMessageList;
 
-typedef std::pair< std::string, XML::Node* > KeyNodePair;
 typedef std::pair< KeyNodePair, NodeTrackerAction > SerializedEventNodeAction;
 
 typedef std::list< SerializedEventNodeAction > KeyToNodeActionList;
@@ -113,6 +110,7 @@ typedef std::set< XML::Node* > AttributesUpdatedSet;
 typedef std::map< std::string, XML::Node const* > KeyToNodeMap;
 typedef std::map< XML::Node const*, std::string > NodeToKeyMap;
 
+    
 // Buddy list management
 typedef std::set< std::string > BuddyList;
 typedef sigc::signal< void, std::string const& > BuddyListSignal;
@@ -126,9 +124,9 @@ struct MessageProcessor;
 class ReceiveMessageQueue;
 
 typedef std::map< MessageType, std::bitset< NUM_FLAGS > > MessageContextMap;
-typedef std::map< MessageType, MessageProcessor*, std::less< MessageType >, GC::Alloc< std::pair< const MessageType, MessageProcessor* >, GC::MANUAL > > MessageProcessorMap;
+typedef std::map< MessageType, MessageProcessor*, std::less< MessageType >, GC::Alloc< std::pair< MessageType, MessageProcessor* >, GC::MANUAL > > MessageProcessorMap;
 
-typedef std::map< std::string, ReceiveMessageQueue*, std::less< std::string >, GC::Alloc< std::pair< const std::string, ReceiveMessageQueue* >, GC::MANUAL > > RecipientToReceiveQueueMap;
+typedef std::map< std::string, ReceiveMessageQueue*, std::less< std::string >, GC::Alloc< std::pair< std::string, ReceiveMessageQueue* >, GC::MANUAL > > RecipientToReceiveQueueMap;
 typedef std::map< std::string, unsigned int > ReceipientToLatestTransactionMap;
 
 typedef std::string ReceivedCommitEvent;
@@ -151,9 +149,9 @@ typedef std::list< Glib::ustring > SerializedEventList;
   Local Variables:
   mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  c-file-offsets:((innamespace . 0)(inline-open . 0))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/jabber_whiteboard/undo-stack-observer.cpp b/src/jabber_whiteboard/undo-stack-observer.cpp
deleted file mode 100644 (file)
index 7750dc7..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/**
- * Undo / redo / undo log commit listener
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "document.h"
-#include "document-private.h"
-
-#include "xml/event.h"
-#include "xml/event-fns.h"
-#include "undo-stack-observer.h"
-
-#include "util/list.h"
-#include "util/reverse-list.h"
-
-#include "jabber_whiteboard/defines.h"
-#include "jabber_whiteboard/session-manager.h"
-#include "jabber_whiteboard/node-tracker.h"
-#include "jabber_whiteboard/serializer.h"
-#include "jabber_whiteboard/message-utilities.h"
-#include "jabber_whiteboard/message-aggregator.h"
-#include "jabber_whiteboard/message-tags.h"
-
-
-#include <glibmm.h>
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-UndoStackObserver::UndoStackObserver(SessionManager* sm) : _sm(sm), _undoSendEventLocks(0), _redoSendEventLocks(0), _undoCommitSendEventLocks(0) { 
-}
-
-UndoStackObserver::~UndoStackObserver() { }
-
-void
-UndoStackObserver::notifyUndoEvent(XML::Event* log)
-{
-       if (this->_undoSendEventLocks == 0) {
-               bool chatroom = this->_sm->session_data->status.test(IN_CHATROOM);
-               Glib::ustring commit = MessageUtilities::makeTagWithContent(MESSAGE_UNDO, "");
-               this->_sm->sendChange(commit, CHANGE_COMMIT, "", chatroom);
-       }
-
-       // Retrieve and process added/deleted nodes in the undo log
-       // TODO: re-enable; right now it doesn't work because we can't recover the names
-       // of deleted nodes (although perhaps creating a subclass of XML::Event that stored
-       // names of serialized nodes along with all other Event information would fix this)
-       /*
-       KeyToNodeActionMap node_actions = this->_action_observer.getNodeActionMap();
-       this->_sm->node_tracker()->process(node_actions);
-       this->_action_observer.clearNodeBuffers();
-       */
-       
-}
-
-void
-UndoStackObserver::notifyRedoEvent(XML::Event* log)
-{
-       if (this->_redoSendEventLocks == 0) {
-               bool chatroom = this->_sm->session_data->status.test(IN_CHATROOM);
-               Glib::ustring commit = MessageUtilities::makeTagWithContent(MESSAGE_REDO, "");
-               this->_sm->sendChange(commit, CHANGE_COMMIT, "", chatroom);
-       }
-
-       // Retrieve and process added/deleted nodes in the redo log
-       /*
-       KeyToNodeActionMap node_actions = this->_action_observer.getNodeActionMap();
-       this->_sm->node_tracker()->process(node_actions);
-       this->_action_observer.clearNodeBuffers();
-       */
-}
-
-void
-UndoStackObserver::notifyUndoCommitEvent(XML::Event* log)
-{
-       if (this->_undoCommitSendEventLocks == 0) {
-               this->_doAction(log);
-       }
-}
-
-void
-UndoStackObserver::lockObserverFromSending(ObserverType type)
-{
-       switch (type) {
-               case UNDO_EVENT:
-                       ++this->_undoSendEventLocks;
-                       break;
-               case REDO_EVENT:
-                       ++this->_redoSendEventLocks;
-                       break;
-               case UNDO_COMMIT_EVENT:
-                       ++this->_undoCommitSendEventLocks;
-                       break;
-               default:
-                       break;
-       }
-}
-
-void
-UndoStackObserver::unlockObserverFromSending(ObserverType type)
-{
-       switch(type) {
-               case UNDO_EVENT:
-                       if (this->_undoSendEventLocks) {
-                               --this->_undoSendEventLocks;
-                       }
-                       break;
-               case REDO_EVENT:
-                       if (this->_redoSendEventLocks) {
-                               --this->_redoSendEventLocks;
-                       }
-                       break;
-               case UNDO_COMMIT_EVENT:
-                       if (this->_undoCommitSendEventLocks) {
-                               --this->_undoCommitSendEventLocks;
-                       }
-                       break;
-               default:
-                       break;
-       }
-}
-
-void
-UndoStackObserver::_doAction(XML::Event* log)
-{
-       if (this->_sm->serializer()) {
-               bool chatroom = this->_sm->session_data->status.test(IN_CHATROOM);
-               XML::replay_log_to_observer(log, *this->_sm->serializer());
-
-               this->_sm->serializer()->synthesizeChildNodeAddEvents();
-
-               SerializedEventList& events = this->_sm->serializer()->getEventList();
-
-               SerializedEventList::iterator i = events.begin();
-               MessageAggregator& agg = MessageAggregator::instance();
-               Glib::ustring msgbuf;
-
-               while(i != events.end()) {
-                       while(agg.addOne(*i++, msgbuf)) {
-                               if (i == events.end()) {
-                                       break;
-                               }
-                       }
-
-                       if (i != events.end()) {
-                               i--;
-                       }
-
-                       this->_sm->sendChange(msgbuf, CHANGE_REPEATABLE, "", chatroom);
-                       msgbuf.clear();
-               }
-
-               KeyToNodeActionList& node_actions = this->_sm->serializer()->getNodeTrackerActions();
-               this->_sm->node_tracker()->process(node_actions);
-               this->_sm->serializer()->reset();
-               Glib::ustring commit = MessageUtilities::makeTagWithContent(MESSAGE_COMMIT, "");
-               this->_sm->sendChange(commit, CHANGE_COMMIT, "", chatroom);
-       }
-}
-
-}
-
-}
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/jabber_whiteboard/undo-stack-observer.h b/src/jabber_whiteboard/undo-stack-observer.h
deleted file mode 100644 (file)
index 3b38847..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Undo / redo / undo log commit listener
- *
- * Authors:
- * David Yip <yipdw@rose-hulman.edu>
- *
- * Copyright (c) 2005 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef __WHITEBOARD_UNDO_COMMIT_OBSERVER_H__
-#define __WHITEBOARD_UNDO_COMMIT_OBSERVER_H__
-
-#include <glibmm.h>
-#include "../undo-stack-observer.h"
-#include "jabber_whiteboard/typedefs.h"
-
-namespace Inkscape {
-
-namespace Whiteboard {
-
-class SessionManager;
-
-/**
- * Inkboard implementation of Inkscape::UndoStackObserver.
- */
-class UndoStackObserver : public Inkscape::UndoStackObserver {
-public:
-       enum ObserverType {
-               UNDO_EVENT,
-               REDO_EVENT,
-               UNDO_COMMIT_EVENT
-       };
-
-       UndoStackObserver(SessionManager* sm);
-       ~UndoStackObserver();
-       void notifyUndoEvent(XML::Event* log);
-       void notifyRedoEvent(XML::Event* log);
-       void notifyUndoCommitEvent(XML::Event* log);
-
-       void lockObserverFromSending(ObserverType type);
-       void unlockObserverFromSending(ObserverType type);
-
-private:
-       SessionManager* _sm;
-
-       // common action handler
-       void _doAction(XML::Event* log);
-
-       // noncopyable, nonassignable
-       UndoStackObserver(UndoStackObserver const& other);
-       UndoStackObserver& operator=(UndoStackObserver const& other);
-
-       unsigned int _undoSendEventLocks;
-       unsigned int _redoSendEventLocks;
-       unsigned int _undoCommitSendEventLocks;
-};
-
-}
-
-}
-
-#endif
-
-/*
-  Local Variables:
-  mode:c++
-  c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
-  indent-tabs-mode:nil
-  fill-column:99
-  End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 986b36edfc65c725e48163c9f764371407f9df38..66d1acb897e1a3fc6b852b47b5566dc22fd34cbe 100644 (file)
@@ -228,16 +228,7 @@ static char const menus_skeleton[] =
 "   </submenu>\n"
 #ifdef WITH_INKBOARD
 "      <submenu name=\"" N_("Whiteboa_rd") "\">\n"
-"              <verb verb-id=\"DialogWhiteboardConnect\" />\n"
-"              <verb verb-id=\"DialogWhiteboardDisconnectSession\" />\n"
-"              <verb verb-id=\"DialogWhiteboardDisconnectServer\" />\n"
-"              <separator/>\n"
-"              <verb verb-id=\"DialogWhiteboardShareWithUser\" />\n"
-"              <verb verb-id=\"DialogWhiteboardShareWithChat\" />\n"
-"              <separator/>\n"
-"              <verb verb-id=\"DialogWhiteboardOpenSessionFile\" />\n"
-"              <separator/>\n"
-"              <verb verb-id=\"DialogWhiteboardDumpXMLTracker\" />\n"
+"              <verb verb-id=\"DialogXmppClient\" />\n"
 "      </submenu>\n"
 #endif
 "   <submenu name=\"" N_("_Help") "\">\n"
index 7ab87c7d3f2c53cadf758cf865d0f7b4924052a9..4e40b645d8648aec3036a8a23a05c306ebc2a376 100644 (file)
@@ -5,18 +5,6 @@ ui/dialog/all: ui/dialog/libuidialog.a
 ui/dialog/clean:
        rm -f ui/dialog/libuidialog.a $(ui_libuidialog_a_OBJECTS)
 
-if WITH_INKBOARD
-inkboard_dialogs = \
-       ui/dialog/session-player.cpp    \
-       ui/dialog/session-player.h      \
-       ui/dialog/whiteboard-connect.cpp \
-       ui/dialog/whiteboard-connect.h \
-       ui/dialog/whiteboard-sharewithuser.cpp \
-       ui/dialog/whiteboard-sharewithuser.h \
-       ui/dialog/whiteboard-sharewithchat.cpp \
-       ui/dialog/whiteboard-sharewithchat.h
-endif
-
 ui_dialog_libuidialog_a_SOURCES =              \
        ui/dialog/dialog-manager.cpp            \
        ui/dialog/dialog-manager.h              \
@@ -54,7 +42,6 @@ ui_dialog_libuidialog_a_SOURCES =             \
        ui/dialog/transformation.h              \
        ui/dialog/tree-editor.cpp               \
        ui/dialog/tree-editor.h                 \
-       $(inkboard_dialogs)     \
        ui/dialog/xml-editor.cpp                \
        ui/dialog/xml-editor.h                  \
        ui/dialog/aboutbox.cpp          \
index 80fae2c9219d48cd934ff7c055ffd356eb13e313..f4099b0500bb9c46bcfb82faa979a4ec8a370d6b 100644 (file)
 #include "ui/dialog/tracedialog.h"
 #include "ui/dialog/transformation.h"
 
-#ifdef WITH_INKBOARD
-#include "ui/dialog/whiteboard-sharewithchat.h"
-#include "ui/dialog/whiteboard-sharewithuser.h"
-#include "ui/dialog/whiteboard-connect.h"
-#include "ui/dialog/session-player.h"
-#endif
-
 #include "ui/dialog/xml-editor.h"
 
 #include "dialogs/tiledialog.h"
@@ -92,12 +85,6 @@ DialogManager::DialogManager() {
     registerFactory("TileDialog",          &create<TileDialog>);
     registerFactory("Trace",               &create<TraceDialog>);
     registerFactory("Transformation",      &create<Transformation>);
-#ifdef WITH_INKBOARD
-       registerFactory("SessionPlayer",       &create<SessionPlaybackDialog>);
-    registerFactory("WhiteboardConnect",   &create<WhiteboardConnectDialog>);
-    registerFactory("WhiteboardShareWithUser",   &create<WhiteboardShareWithUserDialog>);
-    registerFactory("WhiteboardShareWithChat",   &create<WhiteboardShareWithChatroomDialog>);
-#endif
     registerFactory("XmlEditor",           &create<XmlEditor>);
 }
 
index c42f447493cd1e39d03e44d08acc0de74c786103..55f63b443b586eaad8d6f84217af0f39985fa42f 100644 (file)
 #include "interface.h"
 #include "extension/db.h"
 
-#ifdef WITH_INKBOARD
-#include "ui/dialog/whiteboard-connect.h"
-#include "ui/dialog/whiteboard-sharewithuser.h"
-#include "ui/dialog/whiteboard-sharewithchat.h"
-#endif
-
 using namespace Inkscape::UI;
 using namespace Inkscape::UI::Widget;
 
@@ -302,45 +296,6 @@ EditWidget::onDialogXmlEditor()
     _dlg_mgr.showDialog("XmlEditor");
 }
 
-#ifdef WITH_INKBOARD
-void
-EditWidget::onDialogWhiteboardConnect()
-{
-       Dialog::WhiteboardConnectDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardConnectDialogImpl* >(_dlg_mgr.getDialog("WhiteboardConnect"));
-       dlg->setSessionManager();
-       _dlg_mgr.showDialog("WhiteboardConnect");
-}
-
-void
-EditWidget::onDialogWhiteboardShareWithUser()
-{
-               Dialog::WhiteboardShareWithUserDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardShareWithUserDialogImpl* >(_dlg_mgr.getDialog("WhiteboardShareWithUser"));
-               dlg->setSessionManager();
-               _dlg_mgr.showDialog("WhiteboardShareWithUser");
-}
-
-void
-EditWidget::onDialogWhiteboardShareWithChat()
-{
-       Dialog::WhiteboardShareWithChatroomDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardShareWithChatroomDialogImpl* >(_dlg_mgr.getDialog("WhiteboardShareWithChat"));
-       dlg->setSessionManager();
-       _dlg_mgr.showDialog("WhiteboardShareWithChat");
-}
-
-void
-EditWidget::onDialogOpenSessionFile()
-{
-       g_log(NULL, G_LOG_LEVEL_DEBUG, "not reimplemented yet");
-}
-
-void
-EditWidget::onDumpXMLTracker()
-{
-       g_log(NULL, G_LOG_LEVEL_DEBUG, "not reimplemented yet");
-}
-
-#endif
-
 void
 EditWidget::onUriChanged()
 {
@@ -361,9 +316,6 @@ EditWidget::initMenuActions()
 //    _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate")));
 //    _act_grp->add(Gtk::Action::create("MenuPath",   _("PLACEHOLDER, do not translate")));
 //    _act_grp->add(Gtk::Action::create("MenuText",   _("PLACEHOLDER, do not translate")));
-#ifdef WITH_INKBOARD
-//    _act_grp->add(Gtk::Action::create("MenuWhiteboard",   _("PLACEHOLDER, do not translate")));
-#endif
 //    _act_grp->add(Gtk::Action::create("MenuHelp",   _("PLACEHOLDER, do not translate")));
 // temporarily replaced with non-gettext version to have a well-sized menu
 // for testing:
@@ -375,9 +327,6 @@ EditWidget::initMenuActions()
     _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
     _act_grp->add(Gtk::Action::create("MenuPath",   "Path"));
     _act_grp->add(Gtk::Action::create("MenuText",   "Text"));
-#ifdef WITH_INKBOARD
-    _act_grp->add(Gtk::Action::create("MenuWhiteboard",   "Whiteboard"));
-#endif
     _act_grp->add(Gtk::Action::create("MenuHelp",   "Help"));
 
     // File menu
@@ -821,30 +770,6 @@ EditWidget::initMenuActions()
 
        // Whiteboard menu
 #ifdef WITH_INKBOARD
-    _act_grp->add(Gtk::Action::create("DialogWhiteboardConnect",
-                                      Gtk::Stock::CLEAR, Glib::ustring(),
-                                      _("PLACEHOLDER, do not translate")),
-                  sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardConnect));
-
-    _act_grp->add(Gtk::Action::create("DialogWhiteboardShareWithUser",
-                                      Gtk::Stock::CLEAR, Glib::ustring(),
-                                      _("PLACEHOLDER, do not translate")),
-                  sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardShareWithUser));
-
-    _act_grp->add(Gtk::Action::create("DialogWhiteboardShareWithChat",
-                                      Gtk::Stock::CLEAR, Glib::ustring(),
-                                      _("PLACEHOLDER, do not translate")),
-                  sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardShareWithChat));
-
-    _act_grp->add(Gtk::Action::create("WhiteboardOpenSessionFile",
-                                      Gtk::Stock::CLEAR, Glib::ustring(),
-                                      _("PLACEHOLDER, do not translate")),
-                  sigc::mem_fun(*this, &EditWidget::onDialogOpenSessionFile));
-
-    _act_grp->add(Gtk::Action::create("WhiteboardDumpXMLTracker",
-                                      Gtk::Stock::CLEAR, Glib::ustring(),
-                                      _("PLACEHOLDER, do not translate")),
-                  sigc::mem_fun(*this, &EditWidget::onDumpXMLTracker));
 #endif
 
     // About menu
index 9458d2d1760e5458434d815c8c753c9df1e841da..5649d08956942ed724d7b04113b5cd40163f7a09 100644 (file)
 #include "dialogs/input.h"
 
 #ifdef WITH_INKBOARD
-#include "ui/dialog/whiteboard-connect.h"
-#include "ui/dialog/whiteboard-sharewithuser.h"
-#include "ui/dialog/whiteboard-sharewithchat.h"
 #include "jabber_whiteboard/session-manager.h"
-#include "jabber_whiteboard/node-tracker.h"
 #endif
 
 #include "extension/effect.h"
@@ -1576,90 +1572,9 @@ DialogVerb::perform(SPAction *action, void *data, void *pdata)
             sp_item_dialog();
             break;
 #ifdef WITH_INKBOARD
-        case SP_VERB_DIALOG_WHITEBOARD_CONNECT: {
-            // We need to ensure that this dialog is associated with the correct SessionManager,
-            // since the user may have opened a new document (and hence swapped SessionManager
-            // instances) sometime before this dialog invocation
-            Inkscape::UI::Dialog::WhiteboardConnectDialogImpl *dlg = dynamic_cast< Inkscape::UI::Dialog::WhiteboardConnectDialogImpl *>(dt->_dlg_mgr->getDialog("WhiteboardConnect"));
-            dlg->setSessionManager();
-            dt->_dlg_mgr->showDialog("WhiteboardConnect");
-            break;
-        }
-        case SP_VERB_DIALOG_WHITEBOARD_SHAREWITHUSER: {
-            //sp_whiteboard_sharewithuser_dialog(NULL);
-            Inkscape::Whiteboard::SessionManager *sm = SP_ACTIVE_DESKTOP->whiteboard_session_manager();
-            if (sm->session_data && sm->session_data->status[Inkscape::Whiteboard::LOGGED_IN]) {
-                // We need to ensure that this dialog is associated with the correct SessionManager,
-                // since the user may have opened a new document (and hence swapped SessionManager
-                // instances) sometime before this dialog invocation
-                Inkscape::UI::Dialog::WhiteboardShareWithUserDialogImpl *dlg = dynamic_cast< Inkscape::UI::Dialog::WhiteboardShareWithUserDialogImpl *>(dt->_dlg_mgr->getDialog("WhiteboardShareWithUser"));
-                dlg->setSessionManager();
-                dt->_dlg_mgr->showDialog("WhiteboardShareWithUser");
-            } else {
-                Gtk::MessageDialog dlg(_("You need to connect to a Jabber server before sharing a document with another user."), true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE);
-                dlg.run();
-            }
-            break;
-        }
-        case SP_VERB_DIALOG_WHITEBOARD_SHAREWITHCHAT: {
-            Inkscape::Whiteboard::SessionManager *sm = SP_ACTIVE_DESKTOP->whiteboard_session_manager();
-            if (sm->session_data && sm->session_data->status[Inkscape::Whiteboard::LOGGED_IN]) {
-                // We need to ensure that this dialog is associated with the correct SessionManager,
-                // since the user may have opened a new document (and hence swapped SessionManager
-                // instances) sometime before this dialog invocation
-                Inkscape::UI::Dialog::WhiteboardShareWithChatroomDialogImpl *dlg = dynamic_cast< Inkscape::UI::Dialog::WhiteboardShareWithChatroomDialogImpl *>(dt->_dlg_mgr->getDialog("WhiteboardShareWithChat"));
-                dlg->setSessionManager();
-                dt->_dlg_mgr->showDialog("WhiteboardShareWithChat");
-            } else {
-                Gtk::MessageDialog dlg(_("You need to connect to a Jabber server before sharing a document with a chatroom."), true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE);
-                dlg.run();
-            }
-            break;
-        }
-
-        case SP_VERB_DIALOG_WHITEBOARD_DUMPXMLTRACKER:
-            if (SP_ACTIVE_DESKTOP->whiteboard_session_manager()->node_tracker()) {
-                SP_ACTIVE_DESKTOP->whiteboard_session_manager()->node_tracker()->dump();
-            } else {
-                g_log(NULL, G_LOG_LEVEL_DEBUG, _("XML node tracker has not been initialized; nothing to dump"));
-            }
-            break;
-        case SP_VERB_DIALOG_WHITEBOARD_OPENSESSIONFILE: {
-            Gtk::FileChooserDialog sessionfiledlg(_("Open session file"), Gtk::FILE_CHOOSER_ACTION_OPEN);
-            sessionfiledlg.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
-            sessionfiledlg.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
-
-            int result = sessionfiledlg.run();
-            switch (result) {
-                case Gtk::RESPONSE_OK:
-                {
-                    SP_ACTIVE_DESKTOP->whiteboard_session_manager()->clearDocument();
-                    SP_ACTIVE_DESKTOP->whiteboard_session_manager()->loadSessionFile(sessionfiledlg.get_filename());
-                    dt->_dlg_mgr->showDialog("SessionPlayer");
-                    //SP_ACTIVE_DESKTOP->whiteboard_session_manager()->session_player()->start();
-                    break;
-                }
-                case Gtk::RESPONSE_CANCEL:
-                default:
-                    break;
-            }
-            break;
-        }
-
-               case SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SESSION:
-               {
-            Inkscape::Whiteboard::SessionManager *sm = SP_ACTIVE_DESKTOP->whiteboard_session_manager();
-            if (sm->session_data && sm->session_data->status[Inkscape::Whiteboard::IN_WHITEBOARD]) {
-                               SP_ACTIVE_DESKTOP->whiteboard_session_manager()->disconnectFromDocument();
-                       }
-                       break;
-               }
-               case SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SERVER:
+        case SP_VERB_XMPP_CLIENT:
                {
-            Inkscape::Whiteboard::SessionManager *sm = SP_ACTIVE_DESKTOP->whiteboard_session_manager();
-            if (sm->session_data && sm->session_data->status[Inkscape::Whiteboard::LOGGED_IN]) {
-                               SP_ACTIVE_DESKTOP->whiteboard_session_manager()->disconnectFromServer();
-                       }
+            Inkscape::Whiteboard::SessionManager::showClient();
                        break;
                }
 #endif
@@ -2345,22 +2260,8 @@ Verb *Verb::_base_verbs[] = {
     new DialogVerb(SP_VERB_DIALOG_ITEM, "DialogObjectProperties", N_("_Object Properties..."),
                    N_("Edit the ID, locked and visible status, and other object properties"), "dialog_item_properties"),
 #ifdef WITH_INKBOARD
-    new DialogVerb(SP_VERB_DIALOG_WHITEBOARD_CONNECT, "DialogWhiteboardConnect",
-                   N_("_Connect to Jabber server..."), N_("Connect to a Jabber server"), NULL),
-    new DialogVerb(SP_VERB_DIALOG_WHITEBOARD_SHAREWITHUSER, "DialogWhiteboardShareWithUser",
-                   N_("Share with _user..."), N_("Establish a whiteboard session with another Jabber user"), NULL),
-    new DialogVerb(SP_VERB_DIALOG_WHITEBOARD_SHAREWITHCHAT, "DialogWhiteboardShareWithChat",
-                   N_("Share with _chatroom..."), N_("Join a chatroom to start a new whiteboard session or join one in progress"), NULL),
-    new DialogVerb(SP_VERB_DIALOG_WHITEBOARD_DUMPXMLTRACKER, "DialogWhiteboardDumpXMLTracker",
-                   N_("_Dump XML node tracker"), N_("Dump the contents of the XML tracker to the console"), NULL),
-    new DialogVerb(SP_VERB_DIALOG_WHITEBOARD_OPENSESSIONFILE, "DialogWhiteboardOpenSessionFile",
-                   N_("_Open session file..."), N_("Open and browse through records of past whiteboard sessions"), NULL),
-    new DialogVerb(SP_VERB_DIALOG_WHITEBOARD_SESSIONPLAYBACK, "DialogWhiteboardSessionPlayback",
-                   N_("Session file playback"), "", NULL),
-    new DialogVerb(SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SESSION, "DialogWhiteboardDisconnectSession",
-                   N_("_Disconnect from session"), "", NULL),
-    new DialogVerb(SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SERVER, "DialogWhiteboardDisconnectServer",
-                   N_("Disconnect from _server"), "", NULL),
+    new DialogVerb(SP_VERB_XMPP_CLIENT, "DialogXmppClient",
+                   N_("_Instant Messaging..."), N_("Jabber Instant Messaging Client"), NULL),
 #endif
     new DialogVerb(SP_VERB_DIALOG_INPUT, "DialogInput", N_("_Input Devices..."),
                    N_("Configure extended input devices, such as a graphics tablet"), NULL),
index 5d364c53bdf6823bcf310b3e3ad812f7cf0cfa8c..37f6f424bccaf0287ef46d03bf36b6372f5712e5 100644 (file)
@@ -196,14 +196,7 @@ enum {
     SP_VERB_DIALOG_CLONETILER,
     SP_VERB_DIALOG_ITEM,
 #ifdef WITH_INKBOARD
-    SP_VERB_DIALOG_WHITEBOARD_CONNECT,
-    SP_VERB_DIALOG_WHITEBOARD_SHAREWITHUSER,
-    SP_VERB_DIALOG_WHITEBOARD_SHAREWITHCHAT,
-    SP_VERB_DIALOG_WHITEBOARD_DUMPXMLTRACKER,
-    SP_VERB_DIALOG_WHITEBOARD_OPENSESSIONFILE,
-    SP_VERB_DIALOG_WHITEBOARD_SESSIONPLAYBACK,
-    SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SESSION,
-    SP_VERB_DIALOG_WHITEBOARD_DISCONNECT_FROM_SERVER,
+    SP_VERB_XMPP_CLIENT,
 #endif
     SP_VERB_DIALOG_INPUT,
     SP_VERB_DIALOG_EXTENSIONEDITOR,