Code

removed resource name from self's jid, allowing authentication against jabber.org
[inkscape.git] / src / jabber_whiteboard / chat-handler.cpp
1 /**
2  * Whiteboard session manager
3  * Chatroom message handler
4  *
5  * Authors:
6  * David Yip <yipdw@rose-hulman.edu>
7  *
8  * Copyright (c) 2005 Authors
9  *
10  * Released under GNU GPL, read the file 'COPYING' for more information
11  */
13 #include <glibmm/i18n.h>
15 //#include <boost/lexical_cast.hpp>
17 #include "message-stack.h"
18 #include "desktop-handles.h"
19 #include "document.h"
21 #include "util/ucompose.hpp"
23 #include "xml/node.h"
25 #include "jabber_whiteboard/typedefs.h"
26 #include "jabber_whiteboard/message-utilities.h"
27 #include "jabber_whiteboard/message-queue.h"
28 #include "jabber_whiteboard/jabber-handlers.h"
29 #include "jabber_whiteboard/defines.h"
30 #include "jabber_whiteboard/session-manager.h"
31 #include "jabber_whiteboard/node-tracker.h"
32 #include "jabber_whiteboard/chat-handler.h"
33 #include "jabber_whiteboard/error-codes.h"
36 namespace Inkscape {
38 namespace Whiteboard {
40 ChatMessageHandler::ChatMessageHandler(SessionManager* sm) : _sm(sm)
41
43 }
45 ChatMessageHandler::~ChatMessageHandler() 
46 {
48 }
50 LmHandlerResult
51 ChatMessageHandler::parse(LmMessage* message)
52 {
53         // Retrieve the message type
54         LmMessageType mtype = lm_message_get_type(message);
56         // Retrieve root node of message
57         LmMessageNode* root = lm_message_get_node(message);
58         if (root == NULL) {
59                 g_warning("Received a chat message with NULL root node; discarding.");
60                 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
61         }
63         LmMessageSubType msubtype;
66         msubtype = lm_message_get_sub_type(message);
68         switch (mtype) {
69                 case LM_MESSAGE_TYPE_MESSAGE:
70                         switch(msubtype) {
71                                 case LM_MESSAGE_SUB_TYPE_ERROR:
72                                 {
73                                         LmMessageNode* error = lm_message_node_get_child(root, "error");
74                                         if (error != NULL) {
75                                                 this->_handleError(lm_message_node_get_attribute(error, "code"));
76                                         }
77                                         break;
78                                 }
79                                 case LM_MESSAGE_SUB_TYPE_GROUPCHAT:
80                                 {
81                                         // FIXME: We should be checking to see if we're in a room in the presence stanzas as indicated in
82                                         // <http://www.jabber.org/jeps/jep-0045.html#enter-pres> but current versions of mu-conference
83                                         // don't broadcast presence in the correct order.
84                                         //
85                                         // Therefore we need to use some sort of hacked-up method to make this work.  We listen for 
86                                         // the sentinel value in a groupchat message -- currently it is '[username] INKBOARD-JOINED' --
87                                         // and begin processing that way.
88                                         LmMessageNode* body = lm_message_node_get_child(root, "body");
89                                         if (body != NULL) {
90                                                 gchar const* val = lm_message_node_get_value(body);
91                                                 if (strcmp(val, String::ucompose("%1 has become available", this->_sm->session_data->chat_handle).c_str()) == 0) {
92                                                         return this->_finishConnection(); break;
93                                                 } else {
94                                                         return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
95                                                         break;
96                                                 }
97                                         } else {
98                                                 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
99                                                 break;
100                                         }
101                                 }
102                                                                                                 
103                                 default:
104                                         return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
105                                         break;
106                         }
107                         break;
108                 case LM_MESSAGE_TYPE_PRESENCE:
109                         // Retrieve the subtype.
110                         switch (msubtype) {
111                                 case LM_MESSAGE_SUB_TYPE_ERROR:
112                                 {
113                                         g_warning("Could not connect to chatroom");
114                                         // Extract error type
115                                         LmMessageNode* error = lm_message_node_get_child(root, "error");
116                                         if (error != NULL) {
117                                                 this->_handleError(lm_message_node_get_attribute(error, "code"));
118                                         }
119                                         // Reset status bits
120                                         this->_sm->session_data->status.set(CONNECTING_TO_CHAT, 0);
121                                         this->_sm->session_data->recipient = "";
122                                         this->_sm->session_data->chat_handle = "";
124                                         return LM_HANDLER_RESULT_REMOVE_MESSAGE;
125                                         break;
126                                 }
128                                 case LM_MESSAGE_SUB_TYPE_AVAILABLE: 
129                                 {
130                                         // Extract the handle
131                                         // (see JEP-0045, section 6.3.3 - <http://www.jabber.org/jeps/jep-0045.html#enter-pres>)
132                                         Glib::ustring sender = lm_message_node_get_attribute(root, MESSAGE_FROM);
133                                         Glib::ustring chatter = sender.substr(sender.find_last_of('/') + 1, sender.length());
134                                         if (chatter != this->_sm->session_data->chat_handle) {
135                                                 this->_sm->session_data->chatters.insert(g_strdup(chatter.data()));
136                                                 // Make a receive queue for this chatter
137                                                 this->_sm->session_data->receive_queues[sender.raw()] = new ReceiveMessageQueue(this->_sm);
138                                                 
139                                         } else {
140                                                 //g_warning("hmm, who is chatting %s",chatter);
141                                                 // If the presence message is from ourselves, then we know that we 
142                                                 // have successfully entered the chatroom _and_ have received the entire room roster,
143                                                 // and can therefore decide whether we need to synchronize with the rest of the room.
144                                                 // (see JEP-0045, section 6.3.3 - <http://www.jabber.org/jeps/jep-0045.html#enter-pres>)
145                                         }
146                                         return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
147                                 }
149                                 case LM_MESSAGE_SUB_TYPE_UNAVAILABLE:
150                                 {
151                                         Glib::ustring sender = lm_message_node_get_attribute(root, MESSAGE_FROM);
152                                         Glib::ustring chatter = sender.substr(sender.find_last_of('/') + 1, sender.length());
153                                         this->_sm->session_data->chatters.erase(chatter.data());
155                                         // Delete the message queue used by this sender
156                                         this->_sm->session_data->receive_queues.erase(sender.raw());
158                                         sp_desktop_message_stack(this->_sm->desktop())->flashF(Inkscape::INFORMATION_MESSAGE, _("<b>%s</b> has left the chatroom."), sender.c_str());
159                                 }
161                                 default:
162                                         // no idea what this message is; discard it
163                                         return LM_HANDLER_RESULT_REMOVE_MESSAGE;
164                                         break;
165                         }
166                         break;
167                 default:
168                         break;
169         }
171         return LM_HANDLER_RESULT_REMOVE_MESSAGE;
174 LmHandlerResult
175 ChatMessageHandler::_finishConnection()
177         if (this->_sm->session_data->status[CONNECTING_TO_CHAT]) {
178                 this->_sm->session_data->status.set(CONNECTING_TO_CHAT, 0);
180                 if (this->_sm->session_data->chatters.empty()) {
181                         // We are the only one in the chatroom, so there is no
182                         // need for synchronization
183                         this->_sm->session_data->status.set(IN_CHATROOM, 1);
185                         // Populate node tracker
186                         KeyToNodeMap newids;
187                         NodeToKeyMap newnodes;
188                         NewChildObjectMessageList newchildren;
190                         XML::Node* root = this->_sm->document()->rroot;
192                         this->_sm->setupInkscapeInterface();
193                         this->_sm->setupCommitListener();
195                         for ( Inkscape::XML::Node *child = root->firstChild() ; child != NULL ; child = child->next() ) {
196                                 MessageUtilities::newObjectMessage(NULL, newids, newnodes, newchildren, this->_sm->node_tracker(), child, true);
197                         }
199                         this->_sm->node_tracker()->put(newids, newnodes);
200         //              this->_sm->node_tracker()->dump();
202                 } else {
203                         this->_sm->session_data->status.set(WAITING_TO_SYNC_TO_CHAT, 1);
204                         // Send synchronization request to chatroom
205                         this->_sm->sendMessage(CHATROOM_SYNCHRONIZE_REQUEST, 0, "", this->_sm->session_data->recipient, true);
206                 }
207         }
208         return LM_HANDLER_RESULT_REMOVE_MESSAGE;
211 void
212 ChatMessageHandler::_handleError(char const* errcode)
214 //      try {
215         unsigned int code = atoi(errcode);
217 //              unsigned int code = boost::lexical_cast< unsigned int >(errcode);
219         Glib::ustring buf;
220         switch (code) {
221                 case ErrorCodes::CHAT_HANDLE_IN_USE:
222                         buf = String::ucompose(_("Nickname %1 is already in use.  Please choose a different nickname."), this->_sm->session_data->chat_handle);
223                         this->_sm->connectionError(buf);
224                         break;
225                 case ErrorCodes::SERVER_CONNECT_FAILED:
226                         buf = _("An error was encountered while attempting to connect to the server.");
227                         this->_sm->connectionError(buf);
228                         break;
229                 default:
230                         break;
231         }
232 //      } catch (boost::bad_lexical_cast&) {
234 //      }
241 /*
242   Local Variables:
243   mode:c++
244   c-file-style:"stroustrup"
245   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
246   indent-tabs-mode:nil
247   fill-column:99
248   End:
249 */
250 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :