summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c73fd7f)
raw | patch | inline | side by side (parent: c73fd7f)
author | daleharvey <daleharvey@users.sourceforge.net> | |
Fri, 23 Jun 2006 13:15:16 +0000 (13:15 +0000) | ||
committer | daleharvey <daleharvey@users.sourceforge.net> | |
Fri, 23 Jun 2006 13:15:16 +0000 (13:15 +0000) |
84 files changed:
diff --git a/configure.ac b/configure.ac
index 8ababdbbbd7d1ab02f560abfca9336d0124c533d..e83e54676ed53cfba601b9dfd3a4daa9119b2a9d 100644 (file)
--- a/configure.ac
+++ b/configure.ac
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
src/libnrtype/makefile
src/libavoid/makefile
src/livarot/makefile
+src/pedro/makefile
src/jabber_whiteboard/makefile
src/removeoverlap/makefile
src/svg/makefile
Use relocation support: ${enable_binreloc}
Enable LittleCms: ${enable_lcms}
Enable Inkboard: ${with_inkboard}
+ Enable SSL in Inkboard: ${with_inkboard_ssl}
"
diff --git a/mkinstalldirs b/mkinstalldirs
index d2d5f21b611235316317197d3a32c2dff5897a6f..259dbfcd35789bd0f087803d193cfd924f9a5f34 100755 (executable)
--- a/mkinstalldirs
+++ b/mkinstalldirs
#! /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
dirmode=$1
shift
;;
+ --version)
+ echo "$0 $scriptversion"
+ exit $?
+ ;;
--) # stop option processing
shift
break
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
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
# 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
--- /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>
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b284e27d356fa49373ddde9f1c84ab7a88c8d07..090b4c683e3d9d27005b3bfe70ac64cc16b360c8 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
$(FREETYPE_CFLAGS) \
$(GNOME_PRINT_CFLAGS) \
$(GNOME_VFS_CFLAGS) \
- $(LIBLOUDMOUTH_CFLAGS) \
+ $(INKBOARD_CFLAGS) \
$(XFT_CFLAGS) \
-DPOTRACE=\"potrace\" \
$(INKSCAPE_CFLAGS) \
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
libinkpre.a \
application/libinkapp.a \
dialogs/libspdialogs.a \
+ pedro/libpedro.a \
jabber_whiteboard/libjabber_whiteboard.a \
display/libspdisplay.a \
dom/libdom.a \
io/makefile.in \
io/crystalegg.xml \
io/doc2html.xsl \
+ pedro/makefile.in \
jabber_whiteboard/makefile.in \
libcroco/makefile.in \
libnr/makefile.in \
diff --git a/src/Makefile_insert b/src/Makefile_insert
index f6c591d831546b22a565ce7b2598df9bce2eb8c8..c3182f3cc1115309ddb096514a8b7bd12e251891 100644 (file)
--- a/src/Makefile_insert
+++ b/src/Makefile_insert
ui/dialog/libuidialog.a \
dialogs/libspdialogs.a \
jabber_whiteboard/libjabber_whiteboard.a \
+ pedro/libpedro.a \
trace/libtrace.a \
svg/libspsvg.a \
widgets/libspwidgets.a \
$(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
diff --git a/src/desktop.cpp b/src/desktop.cpp
index 7d99043421fb2272c7bdd05221481cf7c1206d2b..49a43bc37b53e98bdfbb7064fe0c7d53cd649aaa 100644 (file)
--- a/src/desktop.cpp
+++ b/src/desktop.cpp
#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
/* 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 =
drawing = NULL;
}
-#ifdef WITH_INKBOARD
- if (_whiteboard_session_manager) {
- delete _whiteboard_session_manager;
- }
-#endif
-
delete _guides_message_context;
_guides_message_context = NULL;
diff --git a/src/document.cpp b/src/document.cpp
index e42f6c8cb57029c2b55e4225e76582c0b50c596e..cf03f4188391a87adb218d3c5744c6b5736f6eff 100644 (file)
--- a/src/document.cpp
+++ b/src/document.cpp
actionkey = NULL;
}
-static SPDocument *
+SPDocument *
sp_document_create(Inkscape::XML::Document *rdoc,
gchar const *uri,
gchar const *base,
diff --git a/src/document.h b/src/document.h
index 4d293e981479a12f1fa68c0b7533621aef8bbd77..9739b69719baca6dbc9a4c38e76c87387b1e67cc 100644 (file)
--- a/src/document.h
+++ b/src/document.h
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
*/
diff --git a/src/file.cpp b/src/file.cpp
index 5c236da82aade712cd236b5dc18831455a495f65..679c28801c5a6a40a5e8f2ce918e7a9012bd28d6 100644 (file)
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -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)
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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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)
* 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"
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,
// 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
+++ /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
+++ /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)
-/// 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
+++ /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
--- /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
--- /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
--- /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
--- /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
diff --git a/src/jabber_whiteboard/internal-constants.cpp b/src/jabber_whiteboard/internal-constants.cpp
index 4956a402c54ab7cfe9cc2756117cf46425816c3b..44355c8a0f32920bdb3874aa067e5d75e048d86c 100644 (file)
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/internal-constants.h b/src/jabber_whiteboard/internal-constants.h
index 5a14737beefc760bed9563f7f08dcd3d8cabfadd..737eacdc7d9b25a52e22aa6c998933d3fa0fa8c5 100644 (file)
// accomodate Inkscape, not the other way around...
// Dispatch interval (in milliseconds)
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 :
diff --git a/src/jabber_whiteboard/invitation-confirm-dialog.cpp b/src/jabber_whiteboard/invitation-confirm-dialog.cpp
index 8590abab8bf7901a35a99aa2740b9f56b28e1851..77fd75fcd740e7ede8450c3ce682196bc9932806 100644 (file)
* 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"
diff --git a/src/jabber_whiteboard/invitation-confirm-dialog.h b/src/jabber_whiteboard/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
--- /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
+++ /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
+++ /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
--- /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
--- /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__ */
+
+
diff --git a/src/jabber_whiteboard/message-aggregator.cpp b/src/jabber_whiteboard/message-aggregator.cpp
index 2077dcc6dc2436617567cd0cbd65174aa84897e3..7d4ee4b3f4cd4357b12b284e8d732aa75f4b7509 100644 (file)
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-aggregator.h b/src/jabber_whiteboard/message-aggregator.h
index 56cd8e3da5c722424e4e8ca07e2e1a1e153d14ea..505e65f121a9926e592f14899969645068790cae 100644 (file)
/**
* 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.
*/
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
+++ /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
+++ /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
+++ /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
+++ /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)
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
+++ /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
+++ /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)
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)
#include <map>
#include "gc-alloc.h"
-
#include "gc-managed.h"
#include "util/list-container.h"
namespace Whiteboard {
-class SessionManager;
class MessageNode;
/// Definition of the basic message node queue
*
* \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
* Implementation of the queue.
*/
MessageQueueBuffer _queue;
-
- /**
- * Pointer to SessionManager.
- */
- SessionManager* _sm;
};
*/
class ReceiveMessageQueue : public MessageQueue, public GC::Managed<> {
public:
- ReceiveMessageQueue(SessionManager* sm);
+ ReceiveMessageQueue() : _latest(0) { }
/**
* Insert a message into the queue.
*/
class SendMessageQueue : public MessageQueue {
public:
- SendMessageQueue(SessionManager* sm);
+ SendMessageQueue() { }
/**
* Insert a message into the queue.
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)
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)
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-utilities.cpp b/src/jabber_whiteboard/message-utilities.cpp
index c10521b61db945709839ae428b73bdc583007e8e..095c6bab3a1171d4aa044ec2609e2aad6ba01ba2 100644 (file)
//
// 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)
namespace Util {
-template <typename T>
+template< typename T >
class ptr_shared;
}
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&);
};
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
--- /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
--- /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
--- /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
+++ /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
+++ /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
+++ /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)
};
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];
}
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
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)
*/
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.
* \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.
* \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.
* \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.
* \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.
* \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.
* \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.
* \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
* \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.
* \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
*
* \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&);
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)
* 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"
}
*/
-Glib::ustring const
+Glib::ustring
NodeUtilities::nodeTypeToString(XML::Node const& node)
{
switch(node.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)
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
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
+++ /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[] =
-{
- { "&" , '&' },
- { "<" , '<' },
- { ">" , '>' },
- { "'", '\'' },
- { """, '"' },
- { 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("&");
- else if (ch == '<')
- ret.append("<");
- else if (ch == '>')
- ret.append(">");
- else if (ch == '\'')
- ret.append("'");
- else if (ch == '"')
- ret.append(""");
- 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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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 :
diff --git a/src/jabber_whiteboard/session-file-selector.cpp b/src/jabber_whiteboard/session-file-selector.cpp
index 85a3a3ec11212aa2ad231198e3a3b723b9c876af..854d61d107151bcc0b6a0dca58c5cdfe8710f43a 100644 (file)
* 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 {
diff --git a/src/jabber_whiteboard/session-file-selector.h b/src/jabber_whiteboard/session-file-selector.h
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
+++ /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
+++ /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)
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"
/// 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,
// 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;
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;
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;
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
+++ /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
+++ /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 :
diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h
index 986b36edfc65c725e48163c9f764371407f9df38..66d1acb897e1a3fc6b852b47b5566dc22fd34cbe 100644 (file)
--- a/src/menus-skeleton.h
+++ b/src/menus-skeleton.h
" </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)
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 \
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"
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;
_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()
{
// _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:
_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
// 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
diff --git a/src/verbs.cpp b/src/verbs.cpp
index 9458d2d1760e5458434d815c8c753c9df1e841da..5649d08956942ed724d7b04113b5cd40163f7a09 100644 (file)
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
#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"
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
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),
diff --git a/src/verbs.h b/src/verbs.h
index 5d364c53bdf6823bcf310b3e3ad812f7cf0cfa8c..37f6f424bccaf0287ef46d03bf36b6372f5712e5 100644 (file)
--- a/src/verbs.h
+++ b/src/verbs.h
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,