You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetwork/kopete/protocols/meanwhile/meanwhilesession.cpp

966 lines
29 KiB

/*
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(TQString password)
{
int port, clientID, versionMajor, versionMinor;
bool useCustomID;
TQString 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);
TQObject::connect(sock, TQT_SIGNAL(readyRead()), this,
TQT_SLOT(slotSocketDataAvailable()));
TQObject::connect(sock, TQT_SIGNAL(closed(int)), this,
TQT_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 TQDict<Kopete::Contact>& contacts)
{
HERE;
TQDictIterator<Kopete::Contact> it(contacts);
GList *buddies = 0L;
/** Convert our TQDict 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 TQString 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);
TQDictIterator<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 {
/* tqfind (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;
TQ_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(
TQString("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);
}
TQString MeanwhileSession::getNickName(struct mwLoginInfo *logininfo)
{
if (logininfo == 0L || logininfo->user_name == 0L)
return TQString();
return getNickName(logininfo->user_name);
}
TQString MeanwhileSession::getNickName(TQString name)
{
int index = name.tqfind(" - ");
if (index != -1)
name = name.remove(0, index + 3);
index = name.tqfind('/');
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;
}
TQString user(target->user);
MeanwhileContact *contact =
static_cast<MeanwhileContact *>(account->contacts()[user]);
struct mwLoginInfo *logininfo = mwConversation_getTargetInfo(conv);
TQString 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(TQString(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(TQString(text));
}
void MeanwhileSession::handleSessionAnnounce(struct mwLoginInfo *from,
gboolean /* may_reply */, const char *text)
{
HERE;
TQString 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;
TQObject::disconnect(socket, TQT_SIGNAL(closed(int)),
this, TQT_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 + "[" +
TQString::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 TQValueList<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 */
TQValueList<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(),
TQString((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;
TQString 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"