summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/meanwhile/meanwhilesession.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/protocols/meanwhile/meanwhilesession.cpp')
-rw-r--r--kopete/protocols/meanwhile/meanwhilesession.cpp965
1 files changed, 965 insertions, 0 deletions
diff --git a/kopete/protocols/meanwhile/meanwhilesession.cpp b/kopete/protocols/meanwhile/meanwhilesession.cpp
new file mode 100644
index 00000000..974ca4af
--- /dev/null
+++ b/kopete/protocols/meanwhile/meanwhilesession.cpp
@@ -0,0 +1,965 @@
+/*
+ meanwhilesession.cpp - interface to the 'C' meanwhile library
+
+ Copyright (c) 2003-2004 by Sivaram Gottimukkala <suppandi@gmail.com>
+ Copyright (c) 2005 by Jeremy Kerr <jk@ozlabs.org>
+
+ Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+
+#include <kopetepassword.h>
+#include <kopetechatsession.h>
+#include <kopetegroup.h>
+#include <kopetecontactlist.h>
+#include "meanwhilesession.h"
+#include "meanwhileprotocol.h"
+
+#include <mw_channel.h>
+#include <mw_message.h>
+#include <mw_error.h>
+#include <mw_service.h>
+#include <mw_session.h>
+#include <mw_srvc_aware.h>
+#include <mw_srvc_conf.h>
+#include <mw_srvc_im.h>
+#include <mw_srvc_store.h>
+#include <mw_cipher.h>
+#include <mw_st_list.h>
+
+#define set_session_handler(a,b) sessionHandler.a = _handleSession ## b
+#define set_aware_handler(a,b) awareHandler.a = _handleAware ## b
+#define set_aware_list_handler(a,b) \
+ awareListHandler.a = _handleAwareList ## b
+#define set_im_handler(a,b) imHandler.a = _handleIm ## b
+
+#define get_protocol() (static_cast<MeanwhileProtocol *>(account->protocol()))
+
+static struct MeanwhileClientID ids[] = {
+ { mwLogin_LIB, "Lotus Binary Library" },
+ { mwLogin_JAVA_WEB, "Lotus Java Applet", },
+ { mwLogin_BINARY, "Lotus Binary App", },
+ { mwLogin_JAVA_APP, "Lotus Java App", },
+ { mwLogin_LINKS, "Sametime Links", },
+
+ { mwLogin_NOTES_6_5, "Notes 6.5", },
+ { mwLogin_NOTES_6_5_3, "Notes 6.5.3", },
+ { mwLogin_NOTES_7_0_beta, "Notes 7.0 beta", },
+ { mwLogin_NOTES_7_0, "Notes 7.0", },
+ { mwLogin_ICT, "ICT", },
+ { mwLogin_ICT_1_7_8_2, "ICT 1.7.8.2", },
+ { mwLogin_ICT_SIP, "ICT SIP", },
+ { mwLogin_NOTESBUDDY_4_14, "NotesBuddy 4.14", },
+ { mwLogin_NOTESBUDDY_4_15, "NotesBuddy 4.15" },
+ { mwLogin_NOTESBUDDY_4_16, "NotesBuddy 4.16" },
+ { mwLogin_SANITY, "Sanity", },
+ { mwLogin_ST_PERL, "ST Perl", },
+ { mwLogin_PMR_ALERT, "PMR Alert", },
+ { mwLogin_TRILLIAN, "Trillian", },
+ { mwLogin_TRILLIAN_IBM, "Trillian (IBM)", },
+ { mwLogin_MEANWHILE, "Meanwhile Library", },
+ { 0, NULL },
+};
+
+MeanwhileSession::MeanwhileSession(MeanwhileAccount *account)
+{
+ HERE;
+ this->account = account;
+ session = 0L;
+ socket = 0L;
+ state = mwSession_STOPPED;
+
+ /* set up main session hander */
+ memset(&sessionHandler, 0, sizeof(sessionHandler));
+ set_session_handler(io_write, IOWrite);
+ set_session_handler(io_close, IOClose);
+ set_session_handler(on_stateChange, StateChange);
+ set_session_handler(on_setPrivacyInfo, SetPrivacyInfo);
+ set_session_handler(on_setUserStatus, SetUserStatus);
+ set_session_handler(on_admin, Admin);
+ set_session_handler(on_announce, Announce);
+ set_session_handler(clear, Clear);
+
+ session = mwSession_new(&sessionHandler);
+ mwSession_setClientData(session, this, 0L);
+
+ /* set up the aware service */
+ memset(&awareHandler, 0, sizeof(awareHandler));
+ set_aware_handler(on_attrib, Attrib);
+
+ awareService = mwServiceAware_new(session, &awareHandler);
+ mwSession_addService(session, (struct mwService *)awareService);
+
+ /* create an aware list */
+ memset(&awareListHandler, 0, sizeof(awareListHandler));
+ set_aware_list_handler(on_aware, Aware);
+ set_aware_list_handler(on_attrib, Attrib);
+ awareList = mwAwareList_new(awareService, &awareListHandler);
+ mwAwareList_setClientData(awareList, this, 0L);
+
+ /* set up an im service */
+ memset(&imHandler, 0, sizeof(imHandler));
+ set_im_handler(conversation_opened, ConvOpened);
+ set_im_handler(conversation_closed, ConvClosed);
+ set_im_handler(conversation_recv, ConvReceived);
+ imHandler.place_invite = 0L;
+ imHandler.clear = 0L;
+
+ imService = mwServiceIm_new(session, &imHandler);
+ mwService_setClientData((struct mwService *)imService, this, 0L);
+ mwSession_addService(session, (struct mwService *) imService);
+
+ /* add resolve service */
+ resolveService = mwServiceResolve_new(session);
+ mwService_setClientData((struct mwService *)resolveService, this, 0L);
+ mwSession_addService(session, (struct mwService *) resolveService);
+
+ /* storage service */
+ storageService = mwServiceStorage_new(session);
+ mwService_setClientData((struct mwService *)storageService, this, 0L);
+ mwSession_addService(session, (struct mwService *) storageService);
+
+#if 0
+ /* conference service setup - just declines invites for now. */
+ memset(&conf_handler, 0, sizeof(conf_handler));
+ conf_handler.on_invited = _conference_invite;
+
+ srvc_conf = mwServiceConference_new(session, &conf_handler);
+ mwService_setClientData((struct mwService *)srvc_conf, this, 0L);
+ mwSession_addService(session, (struct mwService *) srvc_conf);
+#endif
+
+ /* add a necessary cipher */
+ mwSession_addCipher(session, mwCipher_new_RC2_40(session));
+ mwSession_addCipher(session, mwCipher_new_RC2_128(session));
+}
+
+MeanwhileSession::~MeanwhileSession()
+{
+ HERE;
+ if (isConnected() || isConnecting())
+ disconnect();
+
+ mwSession_removeService(session, mwService_STORAGE);
+ mwSession_removeService(session, mwService_RESOLVE);
+ mwSession_removeService(session, mwService_IM);
+ mwSession_removeService(session, mwService_AWARE);
+
+ mwAwareList_free(awareList);
+ mwService_free(MW_SERVICE(storageService));
+ mwService_free(MW_SERVICE(resolveService));
+ mwService_free(MW_SERVICE(imService));
+ mwService_free(MW_SERVICE(awareService));
+ mwCipher_free(mwSession_getCipher(session, mwCipher_RC2_40));
+ mwCipher_free(mwSession_getCipher(session, mwCipher_RC2_128));
+
+ mwSession_free(session);
+
+ if (socket)
+ delete socket;
+}
+
+void MeanwhileSession::getDefaultClientIDParams(int *clientID,
+ int *verMajor, int *verMinor)
+{
+ *clientID = mwLogin_MEANWHILE;
+ *verMajor = MW_PROTOCOL_VERSION_MAJOR;
+ *verMinor = MW_PROTOCOL_VERSION_MINOR;
+}
+
+/* external interface called by meanwhileaccount */
+void MeanwhileSession::connect(QString password)
+{
+ int port, clientID, versionMajor, versionMinor;
+ bool useCustomID;
+ QString host;
+
+ HERE;
+
+ host = account->getServerName();
+ port = account->getServerPort();
+ useCustomID = account->getClientIDParams(&clientID,
+ &versionMajor, &versionMinor);
+
+ KExtendedSocket *sock = new KExtendedSocket(host, port,
+ KExtendedSocket::bufferedSocket);
+
+ if (sock->connect()) {
+ KMessageBox::queuedMessageBox(0, KMessageBox::Error,
+ i18n( "Could not connect to server"), i18n("Meanwhile Plugin"),
+ KMessageBox::Notify);
+ delete sock;
+ return;
+ }
+ socket = sock;
+ /* we want to receive signals when there is data to read */
+ sock->enableRead(true);
+ QObject::connect(sock, SIGNAL(readyRead()), this,
+ SLOT(slotSocketDataAvailable()));
+ QObject::connect(sock, SIGNAL(closed(int)), this,
+ SLOT(slotSocketClosed(int)));
+
+ /* set login details */
+ mwSession_setProperty(session, mwSession_AUTH_USER_ID,
+ g_strdup(account->meanwhileId().ascii()), g_free);
+ mwSession_setProperty(session, mwSession_AUTH_PASSWORD,
+ g_strdup(password.ascii()), g_free);
+
+ /* set client type parameters */
+ if (useCustomID) {
+ mwSession_setProperty(session, mwSession_CLIENT_TYPE_ID,
+ GUINT_TO_POINTER(clientID), NULL);
+ mwSession_setProperty(session, mwSession_CLIENT_VER_MAJOR,
+ GUINT_TO_POINTER(versionMajor), NULL);
+ mwSession_setProperty(session, mwSession_CLIENT_VER_MINOR,
+ GUINT_TO_POINTER(versionMinor), NULL);
+ }
+
+ mwDebug() << "ids: "
+ << mwSession_getProperty(session, mwSession_CLIENT_TYPE_ID) << " v"
+ << mwSession_getProperty(session, mwSession_CLIENT_VER_MAJOR) << "."
+ << mwSession_getProperty(session, mwSession_CLIENT_VER_MINOR) <<
+ endl;
+
+ /* go!! */
+ mwSession_start(session);
+}
+
+void MeanwhileSession::disconnect()
+{
+ HERE;
+ if (state == mwSession_STOPPED || state == mwSession_STOPPING)
+ return;
+
+ mwSession_stop(session, ERR_SUCCESS);
+}
+
+bool MeanwhileSession::isConnected()
+{
+ return mwSession_isStarted(session);
+}
+
+bool MeanwhileSession::isConnecting()
+{
+ return mwSession_isStarting(session);
+}
+
+static void free_id_block(void *data, void *p)
+{
+ if (p != 0L || data == 0L)
+ return;
+ struct mwAwareIdBlock *id = (struct mwAwareIdBlock *)data;
+ free(id->user);
+ free(id);
+}
+
+void MeanwhileSession::addContacts(const QDict<Kopete::Contact>& contacts)
+{
+ HERE;
+ QDictIterator<Kopete::Contact> it(contacts);
+ GList *buddies = 0L;
+
+ /** Convert our QDict of kopete contact to a GList of meanwhile buddies */
+ for( ; it.current(); ++it) {
+ MeanwhileContact *contact =
+ static_cast<MeanwhileContact *>(it.current());
+ struct mwAwareIdBlock *id = (struct mwAwareIdBlock *)
+ malloc(sizeof(*id));
+ if (id == 0L)
+ continue;
+ id->user = strdup(contact->meanwhileId().ascii());
+ id->community = 0L;
+ id->type = mwAware_USER;
+ buddies = g_list_append(buddies, id);
+ }
+
+ mwAwareList_addAware(awareList, buddies);
+
+ g_list_foreach(buddies, free_id_block, 0L);
+ g_list_free(buddies);
+}
+
+/* private functions used only by the meanwhile session object */
+void MeanwhileSession::addContact(const Kopete::Contact *contact)
+{
+ HERE;
+ struct mwAwareIdBlock id = { mwAware_USER,
+ strdup(static_cast<const MeanwhileContact *>(contact)
+ ->meanwhileId().ascii()),
+ 0L };
+
+ GList *buddies = g_list_prepend(0L, &id);
+ mwAwareList_addAware(awareList, buddies);
+ g_list_free(buddies);
+ free(id.user);
+}
+
+int MeanwhileSession::sendMessage(Kopete::Message &message)
+{
+ HERE;
+ MeanwhileContact *contact =
+ static_cast<MeanwhileContact *>(message.to().first());
+ if (!contact) {
+ mwDebug() << "No target for message!" <<endl;
+ return 0;
+ }
+
+ struct mwIdBlock target = { strdup(contact->meanwhileId().ascii()), 0L };
+ struct mwConversation *conv;
+
+ conv = mwServiceIm_getConversation(imService, &target);
+ free(target.user);
+ if (conv == 0L) {
+ mwDebug() << "No target for conversation with '"
+ << contact->meanwhileId() << "'" << endl;
+ return 0;
+ }
+
+ struct ConversationData *convdata = (struct ConversationData *)
+ mwConversation_getClientData(conv);
+
+ if (convdata == 0L) {
+ convdata = createConversationData(conv, contact, true);
+ if (convdata == 0L) {
+ mwDebug() << "No memory for conversation data!" << endl;
+ return 0;
+ }
+ }
+
+ /* if there's other messages in the queue, or the conversation isn't open,
+ * then append to the queue instead of sending right away */
+ if ((convdata->queue && !convdata->queue->isEmpty()) ||
+ !mwConversation_isOpen(conv)) {
+ convdata->queue->append(message);
+ mwConversation_open(conv);
+
+ } else if (!mwConversation_send(conv, mwImSend_PLAIN,
+ message.plainBody().ascii())) {
+ convdata->chat->appendMessage(message);
+ convdata->chat->messageSucceeded();
+ }
+ return 1;
+}
+
+void MeanwhileSession::sendTyping(MeanwhileContact *contact, bool isTyping)
+{
+ HERE;
+ struct mwIdBlock target = { strdup(contact->meanwhileId().ascii()), 0L };
+ struct mwConversation *conv;
+
+ conv = mwServiceIm_getConversation(imService, &target);
+ free(target.user);
+ if (conv == 0L)
+ return;
+
+ if (mwConversation_isOpen(conv))
+ mwConversation_send(conv, mwImSend_TYPING, (void *)isTyping);
+}
+
+void MeanwhileSession::setStatus(Kopete::OnlineStatus status,
+ const QString msg)
+{
+ HERE;
+ mwDebug() << "setStatus: " << status.description() << "("
+ << status.internalStatus() << ")" << endl;
+ if (status.internalStatus() == 0)
+ return;
+
+ struct mwUserStatus stat;
+ mwUserStatus_clone(&stat, mwSession_getUserStatus(session));
+
+ free(stat.desc);
+
+ stat.status = (mwStatusType)status.internalStatus();
+ if (msg.isNull() || msg.isEmpty())
+ stat.desc = strdup(status.description().ascii());
+ else
+ stat.desc = strdup(msg.ascii());
+
+ mwSession_setUserStatus(session, &stat);
+ /* will free stat.desc */
+ mwUserStatus_clear(&stat);
+}
+
+void MeanwhileSession::syncContactsToServer()
+{
+ HERE;
+ struct mwSametimeList *list = mwSametimeList_new();
+
+ /* set up a fallback group for top-level contacts */
+ struct mwSametimeGroup *topstgroup = mwSametimeGroup_new(list,
+ mwSametimeGroup_DYNAMIC, "People");
+ mwSametimeGroup_setOpen(topstgroup, true);
+
+ QDictIterator<Kopete::Contact> it(account->contacts());
+ for( ; it.current(); ++it ) {
+ MeanwhileContact *contact =
+ static_cast<MeanwhileContact *>(it.current());
+
+ /* Find the group that the metacontact is in */
+ Kopete::MetaContact *mc = contact->metaContact();
+ /* myself doesn't have a metacontact */
+ if (mc == 0L)
+ continue;
+
+ Kopete::Group *contactgroup = mc->groups().getFirst();
+ if (contactgroup == 0L)
+ continue;
+
+ if (contactgroup->type() == Kopete::Group::Temporary)
+ continue;
+
+ struct mwSametimeGroup *stgroup;
+ if (contactgroup->type() == Kopete::Group::TopLevel) {
+ stgroup = topstgroup;
+ } else {
+ /* find (or create) a matching sametime list group */
+ stgroup = mwSametimeList_findGroup(list,
+ contactgroup->displayName().ascii());
+ if (stgroup == 0L) {
+ stgroup = mwSametimeGroup_new(list, mwSametimeGroup_DYNAMIC,
+ contactgroup->displayName().ascii());
+ }
+ mwSametimeGroup_setOpen(stgroup, contactgroup->isExpanded());
+ mwSametimeGroup_setAlias(stgroup,
+ contactgroup->pluginData(account->protocol(), "alias")
+ .ascii());
+ }
+
+ /* now add the user (by IDBlock) */
+ struct mwIdBlock id =
+ { (gchar*)contact->meanwhileId().ascii(), 0L };
+ struct mwSametimeUser *stuser = mwSametimeUser_new(stgroup,
+ mwSametimeUser_NORMAL, &id);
+
+ mwSametimeUser_setAlias(stuser, contact->nickName().ascii());
+ }
+
+ /* store! */
+ struct mwPutBuffer *buf = mwPutBuffer_new();
+ struct mwStorageUnit *unit = mwStorageUnit_new(mwStore_AWARE_LIST);
+ struct mwOpaque *opaque = mwStorageUnit_asOpaque(unit);
+
+ mwSametimeList_put(buf, list);
+ mwPutBuffer_finalize(opaque, buf);
+
+ mwServiceStorage_save(storageService, unit, NULL, NULL, NULL);
+
+ mwSametimeList_free(list);
+}
+
+void MeanwhileSession::syncContactsFromServer()
+{
+ struct mwStorageUnit *unit = mwStorageUnit_new(mwStore_AWARE_LIST);
+ mwServiceStorage_load(storageService, unit, &_handleStorageLoad, 0L, 0L);
+}
+
+#define MEANWHILE_SESSION_BUFSIZ 4096
+
+void MeanwhileSession::slotSocketDataAvailable()
+{
+ HERE;
+ guchar *buf;
+ Q_LONG bytesRead;
+
+ if (socket == 0L)
+ return;
+
+ if (!(buf = (guchar *)malloc(MEANWHILE_SESSION_BUFSIZ))) {
+ mwDebug() << "buffer malloc failed" << endl;
+ return;
+ }
+
+ while (socket && socket->bytesAvailable() > 0) {
+ bytesRead = socket->readBlock((char *)buf, MEANWHILE_SESSION_BUFSIZ);
+ if (bytesRead < 0)
+ break;
+ mwSession_recv(session, buf, (unsigned int)bytesRead);
+ }
+ free(buf);
+}
+
+void MeanwhileSession::slotSocketClosed(int reason)
+{
+ HERE;
+
+ if (reason & KExtendedSocket::involuntary)
+ emit serverNotification(
+ QString("Lost connection with Meanwhile server"));
+
+ if (socket) {
+ delete socket;
+ socket = 0L;
+ }
+
+ mwSession_stop(session, 0x00);
+}
+
+
+Kopete::OnlineStatus MeanwhileSession::convertStatus(int mstatus)
+{
+ MeanwhileProtocol *protocol =
+ static_cast<MeanwhileProtocol *>(account->protocol());
+
+ switch (mstatus) {
+ case mwStatus_ACTIVE:
+ return protocol->statusOnline;
+ break;
+ case mwStatus_IDLE:
+ return protocol->statusIdle;
+ break;
+ case mwStatus_AWAY:
+ return protocol->statusAway;
+ break;
+ case mwStatus_BUSY:
+ return protocol->statusBusy;
+ break;
+ case 0:
+ return protocol->statusOffline;
+ break;
+ default:
+ mwDebug() << "unknown status lookup: " << mstatus << endl;
+ }
+ return protocol->statusOffline;
+}
+
+void MeanwhileSession::resolveContactNickname(MeanwhileContact *contact)
+{
+ /* @todo: FIXME: leak! */
+ char *id = strdup(contact->meanwhileId().ascii());
+ GList *query = g_list_prepend(NULL, id);
+ mwServiceResolve_resolve(resolveService, query, mwResolveFlag_USERS,
+ _handleResolveLookupResults, contact, NULL);
+}
+
+QString MeanwhileSession::getNickName(struct mwLoginInfo *logininfo)
+{
+ if (logininfo == 0L || logininfo->user_name == 0L)
+ return QString::null;
+ return getNickName(logininfo->user_name);
+}
+
+QString MeanwhileSession::getNickName(QString name)
+{
+
+ int index = name.find(" - ");
+ if (index != -1)
+ name = name.remove(0, index + 3);
+ index = name.find('/');
+ if (index != -1)
+ name = name.left(index);
+
+ return name;
+}
+
+MeanwhileContact *MeanwhileSession::conversationContact(
+ struct mwConversation *conv)
+{
+ struct mwIdBlock *target = mwConversation_getTarget(conv);
+ if (target == 0L || target->user == 0L) {
+ return 0L;
+ }
+ QString user(target->user);
+
+ MeanwhileContact *contact =
+ static_cast<MeanwhileContact *>(account->contacts()[user]);
+
+ struct mwLoginInfo *logininfo = mwConversation_getTargetInfo(conv);
+ QString name = getNickName(logininfo);
+
+ if (!contact) {
+ account->addContact(user, name, 0L, Kopete::Account::Temporary);
+ contact = static_cast<MeanwhileContact *>(account->contacts()[user]);
+ } else
+ contact->setNickName(name);
+
+ return contact;
+}
+
+/* priave session handling functions, called by libmeanwhile callbacks */
+void MeanwhileSession::handleSessionStateChange(
+ enum mwSessionState state, gpointer data)
+{
+ HERE;
+ this->state = state;
+
+ switch (state) {
+ case mwSession_STARTING:
+ case mwSession_HANDSHAKE:
+ case mwSession_HANDSHAKE_ACK:
+ case mwSession_LOGIN:
+ case mwSession_LOGIN_REDIR:
+ case mwSession_LOGIN_CONT:
+ case mwSession_LOGIN_ACK:
+ break;
+
+ case mwSession_STARTED:
+ {
+ struct mwUserStatus stat = { mwStatus_ACTIVE, 0, 0L };
+ mwSession_setUserStatus(session, &stat);
+ struct mwLoginInfo *logininfo = mwSession_getLoginInfo(session);
+ if (logininfo) {
+ account->myself()->setNickName(getNickName(logininfo));
+ }
+ syncContactsFromServer();
+ }
+ break;
+
+ case mwSession_STOPPING:
+ {
+ unsigned int info = GPOINTER_TO_UINT(data);
+ if (info & ERR_FAILURE) {
+ if (info == INCORRECT_LOGIN)
+ account->password().setWrong();
+ char *reason = mwError(info);
+ emit serverNotification(QString(reason));
+ free(reason);
+ }
+ }
+
+ emit sessionStateChange(
+ static_cast<MeanwhileProtocol *>(account->protocol())
+ ->statusOffline);
+ break;
+
+ case mwSession_STOPPED:
+ break;
+
+ case mwSession_UNKNOWN:
+ default:
+ mwDebug() << "Unhandled state change " << state << endl;
+ }
+}
+
+int MeanwhileSession::handleSessionIOWrite(const guchar *buffer,
+ gsize count)
+{
+ HERE;
+
+ if (socket == 0L)
+ return 1;
+
+ int remaining, retval = 0;
+ for (remaining = count; remaining > 0; remaining -= retval) {
+ retval = socket->writeBlock((char *)buffer, count);
+ if (retval <= 0)
+ return 1;
+ }
+ socket->flush();
+ return 0;
+}
+
+void MeanwhileSession::handleSessionAdmin(const char *text)
+{
+ HERE;
+ emit serverNotification(QString(text));
+}
+
+void MeanwhileSession::handleSessionAnnounce(struct mwLoginInfo *from,
+ gboolean /* may_reply */, const char *text)
+{
+ HERE;
+ QString message;
+ message.sprintf("Announcement from %s:\n%s", from->user_id, text);
+ emit serverNotification(message);
+}
+
+void MeanwhileSession::handleSessionSetUserStatus()
+{
+ struct mwUserStatus *userstatus = mwSession_getUserStatus(session);
+ emit sessionStateChange(convertStatus((unsigned int)userstatus->status));
+}
+
+void MeanwhileSession::handleSessionSetPrivacyInfo()
+{
+}
+
+void MeanwhileSession::handleSessionIOClose()
+{
+ HERE;
+
+ if (socket == 0L)
+ return;
+
+ QObject::disconnect(socket, SIGNAL(closed(int)),
+ this, SLOT(slotSocketClosed(int)));
+ socket->flush();
+ socket->closeNow();
+
+ delete socket;
+ socket = 0L;
+}
+
+void MeanwhileSession::handleSessionClear()
+{
+}
+
+void MeanwhileSession::handleAwareAttrib(struct mwAwareAttribute * /* attrib */)
+{
+ HERE;
+}
+
+void MeanwhileSession::handleAwareListAware(struct mwAwareSnapshot *snapshot)
+{
+ HERE;
+ MeanwhileContact *contact = static_cast<MeanwhileContact *>
+ (account->contacts()[snapshot->id.user]);
+
+ if (contact == 0L)
+ return;
+
+ /* use the setUserStatus callback for status updates for myself. */
+ if (contact == account->myself())
+ return;
+
+ contact->setProperty(get_protocol()->statusMessage, snapshot->status.desc);
+ contact->setProperty(get_protocol()->awayMessage, snapshot->status.desc);
+
+ Kopete::OnlineStatus onlinestatus;
+ if (snapshot->online) {
+ onlinestatus = convertStatus(snapshot->status.status);
+ resolveContactNickname(contact);
+ } else {
+ onlinestatus = convertStatus(0);
+ }
+
+ contact->setOnlineStatus(onlinestatus);
+
+#if 0
+ /* Commented out in previous kopete/meanwhile plugin for some reason,
+ * but has still been ported to the new API.
+ */
+ time_t idletime = 0;
+ if (snapshot->status.status == mwStatus_IDLE) {
+ idletime = (snapshot->status.time == 0xdeadbeef) ?
+ 0 : snapshot->status.time;
+ if (idletime != 0) {
+ contact->setStatusDescription(statusDesc + "[" +
+ QString::number(idletime/60)+" mins]");
+ }
+ } else
+ contact->setStatusDescription(snapshot->status.desc);
+#endif
+}
+
+void MeanwhileSession::handleAwareListAttrib(struct mwAwareIdBlock * /* id */,
+ struct mwAwareAttribute * /* attrib */)
+{
+ HERE;
+}
+
+struct MeanwhileSession::ConversationData
+ *MeanwhileSession::createConversationData(
+ struct mwConversation *conv, MeanwhileContact *contact,
+ bool createQueue)
+{
+ struct ConversationData *cd = new ConversationData();
+
+ if (cd == 0L)
+ return 0L;
+
+ cd->contact = contact;
+ cd->chat = contact->manager(Kopete::Contact::CanCreate);
+ cd->chat->ref();
+ if (createQueue)
+ cd->queue = new QValueList<Kopete::Message>();
+
+ mwConversation_setClientData(conv, cd, 0L);
+
+ return cd;
+}
+
+void MeanwhileSession::handleImConvOpened(struct mwConversation *conv)
+{
+ HERE;
+
+ struct ConversationData *convdata =
+ (struct ConversationData *)mwConversation_getClientData(conv);
+
+ if (convdata == 0L) {
+ /* a new conversation */
+ convdata = createConversationData(conv, conversationContact(conv));
+
+ if (convdata == 0L) {
+ mwDebug() << "No memory for conversation data!" << endl;
+ return;
+ }
+
+ } else if (convdata->queue && !convdata->queue->isEmpty()) {
+ /* send any messages that were waiting for the conversation to open */
+ QValueList<Kopete::Message>::iterator it;
+ for (it = convdata->queue->begin(); it != convdata->queue->end();
+ ++it) {
+ mwConversation_send(conv, mwImSend_PLAIN,
+ (*it).plainBody().ascii());
+ convdata->chat->appendMessage(*it);
+ convdata->chat->messageSucceeded();
+ }
+ convdata->queue->clear();
+ delete convdata->queue;
+ convdata->queue = 0L;
+ }
+ resolveContactNickname(convdata->contact);
+}
+
+void MeanwhileSession::handleImConvClosed(struct mwConversation *conv,
+ guint32)
+{
+ HERE;
+
+ ConversationData *convdata =
+ (ConversationData *)mwConversation_getClientData(conv);
+
+ if (!convdata)
+ return;
+
+ mwConversation_setClientData(conv, 0L, 0L);
+
+ convdata->chat->removeContact(convdata->contact);
+ convdata->chat->deref();
+ convdata->chat = 0L;
+ if (convdata->queue != 0L) {
+ convdata->queue->clear();
+ delete convdata->queue;
+ convdata->queue = 0L;
+ }
+ free(convdata);
+}
+
+void MeanwhileSession::handleImConvReceived(struct mwConversation *conv,
+ enum mwImSendType type, gconstpointer msg)
+{
+ HERE;
+ ConversationData *convdata =
+ (ConversationData *)mwConversation_getClientData(conv);
+
+ if (!convdata)
+ return;
+
+ switch (type) {
+ case mwImSend_PLAIN:
+ {
+ Kopete::Message message(convdata->contact, account->myself(),
+ QString((char *)msg), Kopete::Message::Inbound);
+ convdata->chat->appendMessage(message);
+ }
+ break;
+ case mwImSend_TYPING:
+ convdata->chat->receivedTypingMsg(convdata->contact);
+ break;
+ default:
+ mwDebug() << "Unable to handle message type: " << type << endl;
+ }
+}
+
+void MeanwhileSession::handleResolveLookupResults(
+ struct mwServiceResolve * /* srvc */, guint32 /* id */,
+ guint32 /* code */, GList *results, gpointer data)
+{
+ struct mwResolveResult *result;
+ struct mwResolveMatch *match;
+
+ if (results == 0L)
+ return;
+ if ((result = (struct mwResolveResult *)results->data) == 0L)
+ return;
+
+ if (result->matches == 0L)
+ return;
+ if ((match = (struct mwResolveMatch *)result->matches->data) == 0L)
+ return;
+
+ mwDebug() << "resolve lookup returned '" << match->name << "'" << endl;
+
+ MeanwhileContact *contact = (MeanwhileContact *)data;
+ if (contact == 0L)
+ return;
+
+ contact->setNickName(getNickName(match->name));
+}
+
+void MeanwhileSession::handleStorageLoad(struct mwServiceStorage * /* srvc */,
+ guint32 result, struct mwStorageUnit *item, gpointer /* data */)
+{
+ HERE;
+ if (result != ERR_SUCCESS) {
+ mwDebug() << "contact list load returned " << result << endl;
+ return;
+ }
+
+ struct mwGetBuffer *buf = mwGetBuffer_wrap(mwStorageUnit_asOpaque(item));
+ struct mwSametimeList *list = mwSametimeList_new();
+ mwSametimeList_get(buf, list);
+
+ GList *gl, *glf, *cl, *clf;
+
+ Kopete::ContactList *contactlist = Kopete::ContactList::self();
+
+ for (glf = gl = mwSametimeList_getGroups(list); gl; gl = gl->next) {
+ struct mwSametimeGroup *stgroup = (struct mwSametimeGroup *)gl->data;
+
+ Kopete::Group *group =
+ contactlist->findGroup(mwSametimeGroup_getName(stgroup));
+ group->setPluginData(account->protocol(), "alias",
+ mwSametimeGroup_getAlias(stgroup));
+
+ for (clf = cl = mwSametimeGroup_getUsers(stgroup); cl; cl = cl->next) {
+ struct mwSametimeUser *stuser = (struct mwSametimeUser *)cl->data;
+
+ MeanwhileContact *contact = static_cast<MeanwhileContact *>
+ (account->contacts()[mwSametimeUser_getUser(stuser)]);
+
+ if (contact != 0L)
+ continue;
+
+ account->addContact(mwSametimeUser_getUser(stuser),
+ mwSametimeUser_getAlias(stuser), group,
+ Kopete::Account::ChangeKABC);
+ }
+ g_list_free(clf);
+ }
+ g_list_free(glf);
+
+ mwSametimeList_free(list);
+}
+
+const struct MeanwhileClientID *MeanwhileSession::getClientIDs()
+{
+ return ids;
+}
+
+#if 0
+MEANWHILE_HOOK_CONFERENCE(conference_invite,
+ (struct mwConference *conf, struct mwLoginInfo *inviter,
+ const char *invite),
+ (conf, inviter, invite))
+{
+ HERE;
+ QString message;
+
+ message.sprintf("%s has invited you to a conference called \"%s\"\n"
+ "However, this version of the meanwhile plugin does "
+ "not support conferences, so the invitiation has been declined.",
+ inviter->user_id, invite);
+
+ mwConference_reject(conf, ERR_SUCCESS,
+ "Sorry, my client doesn't support conferences!");
+ KMessageBox::queuedMessageBox(0, KMessageBox::Sorry , message,
+ i18n("Meanwhile Plugin: Conference invitation"),
+ KMessageBox::Notify);
+}
+#endif
+#include "meanwhilesession.moc"