2010-05-27 20:04:31 -05:00
|
|
|
/*
|
|
|
|
* Copyright 2010, Pier Luigi Fiorini. All rights reserved.
|
2021-06-18 01:30:59 -05:00
|
|
|
* Copyright 2021, Jaidyn Levesque. All rights reserved.
|
2010-05-27 20:04:31 -05:00
|
|
|
* Distributed under the terms of the GPL v2 License.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
|
2021-06-11 20:33:28 -05:00
|
|
|
* Jaidyn Levesque, jadedctrl@teknik.io
|
2010-05-27 20:04:31 -05:00
|
|
|
*/
|
|
|
|
|
2021-07-18 20:03:42 -05:00
|
|
|
#include <iostream>
|
|
|
|
|
2021-07-18 22:25:38 -05:00
|
|
|
#include <Catalog.h>
|
2010-05-29 23:26:36 -05:00
|
|
|
#include <Directory.h>
|
|
|
|
#include <Entry.h>
|
|
|
|
#include <File.h>
|
|
|
|
#include <FindDirectory.h>
|
|
|
|
#include <List.h>
|
2021-06-02 16:58:29 -05:00
|
|
|
#include <StringList.h>
|
2010-05-27 20:04:31 -05:00
|
|
|
|
2010-05-29 23:26:36 -05:00
|
|
|
#include <libsupport/SHA1.h>
|
|
|
|
|
2021-06-20 12:44:20 -05:00
|
|
|
#include <ChatProtocolMessages.h>
|
2021-06-30 14:27:58 -05:00
|
|
|
#include <Flags.h>
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
#include <Role.h>
|
|
|
|
|
2021-05-19 16:12:19 -05:00
|
|
|
#include <gloox/chatstatefilter.h>
|
|
|
|
#include <gloox/messageeventfilter.h>
|
2021-06-01 21:53:50 -05:00
|
|
|
#include <gloox/mucroom.h>
|
2010-07-10 14:27:32 -05:00
|
|
|
|
2010-05-28 15:41:58 -05:00
|
|
|
#include "JabberHandler.h"
|
2010-05-27 20:04:31 -05:00
|
|
|
|
|
|
|
|
2021-07-18 22:25:38 -05:00
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
#define B_TRANSLATION_CONTEXT "JabberHandler"
|
|
|
|
|
|
|
|
|
2010-05-27 20:04:31 -05:00
|
|
|
static status_t
|
|
|
|
connect_thread(void* data)
|
|
|
|
{
|
2011-04-08 21:35:20 -05:00
|
|
|
|
2010-05-30 15:50:04 -05:00
|
|
|
JabberHandler* handler = (JabberHandler*)data;
|
|
|
|
if (!handler)
|
|
|
|
return B_BAD_VALUE;
|
|
|
|
|
|
|
|
gloox::Client* client = handler->Client();
|
2010-05-27 20:04:31 -05:00
|
|
|
if (!client)
|
|
|
|
return B_BAD_VALUE;
|
|
|
|
|
2010-05-30 15:50:04 -05:00
|
|
|
gloox::ConnectionError e;
|
2011-04-08 21:35:20 -05:00
|
|
|
while ((e = client->recv(10000000)) == gloox::ConnNoError);
|
2010-05-30 15:50:04 -05:00
|
|
|
|
|
|
|
if (e != gloox::ConnUserDisconnected)
|
2021-06-01 21:53:50 -05:00
|
|
|
handler->HandleConnectionError(e);
|
2010-05-27 20:04:31 -05:00
|
|
|
|
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::JabberHandler()
|
|
|
|
:
|
|
|
|
fClient(NULL),
|
2010-07-10 14:27:32 -05:00
|
|
|
fVCardManager(NULL),
|
|
|
|
fSession(NULL)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
2010-05-29 23:26:36 -05:00
|
|
|
fAvatars = new BList();
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::~JabberHandler()
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
Shutdown();
|
2010-05-29 23:26:36 -05:00
|
|
|
|
|
|
|
BString* item = NULL;
|
|
|
|
for (int32 i = 0; (item = (BString*)fAvatars->ItemAt(i)); i++)
|
|
|
|
delete item;
|
|
|
|
delete fAvatars;
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
2021-06-20 12:44:20 -05:00
|
|
|
JabberHandler::Init(ChatProtocolMessengerInterface* messenger)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
fServerMessenger = messenger;
|
|
|
|
|
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::Process(BMessage* msg)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
if (msg->what != IM_MESSAGE)
|
|
|
|
return B_ERROR;
|
|
|
|
|
|
|
|
int32 im_what = 0;
|
|
|
|
|
|
|
|
msg->FindInt32("im_what", &im_what);
|
|
|
|
|
|
|
|
switch (im_what) {
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_SET_OWN_STATUS:
|
|
|
|
{
|
2010-05-27 20:04:31 -05:00
|
|
|
int32 status = msg->FindInt32("status");
|
|
|
|
BString status_msg = msg->FindString("message");
|
|
|
|
|
|
|
|
switch (status) {
|
2021-06-20 12:44:20 -05:00
|
|
|
case STATUS_ONLINE:
|
2010-05-27 20:04:31 -05:00
|
|
|
// Log in if we still need to
|
2010-05-28 15:41:58 -05:00
|
|
|
resume_thread(fRecvThread);
|
|
|
|
break;
|
2021-06-20 12:44:20 -05:00
|
|
|
case STATUS_OFFLINE:
|
2010-05-28 15:41:58 -05:00
|
|
|
kill_thread(fRecvThread);
|
2010-05-27 20:04:31 -05:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_SEND_MESSAGE:
|
|
|
|
{
|
2021-05-24 01:47:21 -05:00
|
|
|
const char* id = msg->FindString("chat_id");
|
2010-05-27 20:04:31 -05:00
|
|
|
const char* subject = msg->FindString("subject");
|
|
|
|
const char* body = msg->FindString("body");
|
2021-06-03 14:25:51 -05:00
|
|
|
gloox::MUCRoom* room = fRooms.ValueFor(id);
|
2010-05-27 20:04:31 -05:00
|
|
|
|
|
|
|
if (!id || !body)
|
|
|
|
return B_ERROR;
|
|
|
|
|
2010-05-28 15:41:58 -05:00
|
|
|
// Send JabberHandler message
|
2010-05-27 20:04:31 -05:00
|
|
|
gloox::Message jm(gloox::Message::Chat, gloox::JID(id),
|
|
|
|
body, (subject ? subject : gloox::EmptyString));
|
2021-06-03 14:25:51 -05:00
|
|
|
if (room != NULL) {
|
|
|
|
room->send(body);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fClient->send(jm);
|
2010-05-27 20:04:31 -05:00
|
|
|
|
2021-06-03 14:25:51 -05:00
|
|
|
// If non-MUC, tell Caya we actually sent the message
|
|
|
|
// (An MUC should echo the message back to us later, see
|
|
|
|
// handleMUCMessage)
|
2010-05-28 15:41:58 -05:00
|
|
|
_MessageSent(id, subject, body);
|
2010-05-27 20:04:31 -05:00
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_CREATE_CHAT:
|
|
|
|
{
|
2021-06-13 02:34:11 -05:00
|
|
|
const char* user_id = msg->FindString("user_id");
|
2021-05-26 07:48:25 -05:00
|
|
|
|
|
|
|
// TODO: Contact validation, make sure permssion is granted
|
|
|
|
|
2021-06-13 02:34:11 -05:00
|
|
|
if (!user_id)
|
2021-05-26 07:48:25 -05:00
|
|
|
return B_ERROR;
|
|
|
|
|
2021-06-13 02:34:11 -05:00
|
|
|
_EnsureUserChat(user_id);
|
|
|
|
_ChatCreatedMsg(user_id);
|
2021-05-26 07:48:25 -05:00
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_CREATE_ROOM:
|
|
|
|
{
|
2021-06-18 01:30:59 -05:00
|
|
|
BString chat_id;
|
|
|
|
if (msg->FindString("chat_id", &chat_id) != B_OK)
|
|
|
|
break;
|
|
|
|
_JoinRoom(chat_id);
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_JOIN_ROOM:
|
|
|
|
{
|
2021-06-08 19:59:22 -05:00
|
|
|
BString chat_id;
|
|
|
|
if (msg->FindString("chat_id", &chat_id) == B_OK)
|
|
|
|
_JoinRoom(chat_id.String());
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_LEAVE_ROOM:
|
|
|
|
{
|
2021-06-04 16:34:25 -05:00
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
gloox::MUCRoom* room = fRooms.ValueFor(chat_id);
|
|
|
|
|
|
|
|
// MUCs are special, one-on-ones we can just drop
|
|
|
|
if (room != NULL)
|
|
|
|
room->leave();
|
|
|
|
|
|
|
|
// We've gotta let Caya know!
|
|
|
|
BMessage left(IM_MESSAGE);
|
|
|
|
left.AddInt32("im_what", IM_ROOM_LEFT);
|
|
|
|
left.AddString("chat_id", chat_id);
|
|
|
|
_SendMessage(&left);
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_ROOM_INVITE_ACCEPT:
|
|
|
|
{
|
2021-06-08 19:59:22 -05:00
|
|
|
BString chat_id;
|
|
|
|
if (msg->FindString("chat_id", &chat_id) != B_OK)
|
|
|
|
break;
|
|
|
|
|
|
|
|
BStringList splitAtPassword;
|
|
|
|
chat_id.Split("#", false, splitAtPassword);
|
|
|
|
chat_id = splitAtPassword.StringAt(0);
|
|
|
|
|
|
|
|
_JoinRoom(chat_id.String());
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_ROOM_SEND_INVITE:
|
|
|
|
{
|
2021-06-08 21:43:30 -05:00
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
gloox::MUCRoom* room = fRooms.ValueFor(chat_id);
|
|
|
|
BString user_id;
|
|
|
|
if (room == NULL || msg->FindString("user_id", &user_id) != B_OK)
|
|
|
|
break;
|
|
|
|
|
|
|
|
room->invite(gloox::JID(user_id.String()), "");
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_GET_ROOM_PARTICIPANTS:
|
|
|
|
{
|
2021-06-13 01:16:30 -05:00
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
gloox::MUCRoom* room = fRooms.ValueFor(chat_id);
|
|
|
|
|
|
|
|
if (room != NULL)
|
|
|
|
room->getRoomItems();
|
|
|
|
else if (fUserChats.HasString(chat_id) == true) {
|
|
|
|
BMessage users(IM_MESSAGE);
|
|
|
|
users.AddInt32("im_what", IM_ROOM_PARTICIPANTS);
|
|
|
|
users.AddString("user_id", chat_id);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_GET_ROOM_METADATA:
|
|
|
|
{
|
2021-06-13 01:16:30 -05:00
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
gloox::MUCRoom* room = fRooms.ValueFor(chat_id);
|
|
|
|
if (room != NULL)
|
|
|
|
room->getRoomInfo();
|
2021-06-13 02:34:11 -05:00
|
|
|
if (fUserChats.HasString(chat_id) == true)
|
2021-06-13 01:16:30 -05:00
|
|
|
{
|
|
|
|
BMessage metadata(IM_MESSAGE);
|
|
|
|
metadata.AddInt32("im_what", IM_ROOM_METADATA);
|
|
|
|
metadata.AddString("chat_id", chat_id);
|
2021-06-13 02:34:11 -05:00
|
|
|
metadata.AddInt32("room_default_flags", 0 | ROOM_LOG_LOCALLY | ROOM_POPULATE_LOGS);
|
|
|
|
metadata.AddInt32("room_disallowed_flags", 0 | ROOM_AUTOJOIN | ROOM_AUTOCREATE);
|
|
|
|
_SendMessage(&metadata);
|
2021-06-13 01:16:30 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_SET_ROOM_SUBJECT:
|
|
|
|
{
|
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
gloox::MUCRoom* room = fRooms.ValueFor(chat_id);
|
|
|
|
if (room != NULL)
|
|
|
|
room->setSubject(msg->GetString("subject", ""));
|
2021-06-06 16:31:25 -05:00
|
|
|
break;
|
2021-07-29 22:13:20 -05:00
|
|
|
}
|
|
|
|
case IM_GET_EXTENDED_CONTACT_INFO:
|
|
|
|
{
|
2021-06-19 22:03:02 -05:00
|
|
|
BString user_id;
|
|
|
|
if (msg->FindString("user_id", &user_id) == B_OK)
|
|
|
|
fVCardManager->fetchVCard(gloox::JID(user_id.String()), this);
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_CONTACT_LIST_ADD_CONTACT:
|
|
|
|
{
|
2021-06-19 18:25:58 -05:00
|
|
|
BString user_name = msg->FindString("user_name");
|
|
|
|
BString user_id;
|
|
|
|
if (msg->FindString("user_id", &user_id) != B_OK)
|
|
|
|
break;
|
|
|
|
fClient->rosterManager()->add(gloox::JID(user_id.String()),
|
|
|
|
user_name.String(), gloox::StringList());
|
|
|
|
fClient->rosterManager()->subscribe(gloox::JID(user_id.String()),
|
|
|
|
user_name.String());
|
|
|
|
fClient->rosterManager()->synchronize();
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_CONTACT_LIST_REMOVE_CONTACT:
|
|
|
|
{
|
2021-06-19 22:37:20 -05:00
|
|
|
BString user_id;
|
|
|
|
if (msg->FindString("user_id", &user_id) != B_OK)
|
|
|
|
break;
|
|
|
|
fClient->rosterManager()->remove(gloox::JID(user_id.String()));
|
|
|
|
fClient->rosterManager()->unsubscribe(gloox::JID(user_id.String()));
|
|
|
|
fClient->rosterManager()->synchronize();
|
|
|
|
|
|
|
|
BMessage rm(IM_MESSAGE);
|
|
|
|
rm.AddInt32("im_what", IM_CONTACT_LIST_CONTACT_REMOVED);
|
|
|
|
rm.AddString("user_id", user_id);
|
|
|
|
_SendMessage(&rm);
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_CONTACT_LIST_EDIT_CONTACT:
|
|
|
|
{
|
2021-06-19 22:03:02 -05:00
|
|
|
BString user_id;
|
|
|
|
BString user_name = msg->FindString("user_name");
|
|
|
|
if (msg->FindString("user_id", &user_id) != B_OK)
|
|
|
|
break;
|
|
|
|
|
|
|
|
gloox::JID jid(user_id.String());
|
|
|
|
gloox::RosterItem* item =
|
|
|
|
fClient->rosterManager()->getRosterItem(jid);
|
|
|
|
|
|
|
|
if (item != NULL && user_name.IsEmpty() == false) {
|
|
|
|
item->setName(user_name.String());
|
|
|
|
fClient->rosterManager()->synchronize();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-07-29 22:13:20 -05:00
|
|
|
case IM_ROOM_KICK_PARTICIPANT:
|
|
|
|
case IM_ROOM_BAN_PARTICIPANT:
|
|
|
|
case IM_ROOM_UNBAN_PARTICIPANT:
|
|
|
|
case IM_ROOM_MUTE_PARTICIPANT:
|
|
|
|
case IM_ROOM_UNMUTE_PARTICIPANT:
|
|
|
|
_MUCModeration(msg);
|
|
|
|
break;
|
2010-05-27 20:04:31 -05:00
|
|
|
default:
|
|
|
|
return B_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::Shutdown()
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
2010-07-10 14:27:32 -05:00
|
|
|
if (fVCardManager)
|
|
|
|
fVCardManager->cancelVCardOperations(this);
|
|
|
|
|
2021-06-11 20:33:28 -05:00
|
|
|
if (fClient)
|
2010-07-10 14:27:32 -05:00
|
|
|
fClient->disposeMessageSession(fSession);
|
2021-06-11 20:33:28 -05:00
|
|
|
|
|
|
|
kill_thread(fRecvThread);
|
2010-07-10 14:27:32 -05:00
|
|
|
|
2010-05-27 20:04:31 -05:00
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Allow multiple protocols per add-on
Now an add-on can contain multiple protocols, and the protocol API has
changed. An add-on must now export protocol_count() and protocol_at(),
with the latter replacing protocol(). protocol_count() returning the
amount of protocols in a given add-on, and protocol_at(i) giving a
new CayaProtocol* "at" the given index.
CayaProtocol has also been changed, adding Signature(),
FriendlySignature(), Icon(), Path(), and SetPath(). The reasoning is
that different protocols (even within a single add-on) will have
different signatures and icons, so this data should be accessible from
the protocol itself.
CayaProtocolAddOn now has CountProtocols() and ProtocolAt(i), allowing
the accessing of multiple protocols. A CayaProtocolAddOn can be given a
default protocol index in the constructor, whose protocol will be
returned with Protocol(). Version() was also moved from CayaProtocol to
CayaProtocolAddOn.
2021-05-21 13:33:43 -05:00
|
|
|
void
|
2021-06-01 21:53:50 -05:00
|
|
|
JabberHandler::SetAddOnPath(BPath path)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
Allow multiple protocols per add-on
Now an add-on can contain multiple protocols, and the protocol API has
changed. An add-on must now export protocol_count() and protocol_at(),
with the latter replacing protocol(). protocol_count() returning the
amount of protocols in a given add-on, and protocol_at(i) giving a
new CayaProtocol* "at" the given index.
CayaProtocol has also been changed, adding Signature(),
FriendlySignature(), Icon(), Path(), and SetPath(). The reasoning is
that different protocols (even within a single add-on) will have
different signatures and icons, so this data should be accessible from
the protocol itself.
CayaProtocolAddOn now has CountProtocols() and ProtocolAt(i), allowing
the accessing of multiple protocols. A CayaProtocolAddOn can be given a
default protocol index in the constructor, whose protocol will be
returned with Protocol(). Version() was also moved from CayaProtocol to
CayaProtocolAddOn.
2021-05-21 13:33:43 -05:00
|
|
|
fPath = path;
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Allow multiple protocols per add-on
Now an add-on can contain multiple protocols, and the protocol API has
changed. An add-on must now export protocol_count() and protocol_at(),
with the latter replacing protocol(). protocol_count() returning the
amount of protocols in a given add-on, and protocol_at(i) giving a
new CayaProtocol* "at" the given index.
CayaProtocol has also been changed, adding Signature(),
FriendlySignature(), Icon(), Path(), and SetPath(). The reasoning is
that different protocols (even within a single add-on) will have
different signatures and icons, so this data should be accessible from
the protocol itself.
CayaProtocolAddOn now has CountProtocols() and ProtocolAt(i), allowing
the accessing of multiple protocols. A CayaProtocolAddOn can be given a
default protocol index in the constructor, whose protocol will be
returned with Protocol(). Version() was also moved from CayaProtocol to
CayaProtocolAddOn.
2021-05-21 13:33:43 -05:00
|
|
|
BPath
|
2021-06-01 21:53:50 -05:00
|
|
|
JabberHandler::AddOnPath()
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
Allow multiple protocols per add-on
Now an add-on can contain multiple protocols, and the protocol API has
changed. An add-on must now export protocol_count() and protocol_at(),
with the latter replacing protocol(). protocol_count() returning the
amount of protocols in a given add-on, and protocol_at(i) giving a
new CayaProtocol* "at" the given index.
CayaProtocol has also been changed, adding Signature(),
FriendlySignature(), Icon(), Path(), and SetPath(). The reasoning is
that different protocols (even within a single add-on) will have
different signatures and icons, so this data should be accessible from
the protocol itself.
CayaProtocolAddOn now has CountProtocols() and ProtocolAt(i), allowing
the accessing of multiple protocols. A CayaProtocolAddOn can be given a
default protocol index in the constructor, whose protocol will be
returned with Protocol(). Version() was also moved from CayaProtocol to
CayaProtocolAddOn.
2021-05-21 13:33:43 -05:00
|
|
|
return fPath;
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-01 21:53:50 -05:00
|
|
|
void
|
|
|
|
JabberHandler::SetName(const char* name)
|
|
|
|
{
|
|
|
|
fName = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char*
|
|
|
|
JabberHandler::GetName()
|
|
|
|
{
|
|
|
|
return fName.String();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-20 01:24:34 -05:00
|
|
|
BObjectList<BMessage>
|
|
|
|
JabberHandler::Commands()
|
|
|
|
{
|
|
|
|
return BObjectList<BMessage>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BObjectList<BMessage>
|
|
|
|
JabberHandler::ChatPopUpItems()
|
|
|
|
{
|
|
|
|
return BObjectList<BMessage>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BObjectList<BMessage>
|
|
|
|
JabberHandler::UserPopUpItems()
|
|
|
|
{
|
|
|
|
return BObjectList<BMessage>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BObjectList<BMessage>
|
|
|
|
JabberHandler::MenuBarItems()
|
|
|
|
{
|
|
|
|
return BObjectList<BMessage>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-27 20:04:31 -05:00
|
|
|
status_t
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::UpdateSettings(BMessage* msg)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
const char* username = msg->FindString("username");
|
|
|
|
const char* password = msg->FindString("password");
|
|
|
|
const char* server = msg->FindString("server");
|
|
|
|
const char* resource = msg->FindString("resource");
|
|
|
|
|
|
|
|
// Sanity check
|
2010-05-28 15:41:58 -05:00
|
|
|
if (!username || !password || !resource)
|
2010-05-27 20:04:31 -05:00
|
|
|
return B_ERROR;
|
|
|
|
|
|
|
|
// Store settings
|
|
|
|
fUsername = username;
|
2021-06-02 16:58:29 -05:00
|
|
|
fNick = username;
|
2010-05-27 20:04:31 -05:00
|
|
|
fPassword = password;
|
|
|
|
fServer = server;
|
|
|
|
fResource = resource;
|
2010-05-30 07:17:59 -05:00
|
|
|
fPort = 5222;
|
2010-05-27 20:04:31 -05:00
|
|
|
|
2010-05-28 15:41:58 -05:00
|
|
|
// Give the add-on a change to override settings
|
|
|
|
OverrideSettings();
|
|
|
|
|
|
|
|
// Compose JID
|
|
|
|
BString jid = ComposeJID();
|
2010-05-30 07:17:59 -05:00
|
|
|
fJid.setJID(jid.String());
|
2010-05-27 20:04:31 -05:00
|
|
|
|
|
|
|
// Register our client
|
2021-07-18 20:03:42 -05:00
|
|
|
fClient = new OurClient(fJid, fPassword.String());
|
2010-05-28 15:41:58 -05:00
|
|
|
fClient->setServer(fServer.String());
|
2010-05-30 07:17:59 -05:00
|
|
|
if (fPort > 0)
|
|
|
|
fClient->setPort(fPort);
|
2010-05-27 20:04:31 -05:00
|
|
|
fClient->registerConnectionListener(this);
|
2010-07-10 14:27:32 -05:00
|
|
|
fClient->registerMessageSessionHandler(this);
|
2021-06-08 19:59:22 -05:00
|
|
|
fClient->registerMUCInvitationHandler(new InviteHandler(fClient, this));
|
2010-05-27 20:04:31 -05:00
|
|
|
fClient->rosterManager()->registerRosterListener(this);
|
2021-07-18 22:25:38 -05:00
|
|
|
fClient->disco()->setVersion("Cardie", VERSION);
|
|
|
|
fClient->disco()->setIdentity("client", "cardie");
|
2010-05-27 20:04:31 -05:00
|
|
|
fClient->logInstance().registerLogHandler(gloox::LogLevelDebug,
|
|
|
|
gloox::LogAreaAll, this);
|
|
|
|
|
|
|
|
// Register vCard manager
|
|
|
|
fVCardManager = new gloox::VCardManager(fClient);
|
|
|
|
|
|
|
|
// Connect to the server
|
|
|
|
fClient->connect(false);
|
|
|
|
|
|
|
|
// Read data from another thread
|
2010-05-28 15:41:58 -05:00
|
|
|
fRecvThread = spawn_thread(connect_thread, "connect_thread",
|
2010-05-30 15:50:04 -05:00
|
|
|
B_NORMAL_PRIORITY, (void*)this);
|
2010-05-28 15:41:58 -05:00
|
|
|
if (fRecvThread < B_OK)
|
|
|
|
return B_ERROR;
|
|
|
|
return B_OK;
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::GetEncoding()
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
return 0xffff;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-20 12:44:20 -05:00
|
|
|
ChatProtocolMessengerInterface*
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::MessengerInterface() const
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
return fServerMessenger;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-30 15:50:04 -05:00
|
|
|
gloox::Client*
|
|
|
|
JabberHandler::Client() const
|
|
|
|
{
|
|
|
|
return fClient;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2021-06-01 21:53:50 -05:00
|
|
|
JabberHandler::HandleConnectionError(gloox::ConnectionError& e)
|
2010-05-30 15:50:04 -05:00
|
|
|
{
|
2021-07-18 22:25:38 -05:00
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
#define B_TRANSLATION_CONTEXT "JabberHandler ― Connection errors"
|
|
|
|
|
2010-05-30 15:50:04 -05:00
|
|
|
// Handle error
|
|
|
|
BMessage errMsg(IM_ERROR);
|
|
|
|
|
|
|
|
switch (e) {
|
|
|
|
case gloox::ConnStreamError:
|
|
|
|
{
|
2021-07-18 22:25:38 -05:00
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
#define B_TRANSLATION_CONTEXT "JabberHandler ― Connection stream errors"
|
2010-05-30 15:50:04 -05:00
|
|
|
gloox::StreamError streamError = fClient->streamError();
|
|
|
|
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("error", B_TRANSLATE("Bad or malformed XML stream."));
|
2010-05-30 15:50:04 -05:00
|
|
|
|
|
|
|
switch (streamError) {
|
|
|
|
case gloox::StreamErrorBadFormat:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The entity has "
|
|
|
|
"sent XML that cannot be processed"));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorBadNamespacePrefix:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The entity has "
|
|
|
|
"sent a namespace prefix which is not supported, "
|
|
|
|
"or has sent no namespace prefix on an element "
|
|
|
|
"that requires such prefix."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorConflict:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The server is "
|
|
|
|
"closing the active stream for this entity "
|
|
|
|
"because a new stream has been initiated that "
|
|
|
|
"conflicts with the existing stream."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorConnectionTimeout:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The entity has "
|
|
|
|
"not generated any traffic over the stream for "
|
|
|
|
"some period of time."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorHostGone:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The host initially "
|
|
|
|
"used corresponds to a hostname that is no longer "
|
|
|
|
"hosted by the server."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorHostUnknown:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The host initially "
|
|
|
|
"used does not correspond to a hostname that is "
|
|
|
|
"hosted by the server."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorImproperAddressing:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("A stanza sent "
|
|
|
|
"between two servers lacks a 'to' or 'from' "
|
|
|
|
"attribute (or the attribute has no value."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorInternalServerError:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The server has "
|
|
|
|
"experienced a misconfiguration or an "
|
|
|
|
"otherwise-undefined internal error that prevents "
|
|
|
|
"it from servicing the stream."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorInvalidFrom:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The JID or "
|
|
|
|
"hostname provided in a 'from' address does not "
|
|
|
|
"match an authorized JID or validated domain "
|
|
|
|
"negotiation between servers via SASL or dialback, "
|
|
|
|
"or between a client and a server via "
|
|
|
|
"authentication and resource binding."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorInvalidId:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The stream ID or "
|
|
|
|
"dialback ID is invalid or does not match and ID "
|
|
|
|
"previously provdided."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorInvalidNamespace:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The streams "
|
|
|
|
"namespace name is something other than "
|
|
|
|
"\"http://etherx.jabber.org/streams\" or the "
|
|
|
|
"dialback namespace name is something other than "
|
|
|
|
"\"jabber:server:dialback\"."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorInvalidXml:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The entity has "
|
|
|
|
"sent invalid XML over the stream to a server that "
|
|
|
|
"performs validation."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorNotAuthorized:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The entity has "
|
|
|
|
"attempted to send data before the stream has been "
|
|
|
|
"authenticated, or otherwise is not authorized to "
|
|
|
|
"perform an action related to stream negotiation; "
|
|
|
|
"the receiving entity must not process the "
|
|
|
|
"offending stanza before sending the stream "
|
|
|
|
"error."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorPolicyViolation:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The entity has "
|
|
|
|
"violated some local service policy; the server "
|
|
|
|
"may choose to specify the policy in the <text/> "
|
|
|
|
"element or an application-specific condition "
|
|
|
|
"element."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorRemoteConnectionFailed:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The server is "
|
|
|
|
"unable to properly connect to a remote entity "
|
|
|
|
"that is required for authentication."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorResourceConstraint:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The server lacks "
|
|
|
|
"the system resources necessary to service the "
|
|
|
|
"stream."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorRestrictedXml:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The entity has "
|
|
|
|
"attempted to send restricted XML features such as "
|
|
|
|
"a comment, processing instruction, DTD, entity "
|
|
|
|
"reference or unescaped character."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorSeeOtherHost:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The server will "
|
|
|
|
"not provide service to the initiating entity but "
|
|
|
|
"is redirecting traffic to another host; the "
|
|
|
|
"server should specify the alternate hostname or "
|
|
|
|
"IP address (which MUST be a valid domain "
|
|
|
|
"identifier) as the XML characted data of the "
|
|
|
|
"<see-other-host/> element."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorSystemShutdown:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The server is "
|
|
|
|
"being shut down and all active streams are being "
|
|
|
|
"closed."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorUndefinedCondition:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The error "
|
|
|
|
"condition is not one of those defined by the "
|
|
|
|
"other condition in this list; this error "
|
|
|
|
"condition should be used only in conjunction with "
|
|
|
|
"an application-specific condition."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorUnsupportedEncoding:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The initiating "
|
|
|
|
"entity has encoded the stream in an encoding "
|
|
|
|
"that is not supported by the server."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorUnsupportedStanzaType:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The initiating "
|
|
|
|
"entity has sent a first-level child of the stream "
|
|
|
|
"that is not supported by the server."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorUnsupportedVersion:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The value of the "
|
|
|
|
"'version' attribute provided by the initiating "
|
|
|
|
"entity in the stream header specifies a version "
|
|
|
|
"of XMPP that is not supported by the server; the "
|
|
|
|
"server may specify the version(s) it supports in "
|
|
|
|
"the <text/> element."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::StreamErrorXmlNotWellFormed:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The initiating "
|
|
|
|
"entity has sent XML that is not well-formed as "
|
|
|
|
"defined by XML."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case gloox::ConnStreamVersionError:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The incoming stream's "
|
|
|
|
"version is not supported."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnStreamClosed:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The stream has been closed "
|
|
|
|
"by the server."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnProxyAuthRequired:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The HTTP/SOCKS5 proxy "
|
|
|
|
"requires authentication."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnProxyAuthFailed:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("HTTP/SOCKS5 proxy "
|
|
|
|
"authentication failed."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnProxyNoSupportedAuth:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The HTTP/SOCKS5 proxy "
|
|
|
|
"requires an unsupported authentication mechanism."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnIoError:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("Input/output error."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnParseError:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("A XML parse error "
|
|
|
|
"occurred."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnConnectionRefused:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The connection was refused "
|
|
|
|
"by the server on the socket level."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnDnsError:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("Server's hostname "
|
|
|
|
"resolution failed."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnOutOfMemory:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("Out of memory."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnTlsFailed:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The server's certificate "
|
|
|
|
"could not be verified or the TLS handshake did not "
|
|
|
|
"complete successfully."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnTlsNotAvailable:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The server didn't offer "
|
|
|
|
"TLS while it was set to be required, or TLS was not "
|
|
|
|
"compiled in."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnCompressionFailed:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("Negotiating or "
|
|
|
|
"initializing compression failed."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::ConnAuthenticationFailed:
|
|
|
|
{
|
2021-07-18 22:25:38 -05:00
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
#define B_TRANSLATION_CONTEXT "JabberHandler ― Connection authentication errors"
|
2010-05-30 15:50:04 -05:00
|
|
|
gloox::AuthenticationError authError = fClient->authError();
|
|
|
|
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("error", B_TRANSLATE("Authentication failed. "
|
|
|
|
"Username or password wrong or account does not "
|
|
|
|
"exist."));
|
2010-05-30 15:50:04 -05:00
|
|
|
|
|
|
|
switch (authError) {
|
|
|
|
case gloox::SaslAborted:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The receiving "
|
|
|
|
"entity acknowledges an <abort/> element sent by "
|
|
|
|
"initiating entity; sent in reply to the <abort/> "
|
|
|
|
"element."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::SaslIncorrectEncoding:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The data provided "
|
|
|
|
"by the initiating entity could not be processed "
|
|
|
|
"because the base64 encoding is incorrect."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::SaslInvalidAuthzid:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The authid "
|
|
|
|
"provided by the initiating entity is invalid, "
|
|
|
|
"either because it is incorrectly formatted or "
|
|
|
|
"because the initiating entity does not have "
|
|
|
|
"permissions to authorize that ID; sent in reply "
|
|
|
|
"to a <response/> element or an <auth/> element "
|
|
|
|
"with initial response data."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::SaslInvalidMechanism:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The initiating "
|
|
|
|
"element did not provide a mechanism or requested "
|
|
|
|
"a mechanism that is not supported by the "
|
|
|
|
"receiving entity; sent in reply to an <auth/> "
|
|
|
|
"element."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::SaslMalformedRequest:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The request is "
|
|
|
|
"malformed (e.g., the <auth/> element includes an "
|
|
|
|
"initial response but the mechanism does not "
|
|
|
|
"allow that); sent in reply to an <abort/>, "
|
|
|
|
"<auth/>, <challenge/>, or <response/> element."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::SaslMechanismTooWeak:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The mechanism "
|
|
|
|
"requested by the initiating entity is weaker "
|
|
|
|
"than server policy permits for that initiating "
|
|
|
|
"entity; sent in reply to a <response/> element or "
|
|
|
|
"an <auth/> element with initial response data."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::SaslNotAuthorized:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The authentication "
|
|
|
|
"failed because the initiating entity did not "
|
|
|
|
"provide valid credentials (this includes but is "
|
|
|
|
"not limited to the case of an unknown username); "
|
|
|
|
"sent in reply to a <response/> element or an "
|
|
|
|
"<auth/> element with initial response data."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::SaslTemporaryAuthFailure:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("The authentication "
|
|
|
|
"failed because of a temporary error condition "
|
|
|
|
"within the receiving entity; sent in reply to an "
|
|
|
|
"<auth/> element or <response/> element."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::NonSaslConflict:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("Resource conflict, "
|
|
|
|
"see XEP-0078."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::NonSaslNotAcceptable:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("Required "
|
|
|
|
"information not provided, see XEP-0078."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
case gloox::NonSaslNotAuthorized:
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("detail", B_TRANSLATE("Incorrect "
|
|
|
|
"credentials."));
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
Redesign add-on disconnection
Currently, add-ons are disconnected when ChatProtocol::Shutdown() is
called, which the add-on can do by itself― but there is no standard way
for add-ons to notify the app about their Shutdown. Because of this,
they tend to not call Shutdown()― instead (as in the case of the Jabber
add-on), they display a BAlert (IM_ERROR) notifying the user of the
connection error, but the account is considered active by Cardie (and
its threads are still existant, including its ProtocolLooper).
Zombies are bad, so this is redesigned somewhat with this commit:
Protocols should no longer call ChatProtocol::Shutdown() themselves,
they must send an IM_MESSAGE of IM_PROTOCOL_DISABLE to the app.
This will delete its ProtocolLooper, which in turn will send a
notification to the user and delete the ChatProtocol, and so
calling ChatProtocol::Shutdown().
In the included protocols, an IM_ERROR is sent right before
IM_PROTOCOL_DISABLE is sent if due to a connection error. This is not
required, but it is courteous to inform your user about the "why." :)
2021-07-18 17:52:36 -05:00
|
|
|
case gloox::ConnNotConnected: {
|
|
|
|
BMessage disconnect(IM_MESSAGE);
|
|
|
|
disconnect.AddInt32("im_what", IM_PROTOCOL_DISABLE);
|
|
|
|
_SendMessage(&disconnect);
|
2010-05-30 15:50:04 -05:00
|
|
|
break;
|
Redesign add-on disconnection
Currently, add-ons are disconnected when ChatProtocol::Shutdown() is
called, which the add-on can do by itself― but there is no standard way
for add-ons to notify the app about their Shutdown. Because of this,
they tend to not call Shutdown()― instead (as in the case of the Jabber
add-on), they display a BAlert (IM_ERROR) notifying the user of the
connection error, but the account is considered active by Cardie (and
its threads are still existant, including its ProtocolLooper).
Zombies are bad, so this is redesigned somewhat with this commit:
Protocols should no longer call ChatProtocol::Shutdown() themselves,
they must send an IM_MESSAGE of IM_PROTOCOL_DISABLE to the app.
This will delete its ProtocolLooper, which in turn will send a
notification to the user and delete the ChatProtocol, and so
calling ChatProtocol::Shutdown().
In the included protocols, an IM_ERROR is sent right before
IM_PROTOCOL_DISABLE is sent if due to a connection error. This is not
required, but it is courteous to inform your user about the "why." :)
2021-07-18 17:52:36 -05:00
|
|
|
}
|
2010-05-30 15:50:04 -05:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
_SendMessage(&errMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-01 21:53:50 -05:00
|
|
|
void
|
|
|
|
JabberHandler::HandleStanzaError(gloox::StanzaError error)
|
|
|
|
{
|
2021-07-18 22:25:38 -05:00
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
#define B_TRANSLATION_CONTEXT "JabberHandler ― Stanza errors"
|
|
|
|
|
2021-06-01 21:53:50 -05:00
|
|
|
BMessage errMsg(IM_ERROR);
|
2021-07-18 22:25:38 -05:00
|
|
|
errMsg.AddString("error", B_TRANSLATE("Stanza-related error"));
|
2021-06-01 21:53:50 -05:00
|
|
|
BString detail;
|
|
|
|
|
|
|
|
switch (error)
|
|
|
|
{
|
|
|
|
case gloox::StanzaErrorBadRequest:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The sender has sent XML that is malformed or "
|
|
|
|
"that cannot be processed.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorConflict:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("Access cannot be granted because an existing "
|
|
|
|
"resource or session exists with the same name or address.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorFeatureNotImplemented:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("This feature hasn't been implemented by the "
|
|
|
|
"recipient or by the server.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorForbidden:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("You don't have permssion to do this.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorGone:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The recipient or server can no longer be "
|
|
|
|
"contacted at this address. Try again later, or with a "
|
|
|
|
"different address.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorInternalServerError:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The server could not process the stanza "
|
|
|
|
"because of a misconfiguration or an otherwise-undefined "
|
|
|
|
"internal server error.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorItemNotFound:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The addressed JID or item requested cannot "
|
|
|
|
"be found.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorJidMalformed:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("An invalid XMPP address or identifier was "
|
|
|
|
"given. If you can, please try a different one.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorNotAcceptable:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The server or user refuses to accept this, "
|
|
|
|
"because some criteria hasn't been met (e.g., a local policy "
|
|
|
|
"regarding acceptable words in messages).");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorNotAllowed:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("You aren't allowed to do this by the server "
|
|
|
|
"or recepient.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorNotAuthorized:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("You need to be properily authenticated "
|
|
|
|
"before doing this.");
|
2021-06-01 21:53:50 -05:00
|
|
|
case gloox::StanzaErrorNotModified:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The item requested has not changed since it "
|
|
|
|
"was last requested.");
|
2021-06-01 21:53:50 -05:00
|
|
|
case gloox::StanzaErrorPaymentRequired:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The server refuses to offer service, because "
|
|
|
|
"payment is required.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorRecipientUnavailable:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The recipient is temporarily unavailable.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorRedirect:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The recipient or server is redirecting "
|
|
|
|
"requests for this information to another entity, usually "
|
|
|
|
"temporarily.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorRegistrationRequired:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("You can't do this before registration! Be "
|
|
|
|
"sure your finished registering for your account.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorRemoteServerNotFound:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("That user's server doesn't exist.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorRemoteServerTimeout:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("Connection to that user's server has timed "
|
|
|
|
"out.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorResourceConstraint:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The server or recipient are too busy right "
|
|
|
|
"now; try again later.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorServiceUnavailable:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("The server or recipient don't provide this "
|
|
|
|
"service.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
case gloox::StanzaErrorSubscribtionRequired:
|
2021-07-18 22:25:38 -05:00
|
|
|
detail = B_TRANSLATE("You can't access this unless you are "
|
|
|
|
"subscribed.");
|
2021-06-01 21:53:50 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
errMsg.AddString("detail", detail);
|
|
|
|
_SendMessage(&errMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-30 07:30:47 -05:00
|
|
|
void
|
|
|
|
JabberHandler::_SendMessage(BMessage* msg)
|
|
|
|
{
|
|
|
|
// Skip invalid messages
|
|
|
|
if (!msg)
|
|
|
|
return;
|
|
|
|
|
Allow multiple protocols per add-on
Now an add-on can contain multiple protocols, and the protocol API has
changed. An add-on must now export protocol_count() and protocol_at(),
with the latter replacing protocol(). protocol_count() returning the
amount of protocols in a given add-on, and protocol_at(i) giving a
new CayaProtocol* "at" the given index.
CayaProtocol has also been changed, adding Signature(),
FriendlySignature(), Icon(), Path(), and SetPath(). The reasoning is
that different protocols (even within a single add-on) will have
different signatures and icons, so this data should be accessible from
the protocol itself.
CayaProtocolAddOn now has CountProtocols() and ProtocolAt(i), allowing
the accessing of multiple protocols. A CayaProtocolAddOn can be given a
default protocol index in the constructor, whose protocol will be
returned with Protocol(). Version() was also moved from CayaProtocol to
CayaProtocolAddOn.
2021-05-21 13:33:43 -05:00
|
|
|
msg->AddString("protocol", Signature());
|
2010-05-30 07:30:47 -05:00
|
|
|
fServerMessenger->SendMessage(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-30 13:57:19 -05:00
|
|
|
JabberHandler::_Notify(notification_type type, const char* title, const char* message)
|
|
|
|
{
|
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddInt32("im_what", IM_NOTIFICATION);
|
|
|
|
msg.AddInt32("type", (int32)type);
|
|
|
|
msg.AddString("title", title);
|
|
|
|
msg.AddString("message", message);
|
|
|
|
_SendMessage(&msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::_NotifyProgress(const char* title, const char* message, float progress)
|
2010-05-30 07:30:47 -05:00
|
|
|
{
|
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddInt32("im_what", IM_PROGRESS);
|
|
|
|
msg.AddString("title", title);
|
|
|
|
msg.AddString("message", message);
|
|
|
|
msg.AddFloat("progress", progress);
|
|
|
|
_SendMessage(&msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-27 20:04:31 -05:00
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::_MessageSent(const char* id, const char* subject,
|
2010-05-27 20:04:31 -05:00
|
|
|
const char* body)
|
|
|
|
{
|
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddInt32("im_what", IM_MESSAGE_SENT);
|
2021-06-06 12:02:26 -05:00
|
|
|
msg.AddString("user_id", fJid.bare().c_str());
|
2021-05-24 01:47:21 -05:00
|
|
|
msg.AddString("chat_id", id);
|
2010-05-27 20:04:31 -05:00
|
|
|
msg.AddString("subject", subject);
|
|
|
|
msg.AddString("body", body);
|
2010-05-30 07:30:47 -05:00
|
|
|
_SendMessage(&msg);
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-26 07:48:25 -05:00
|
|
|
void
|
2021-06-07 00:03:15 -05:00
|
|
|
JabberHandler::_ChatCreatedMsg(const char* id)
|
2021-05-26 07:48:25 -05:00
|
|
|
{
|
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddInt32("im_what", IM_CHAT_CREATED);
|
|
|
|
msg.AddString("chat_id", id);
|
|
|
|
msg.AddString("user_id", id);
|
|
|
|
_SendMessage(&msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-07 00:03:15 -05:00
|
|
|
void
|
|
|
|
JabberHandler::_RoleChangedMsg(BString chat_id, BString user_id,
|
|
|
|
gloox::MUCRoomRole role, gloox::MUCRoomAffiliation aff)
|
|
|
|
{
|
|
|
|
BMessage roleMsg(IM_MESSAGE);
|
2021-06-07 11:45:30 -05:00
|
|
|
roleMsg.AddInt32("im_what", IM_ROOM_ROLECHANGED);
|
2021-06-07 00:03:15 -05:00
|
|
|
roleMsg.AddString("user_id", user_id);
|
|
|
|
roleMsg.AddString("chat_id", chat_id);
|
|
|
|
roleMsg.AddString("role_title", _RoleTitle(role, aff));
|
|
|
|
roleMsg.AddInt32("role_perms", _RolePerms(role, aff));
|
|
|
|
roleMsg.AddInt32("role_priority", _RolePriority(role, aff));
|
|
|
|
_SendMessage(&roleMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::_UserLeftMsg(BString chat_id, gloox::MUCRoomParticipant participant)
|
|
|
|
{
|
|
|
|
BString user_id;
|
|
|
|
const char* nick = participant.nick->resource().c_str();
|
|
|
|
bool isSelf = _MUCUserId(chat_id, nick, &user_id);
|
|
|
|
|
|
|
|
if (user_id.IsEmpty() == true)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int32 im_what = IM_ROOM_PARTICIPANT_LEFT;
|
|
|
|
int flags = participant.flags;
|
|
|
|
|
|
|
|
if (flags & gloox::UserBanned)
|
|
|
|
im_what = IM_ROOM_PARTICIPANT_BANNED;
|
|
|
|
else if (flags & gloox::UserKicked)
|
|
|
|
im_what = IM_ROOM_PARTICIPANT_KICKED;
|
|
|
|
|
|
|
|
BMessage leftMsg(IM_MESSAGE);
|
|
|
|
leftMsg.AddInt32("im_what", im_what);
|
|
|
|
leftMsg.AddString("chat_id", chat_id);
|
|
|
|
leftMsg.AddString("user_id", user_id);
|
|
|
|
leftMsg.AddString("user_name", nick);
|
|
|
|
if (participant.reason.empty() == false)
|
|
|
|
leftMsg.AddString("body", participant.reason.c_str());
|
|
|
|
_SendMessage(&leftMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::_StatusSetMsg(const char* user_id, gloox::Presence::PresenceType type,
|
|
|
|
const char* message, const char* resource)
|
|
|
|
{
|
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddInt32("im_what", IM_STATUS_SET);
|
|
|
|
msg.AddString("user_id", user_id);
|
2021-06-20 12:44:20 -05:00
|
|
|
msg.AddInt32("status", _GlooxStatusToApp(type));
|
2021-06-07 00:03:15 -05:00
|
|
|
|
|
|
|
if (BString(resource).IsEmpty() == false)
|
|
|
|
msg.AddString("resource", resource);
|
|
|
|
if (BString(message).IsEmpty() == false)
|
|
|
|
msg.AddString("message", message);
|
|
|
|
|
|
|
|
_SendMessage(&msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-13 01:16:30 -05:00
|
|
|
void
|
|
|
|
JabberHandler::_EnsureUserChat(const char* chat_id)
|
|
|
|
{
|
|
|
|
if (fUserChats.HasString(BString(chat_id)) == false)
|
|
|
|
fUserChats.Add(BString(chat_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-29 23:26:36 -05:00
|
|
|
status_t
|
|
|
|
JabberHandler::_SetupAvatarCache()
|
|
|
|
{
|
|
|
|
if (fAvatarCachePath.InitCheck() == B_OK)
|
|
|
|
return B_OK;
|
|
|
|
|
|
|
|
BPath path;
|
|
|
|
|
|
|
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
|
|
|
|
return B_ERROR;
|
|
|
|
|
Reorganize settings directory, custom purple paths
The settings file-hierarchy has been changed a bit:
* Cardie/
* preferences
* Accounts/
* Cache/
* Accounts/
* Add-Ons/
`Cardie/Protocols` is now `Cardie/Accounts`, and the cache directory
has been split into two. `Cache/Accounts/` is for account-specific
cached data (e.g., cached roster icons, data, etc.), and
`Cache/Protocols` is for protocol-wide settings/data.
For purple, this will be used as the user's libpurple directory,
which has been moved from the default of `~/.purple` (yikes!)
Some plugin search-paths have been given to purple, too― lib
directories + "/purple2/", and Cardie/Cache/Add-Ons/purple/plugins/.
2021-06-30 20:29:30 -05:00
|
|
|
path.Append("Cardie/Cache/Accounts");
|
2021-06-09 11:40:27 -05:00
|
|
|
path.Append(GetName());
|
2010-05-29 23:26:36 -05:00
|
|
|
|
|
|
|
if (create_directory(path.Path(), 0755) != B_OK)
|
|
|
|
return B_ERROR;
|
|
|
|
|
|
|
|
fCachePath = path;
|
|
|
|
|
|
|
|
path.Append("avatar-cache");
|
|
|
|
|
|
|
|
BFile file(path.Path(), B_READ_ONLY);
|
|
|
|
fAvatarCache.Unflatten(&file);
|
|
|
|
|
|
|
|
fAvatarCachePath = path;
|
|
|
|
|
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
JabberHandler::_SaveAvatarCache()
|
|
|
|
{
|
|
|
|
if (fAvatarCachePath.InitCheck() != B_OK)
|
|
|
|
return B_ERROR;
|
|
|
|
|
|
|
|
BFile file(fAvatarCachePath.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE);
|
|
|
|
return fAvatarCache.Flatten(&file);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::_CacheAvatar(const char* id, const char* binimage, size_t length)
|
|
|
|
{
|
|
|
|
if (!id || !binimage || length <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Calculate avatar hash
|
|
|
|
CSHA1 s1;
|
|
|
|
char hash[256];
|
|
|
|
s1.Reset();
|
|
|
|
s1.Update((uchar*)binimage, length);
|
|
|
|
s1.Final();
|
|
|
|
s1.ReportHash(hash, CSHA1::REPORT_HEX);
|
|
|
|
|
|
|
|
BString sha1;
|
|
|
|
sha1.SetTo(hash, 256);
|
|
|
|
|
|
|
|
BString oldSha1;
|
2010-05-30 07:17:59 -05:00
|
|
|
if (fAvatarCache.FindString(id, &oldSha1) != B_OK || oldSha1 == "" || sha1 != oldSha1) {
|
2010-05-29 23:26:36 -05:00
|
|
|
// Replace old hash and save cache
|
|
|
|
fAvatarCache.RemoveName(id);
|
|
|
|
fAvatarCache.AddString(id, sha1);
|
|
|
|
_SaveAvatarCache();
|
|
|
|
|
|
|
|
if (oldSha1 != "") {
|
|
|
|
BPath path(fCachePath);
|
|
|
|
path.Append(oldSha1);
|
|
|
|
|
|
|
|
// Remove old image file
|
|
|
|
BEntry entry(path.Path());
|
|
|
|
entry.Remove();
|
|
|
|
|
|
|
|
// Remove old hash from the list
|
|
|
|
BString* item = NULL;
|
|
|
|
for (int32 i = 0; (item = (BString*)fAvatars->ItemAt(i)); i++) {
|
|
|
|
if (item->Compare(oldSha1) == 0) {
|
|
|
|
fAvatars->RemoveItem(item);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine file path
|
|
|
|
BPath path(fCachePath);
|
|
|
|
path.Append(sha1);
|
|
|
|
|
|
|
|
BEntry entry(path.Path());
|
|
|
|
if (!entry.Exists()) {
|
|
|
|
// Save to file
|
|
|
|
BFile file(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE);
|
|
|
|
file.Write(binimage, length);
|
|
|
|
}
|
|
|
|
|
2021-07-18 22:25:38 -05:00
|
|
|
// Do we need to notify the app?
|
2010-05-29 23:26:36 -05:00
|
|
|
bool found = false;
|
|
|
|
BString* item = NULL;
|
|
|
|
for (int32 i = 0; (item = (BString*)fAvatars->ItemAt(i)); i++) {
|
|
|
|
if (item->Compare(sha1) == 0) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
// Add new hash to the list if needed
|
|
|
|
fAvatars->AddItem(new BString(sha1));
|
|
|
|
|
|
|
|
// Notify Caya that the avatar has changed
|
|
|
|
_AvatarChanged(id, path.Path());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::_AvatarChanged(const char* id, const char* filename)
|
|
|
|
{
|
|
|
|
entry_ref ref;
|
|
|
|
if (get_ref_for_path(filename, &ref) != B_OK)
|
|
|
|
return;
|
|
|
|
|
|
|
|
BMessage msg(IM_MESSAGE);
|
2010-05-30 07:17:59 -05:00
|
|
|
if (fJid.bare() == id)
|
|
|
|
msg.AddInt32("im_what", IM_OWN_AVATAR_SET);
|
|
|
|
else {
|
|
|
|
msg.AddInt32("im_what", IM_AVATAR_SET);
|
2021-05-24 01:47:21 -05:00
|
|
|
msg.AddString("user_id", id);
|
2010-05-30 07:17:59 -05:00
|
|
|
}
|
2010-05-29 23:26:36 -05:00
|
|
|
msg.AddRef("ref", &ref);
|
2010-05-30 07:30:47 -05:00
|
|
|
_SendMessage(&msg);
|
2010-05-30 07:17:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-20 12:44:20 -05:00
|
|
|
UserStatus
|
|
|
|
JabberHandler::_GlooxStatusToApp(gloox::Presence::PresenceType type)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case gloox::Presence::Available:
|
|
|
|
case gloox::Presence::Chat:
|
2021-06-20 12:44:20 -05:00
|
|
|
return STATUS_ONLINE;
|
2010-05-27 20:04:31 -05:00
|
|
|
case gloox::Presence::Away:
|
2021-06-20 12:44:20 -05:00
|
|
|
return STATUS_AWAY;
|
2010-05-27 20:04:31 -05:00
|
|
|
case gloox::Presence::XA:
|
2021-06-20 12:44:20 -05:00
|
|
|
return STATUS_CUSTOM_STATUS;
|
2010-05-27 20:04:31 -05:00
|
|
|
case gloox::Presence::DND:
|
2021-06-20 12:44:20 -05:00
|
|
|
return STATUS_DO_NOT_DISTURB;
|
2010-05-27 20:04:31 -05:00
|
|
|
case gloox::Presence::Unavailable:
|
2021-06-20 12:44:20 -05:00
|
|
|
return STATUS_OFFLINE;
|
2010-05-27 20:04:31 -05:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-06-20 12:44:20 -05:00
|
|
|
return STATUS_OFFLINE;
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-03 20:24:34 -05:00
|
|
|
BString
|
2021-06-03 14:25:51 -05:00
|
|
|
JabberHandler::_MUCChatId(gloox::MUCRoom* room)
|
|
|
|
{
|
|
|
|
BString chat_id(room->name().c_str());
|
|
|
|
chat_id << "@" << room->service().c_str();
|
|
|
|
|
2021-06-03 20:24:34 -05:00
|
|
|
BStringList parts;
|
|
|
|
chat_id.Split("/", false, parts);
|
|
|
|
|
|
|
|
return parts.StringAt(0);
|
2021-06-03 14:25:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2021-06-03 20:24:34 -05:00
|
|
|
JabberHandler::_MUCUserId(BString chat_id, const char* nick, BString* id)
|
2021-06-03 14:25:51 -05:00
|
|
|
{
|
|
|
|
BString chat(chat_id);
|
|
|
|
chat << "/" << nick;
|
|
|
|
|
|
|
|
// If sent from own user, use normal ID
|
|
|
|
if (nick == fNick) {
|
|
|
|
*id = fJid.bare().c_str();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
*id = chat;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-08 19:59:22 -05:00
|
|
|
void
|
|
|
|
JabberHandler::_JoinRoom(const char* chat_id)
|
|
|
|
{
|
|
|
|
BString join_id(chat_id);
|
|
|
|
join_id << "/" << fNick;
|
|
|
|
|
|
|
|
gloox::MUCRoom* room = fRooms.ValueFor(chat_id);
|
|
|
|
if (room == NULL)
|
|
|
|
room = new gloox::MUCRoom(fClient, gloox::JID(join_id.String()), this, this);
|
|
|
|
|
|
|
|
room->join();
|
|
|
|
fRooms.AddItem(BString(chat_id), room);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-06 16:31:25 -05:00
|
|
|
void
|
|
|
|
JabberHandler::_MUCModeration(BMessage* msg)
|
|
|
|
{
|
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
BString user_id;
|
|
|
|
BString body = msg->FindString("body");
|
|
|
|
gloox::MUCRoom* room = fRooms.ValueFor(chat_id);
|
|
|
|
|
|
|
|
if (room == NULL || msg->FindString("user_id", &user_id) != B_OK)
|
|
|
|
return;
|
|
|
|
|
|
|
|
std::string nick = gloox::JID(user_id.String()).resource();
|
|
|
|
|
|
|
|
switch (msg->FindInt32("im_what"))
|
|
|
|
{
|
|
|
|
case IM_ROOM_KICK_PARTICIPANT:
|
|
|
|
room->kick(nick, body.String());
|
|
|
|
break;
|
|
|
|
case IM_ROOM_BAN_PARTICIPANT:
|
|
|
|
room->ban(nick, body.String());
|
|
|
|
break;
|
|
|
|
case IM_ROOM_MUTE_PARTICIPANT:
|
|
|
|
room->revokeVoice(nick, body.String());
|
|
|
|
break;
|
|
|
|
case IM_ROOM_UNMUTE_PARTICIPANT:
|
|
|
|
room->grantVoice(nick, body.String());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
const char*
|
|
|
|
JabberHandler::_RoleTitle(gloox::MUCRoomRole role, gloox::MUCRoomAffiliation aff)
|
|
|
|
{
|
2021-07-18 22:25:38 -05:00
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
#define B_TRANSLATION_CONTEXT "JabberHandler ― User roles"
|
|
|
|
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
switch (role)
|
|
|
|
{
|
|
|
|
case gloox::RoleVisitor:
|
2021-07-18 22:25:38 -05:00
|
|
|
return B_TRANSLATE("Visitor");
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
case gloox::RoleParticipant:
|
2021-07-18 22:25:38 -05:00
|
|
|
return B_TRANSLATE("Member");
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
case gloox::RoleModerator:
|
|
|
|
if (aff == gloox::AffiliationOwner)
|
2021-07-18 22:25:38 -05:00
|
|
|
return B_TRANSLATE("Owner");
|
|
|
|
return B_TRANSLATE("Moderator");
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
}
|
2021-07-18 22:25:38 -05:00
|
|
|
return B_TRANSLATE("Invalid");
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-06 01:49:11 -05:00
|
|
|
int32
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
JabberHandler::_RolePerms(gloox::MUCRoomRole role, gloox::MUCRoomAffiliation aff)
|
|
|
|
{
|
|
|
|
switch (role)
|
|
|
|
{
|
|
|
|
case gloox::RoleVisitor:
|
|
|
|
return 0 | PERM_READ | PERM_NICK;
|
|
|
|
case gloox::RoleParticipant:
|
|
|
|
return 0 | PERM_READ | PERM_WRITE | PERM_ROOM_SUBJECT;
|
2021-06-06 16:31:25 -05:00
|
|
|
case gloox::RoleModerator: {
|
|
|
|
int32 perm = 0 | PERM_READ | PERM_WRITE | PERM_ROOM_SUBJECT
|
|
|
|
| PERM_KICK | PERM_MUTE;
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
if (aff == gloox::AffiliationOwner)
|
2021-06-06 16:31:25 -05:00
|
|
|
perm = perm | PERM_ROLECHANGE | PERM_BAN;
|
|
|
|
return perm;
|
|
|
|
}
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-06 01:49:11 -05:00
|
|
|
int32
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
JabberHandler::_RolePriority(gloox::MUCRoomRole role, gloox::MUCRoomAffiliation aff)
|
|
|
|
{
|
|
|
|
switch (role)
|
|
|
|
{
|
|
|
|
case gloox::RoleParticipant:
|
|
|
|
return 1;
|
|
|
|
case gloox::RoleModerator:
|
|
|
|
if (aff == gloox::AffiliationOwner)
|
|
|
|
return 3;
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-20 09:32:52 -05:00
|
|
|
BMessage
|
|
|
|
JabberHandler::_SettingsTemplate(const char* username, bool serverOption)
|
|
|
|
{
|
2021-07-18 22:25:38 -05:00
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
#define B_TRANSLATION_CONTEXT "JabberHandler ― Settings template"
|
|
|
|
|
2021-05-20 09:32:52 -05:00
|
|
|
BMessage stemplate('IMst');
|
|
|
|
|
|
|
|
BMessage usernameText;
|
|
|
|
usernameText.AddString("name", "username");
|
|
|
|
usernameText.AddString("description", username);
|
2021-07-18 22:25:38 -05:00
|
|
|
usernameText.AddString("error", B_TRANSLATE("You can't log into an account "
|
|
|
|
"without a username.\nPlease fill in your username for the given "
|
|
|
|
"server."));
|
2021-05-20 09:32:52 -05:00
|
|
|
usernameText.AddInt32("type", 'CSTR');
|
|
|
|
stemplate.AddMessage("setting", &usernameText);
|
|
|
|
|
|
|
|
BMessage passwordText;
|
|
|
|
passwordText.AddString("name", "password");
|
2021-07-18 22:25:38 -05:00
|
|
|
passwordText.AddString("description", B_TRANSLATE("Password:"));
|
|
|
|
passwordText.AddString("error", B_TRANSLATE("You can't log into an account "
|
|
|
|
"without a password.\nPlease fill in your password for the given "
|
|
|
|
"account."));
|
2021-05-20 09:32:52 -05:00
|
|
|
passwordText.AddInt32("type", 'CSTR');
|
|
|
|
passwordText.AddBool("is_secret", true);
|
|
|
|
stemplate.AddMessage("setting", &passwordText);
|
|
|
|
|
|
|
|
BMessage serverText;
|
|
|
|
serverText.AddString("name", "server");
|
2021-07-18 22:25:38 -05:00
|
|
|
serverText.AddString("description", B_TRANSLATE("Server:"));
|
|
|
|
serverText.AddString("error", B_TRANSLATE("You can't add an account "
|
|
|
|
"without a server.\nPlease add a valid XMPP server."));
|
2021-05-20 09:32:52 -05:00
|
|
|
serverText.AddInt32("type", 'CSTR');
|
|
|
|
if (serverOption == true)
|
|
|
|
stemplate.AddMessage("setting", &serverText);
|
|
|
|
|
|
|
|
BMessage resourceText;
|
|
|
|
resourceText.AddString("name", "resource");
|
2021-07-18 22:25:38 -05:00
|
|
|
resourceText.AddString("description", B_TRANSLATE("Resource:"));
|
2021-05-20 09:32:52 -05:00
|
|
|
resourceText.AddInt32("type", 'CSTR');
|
2021-07-18 22:25:38 -05:00
|
|
|
resourceText.AddString("default", "Cardie");
|
|
|
|
resourceText.AddString("error", B_TRANSLATE("You can't add an account "
|
|
|
|
"without a resource.\nDon't worry― it can be whatever string you "
|
|
|
|
"want."));
|
2021-05-20 09:32:52 -05:00
|
|
|
stemplate.AddMessage("setting", &resourceText);
|
|
|
|
|
|
|
|
return stemplate;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-18 01:30:59 -05:00
|
|
|
BMessage
|
|
|
|
JabberHandler::_RoomTemplate()
|
|
|
|
{
|
2021-07-18 22:25:38 -05:00
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
#define B_TRANSLATION_CONTEXT "JabberHandler ― Room template"
|
|
|
|
|
2021-06-18 01:30:59 -05:00
|
|
|
BMessage stemplate('IMst');
|
|
|
|
BMessage roomIdentifier;
|
|
|
|
roomIdentifier.AddString("name", "chat_id");
|
2021-07-18 22:25:38 -05:00
|
|
|
roomIdentifier.AddString("description", B_TRANSLATE("Room ID:"));
|
|
|
|
roomIdentifier.AddString("error", B_TRANSLATE("You can't have a room "
|
|
|
|
"without a JID!\nUse the \"name@server\" format."));
|
2021-06-18 01:30:59 -05:00
|
|
|
roomIdentifier.AddInt32("type", 'CSTR');
|
|
|
|
stemplate.AddMessage("setting", &roomIdentifier);
|
|
|
|
|
|
|
|
return stemplate;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-19 18:25:58 -05:00
|
|
|
BMessage
|
|
|
|
JabberHandler::_RosterTemplate()
|
|
|
|
{
|
2021-07-18 22:25:38 -05:00
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
#define B_TRANSLATION_CONTEXT "JabberHandler ― Roster template"
|
|
|
|
|
2021-06-19 18:25:58 -05:00
|
|
|
BMessage stemplate('IMst');
|
|
|
|
|
|
|
|
BMessage user_id;
|
|
|
|
user_id.AddString("name", "user_id");
|
2021-07-18 22:25:38 -05:00
|
|
|
user_id.AddString("description", B_TRANSLATE("User ID:"));
|
|
|
|
user_id.AddString("error", B_TRANSLATE("You can't befriend an IDless "
|
|
|
|
"miscreant!\nPlease use the \"name@server\" format."));
|
2021-06-19 18:25:58 -05:00
|
|
|
user_id.AddInt32("type", 'CSTR');
|
|
|
|
stemplate.AddMessage("setting", &user_id);
|
|
|
|
|
|
|
|
BMessage user_name;
|
|
|
|
user_name.AddString("name", "user_name");
|
2021-07-18 22:25:38 -05:00
|
|
|
user_name.AddString("description", B_TRANSLATE("Nickname:"));
|
2021-06-19 18:25:58 -05:00
|
|
|
user_name.AddInt32("type", 'CSTR');
|
|
|
|
stemplate.AddMessage("setting", &user_name);
|
|
|
|
|
|
|
|
return stemplate;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-27 20:04:31 -05:00
|
|
|
/***********************************************************************
|
|
|
|
* gloox callbacks
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::onConnect()
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
2010-05-30 15:50:04 -05:00
|
|
|
// We are online
|
2010-05-27 20:04:31 -05:00
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddInt32("im_what", IM_OWN_STATUS_SET);
|
2021-06-20 12:44:20 -05:00
|
|
|
msg.AddInt32("status", STATUS_ONLINE);
|
2010-05-30 07:30:47 -05:00
|
|
|
_SendMessage(&msg);
|
2010-05-30 07:17:59 -05:00
|
|
|
|
|
|
|
fVCardManager->fetchVCard(fJid, this);
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::onDisconnect(gloox::ConnectionError e)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
2010-05-30 15:50:04 -05:00
|
|
|
// We are offline
|
2010-05-27 20:04:31 -05:00
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddInt32("im_what", IM_OWN_STATUS_SET);
|
2021-06-20 12:44:20 -05:00
|
|
|
msg.AddInt32("status", STATUS_OFFLINE);
|
2010-05-30 07:30:47 -05:00
|
|
|
_SendMessage(&msg);
|
2010-05-30 07:17:59 -05:00
|
|
|
|
2010-05-30 15:50:04 -05:00
|
|
|
if (e == gloox::ConnNoError) {
|
|
|
|
// Notify our offline status
|
|
|
|
BString content(fUsername);
|
|
|
|
content << " has logged out!";
|
|
|
|
_Notify(B_INFORMATION_NOTIFICATION, "Disconnected",
|
|
|
|
content.String());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle error
|
2021-06-01 21:53:50 -05:00
|
|
|
HandleConnectionError(e);
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::onTLSConnect(const gloox::CertInfo& info)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::onResourceBindError(const gloox::Error* error)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleRoster(const gloox::Roster& roster)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
std::list<BMessage> msgs;
|
|
|
|
|
|
|
|
BMessage contactListMsg(IM_MESSAGE);
|
|
|
|
contactListMsg.AddInt32("im_what", IM_CONTACT_LIST);
|
|
|
|
|
|
|
|
gloox::Roster::const_iterator it = roster.begin();
|
|
|
|
for (; it != roster.end(); ++it) {
|
2021-05-19 16:13:24 -05:00
|
|
|
const char* jid = (*it).second->jidJID().full().c_str();
|
2010-05-27 20:04:31 -05:00
|
|
|
const char* name = (*it).second->name().c_str();
|
|
|
|
int32 subscription = (*it).second->subscription();
|
|
|
|
|
|
|
|
// Add jid to the server based contact list message
|
2021-05-24 01:47:21 -05:00
|
|
|
contactListMsg.AddString("user_id", jid);
|
2010-05-27 20:04:31 -05:00
|
|
|
|
|
|
|
// Contact information message
|
|
|
|
BMessage infoMsg(IM_MESSAGE);
|
|
|
|
infoMsg.AddInt32("im_what", IM_CONTACT_INFO);
|
2021-05-24 01:47:21 -05:00
|
|
|
infoMsg.AddString("user_id", jid);
|
2021-06-07 11:45:30 -05:00
|
|
|
infoMsg.AddString("user_name", name);
|
2021-06-20 12:44:20 -05:00
|
|
|
infoMsg.AddInt32("status", STATUS_OFFLINE);
|
2010-05-27 20:04:31 -05:00
|
|
|
|
|
|
|
// Groups
|
|
|
|
gloox::StringList g = (*it).second->groups();
|
|
|
|
gloox::StringList::const_iterator it_g = g.begin();
|
|
|
|
for (; it_g != g.end(); ++it_g)
|
|
|
|
infoMsg.AddString("group", (*it_g).c_str());
|
|
|
|
|
|
|
|
// Resources
|
|
|
|
gloox::RosterItem::ResourceMap::const_iterator rit
|
|
|
|
= (*it).second->resources().begin();
|
|
|
|
for (; rit != (*it).second->resources().end(); ++rit)
|
|
|
|
infoMsg.AddString("resource", (*rit).first.c_str());
|
|
|
|
|
|
|
|
// Store contact info message to be sent later
|
|
|
|
msgs.push_back(infoMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send server based contact list
|
2010-05-30 07:30:47 -05:00
|
|
|
_SendMessage(&contactListMsg);
|
2010-05-27 20:04:31 -05:00
|
|
|
|
|
|
|
// Contact list and vCard request
|
|
|
|
std::list<BMessage>::iterator msgsIt;
|
|
|
|
for (msgsIt = msgs.begin(); msgsIt != msgs.end(); ++msgsIt) {
|
|
|
|
BMessage msg = (*msgsIt);
|
2021-05-24 01:47:21 -05:00
|
|
|
const char* jid = msg.FindString("user_id");
|
2010-05-30 07:30:47 -05:00
|
|
|
_SendMessage(&msg);
|
2010-05-27 20:04:31 -05:00
|
|
|
fVCardManager->fetchVCard(gloox::JID(jid), this);
|
|
|
|
}
|
2021-06-12 16:13:52 -05:00
|
|
|
|
|
|
|
// This is a safe spot to say "READY", since this is called immediately
|
|
|
|
// after logging in, whether the user has friends in the roster or not―
|
|
|
|
// especially since loading all the users from the roster can take a while.
|
|
|
|
BMessage readyMsg(IM_MESSAGE);
|
|
|
|
readyMsg.AddInt32("im_what", IM_PROTOCOL_READY);
|
|
|
|
_SendMessage(&readyMsg);
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-10 14:27:32 -05:00
|
|
|
void
|
|
|
|
JabberHandler::handleMessageSession(gloox::MessageSession* session)
|
|
|
|
{
|
|
|
|
// Delete previous session
|
|
|
|
if (fSession)
|
|
|
|
fClient->disposeMessageSession(fSession);
|
|
|
|
fSession = session;
|
|
|
|
|
|
|
|
// Register message handler
|
|
|
|
fSession->registerMessageHandler(this);
|
|
|
|
|
|
|
|
// Message event filter
|
|
|
|
gloox::MessageEventFilter* messageFilter
|
|
|
|
= new gloox::MessageEventFilter(fSession);
|
|
|
|
messageFilter->registerMessageEventHandler(this);
|
|
|
|
|
|
|
|
// Chat state filter
|
|
|
|
gloox::ChatStateFilter* chatFilter
|
|
|
|
= new gloox::ChatStateFilter(fSession);
|
|
|
|
chatFilter->registerChatStateHandler(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-27 20:04:31 -05:00
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleMessage(const gloox::Message& m, gloox::MessageSession*)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
// Only chat messages are handled now
|
|
|
|
if (m.subtype() != gloox::Message::Chat)
|
|
|
|
return;
|
|
|
|
|
2010-07-10 14:27:32 -05:00
|
|
|
// We need a body
|
|
|
|
if (m.body() == "")
|
|
|
|
return;
|
|
|
|
|
2021-06-13 01:16:30 -05:00
|
|
|
_EnsureUserChat(m.from().bare().c_str());
|
|
|
|
|
2010-07-10 14:27:32 -05:00
|
|
|
// Notify that a chat message was received
|
|
|
|
BMessage msg(IM_MESSAGE);
|
2021-05-24 01:47:21 -05:00
|
|
|
msg.AddString("user_id", m.from().bare().c_str());
|
|
|
|
msg.AddString("chat_id", m.from().bare().c_str());
|
2010-07-10 14:27:32 -05:00
|
|
|
msg.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
|
|
|
if (m.subject() != "")
|
2010-05-27 20:04:31 -05:00
|
|
|
msg.AddString("subject", m.subject().c_str());
|
2010-07-10 14:27:32 -05:00
|
|
|
msg.AddString("body", m.body().c_str());
|
|
|
|
_SendMessage(&msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleMessageEvent(const gloox::JID& from, gloox::MessageEventType event)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleChatState(const gloox::JID& from, gloox::ChatStateType state)
|
|
|
|
{
|
|
|
|
// We're interested only in some states
|
|
|
|
if (state == gloox::ChatStateActive || state == gloox::ChatStateInvalid)
|
|
|
|
return;
|
|
|
|
|
2021-06-13 01:16:30 -05:00
|
|
|
_EnsureUserChat(from.bare().c_str());
|
|
|
|
|
2010-07-10 14:27:32 -05:00
|
|
|
BMessage msg(IM_MESSAGE);
|
2021-05-24 01:47:21 -05:00
|
|
|
msg.AddString("user_id", from.bare().c_str());
|
|
|
|
msg.AddString("chat_id", from.bare().c_str());
|
2010-07-10 14:27:32 -05:00
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case gloox::ChatStateComposing:
|
2021-06-07 11:45:30 -05:00
|
|
|
msg.AddInt32("im_what", IM_USER_STARTED_TYPING);
|
2010-07-10 14:27:32 -05:00
|
|
|
break;
|
|
|
|
case gloox::ChatStatePaused:
|
2021-06-07 11:45:30 -05:00
|
|
|
msg.AddInt32("im_what", IM_USER_STOPPED_TYPING);
|
2010-07-10 14:27:32 -05:00
|
|
|
break;
|
|
|
|
case gloox::ChatStateGone:
|
|
|
|
// TODO
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
2010-07-10 14:27:32 -05:00
|
|
|
|
|
|
|
_SendMessage(&msg);
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-01 21:53:50 -05:00
|
|
|
void
|
|
|
|
JabberHandler::handleMUCParticipantPresence(gloox::MUCRoom *room,
|
|
|
|
const gloox::MUCRoomParticipant participant,
|
|
|
|
const gloox::Presence &presence)
|
|
|
|
{
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
// participant.flags, particpiant.role
|
|
|
|
// 0-0 (left), 0-* (joined/rolechange)
|
|
|
|
|
|
|
|
gloox::MUCRoomRole role = participant.role;
|
|
|
|
gloox::MUCRoomAffiliation aff = participant.affiliation;
|
|
|
|
|
2021-06-03 14:25:51 -05:00
|
|
|
const char* nick = participant.nick->resource().c_str();
|
2021-06-02 16:58:29 -05:00
|
|
|
|
2021-06-03 14:25:51 -05:00
|
|
|
BString user_id;
|
2021-06-03 20:24:34 -05:00
|
|
|
BString chat_id = _MUCChatId(room);
|
2021-06-03 14:25:51 -05:00
|
|
|
bool isSelf = _MUCUserId(chat_id, nick, &user_id);
|
2021-06-02 16:58:29 -05:00
|
|
|
|
2021-06-03 20:24:34 -05:00
|
|
|
if (chat_id.IsEmpty() == true || user_id.IsEmpty() == true)
|
|
|
|
return;
|
|
|
|
|
2021-06-03 14:25:51 -05:00
|
|
|
if (isSelf == true) {
|
2021-06-04 16:34:25 -05:00
|
|
|
int im_what = IM_ROOM_JOINED;
|
|
|
|
if (presence.presence() == 5)
|
|
|
|
im_what = IM_ROOM_LEFT;
|
|
|
|
|
2021-06-02 16:58:29 -05:00
|
|
|
BMessage joinedMsg(IM_MESSAGE);
|
2021-06-04 16:34:25 -05:00
|
|
|
joinedMsg.AddInt32("im_what", im_what);
|
2021-06-02 16:58:29 -05:00
|
|
|
joinedMsg.AddString("chat_id", chat_id);
|
|
|
|
_SendMessage(&joinedMsg);
|
2021-06-07 00:03:15 -05:00
|
|
|
_RoleChangedMsg(chat_id, user_id, role, aff);
|
2021-06-02 16:58:29 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-06-07 00:03:15 -05:00
|
|
|
_StatusSetMsg(user_id.String(), presence.presence(), presence.status().c_str(), "");
|
2021-06-02 16:58:29 -05:00
|
|
|
|
|
|
|
// If unavailable (disconnected/left chat)
|
|
|
|
if (presence.presence() == 5) {
|
2021-06-07 00:03:15 -05:00
|
|
|
_UserLeftMsg(chat_id, participant);
|
2021-06-02 16:58:29 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BMessage joinMsg(IM_MESSAGE);
|
2021-06-07 00:03:15 -05:00
|
|
|
joinMsg.AddInt32("im_what", IM_ROOM_PARTICIPANT_JOINED);
|
2021-06-02 16:58:29 -05:00
|
|
|
joinMsg.AddString("user_id", user_id);
|
|
|
|
joinMsg.AddString("user_name", nick);
|
|
|
|
joinMsg.AddString("chat_id", chat_id);
|
|
|
|
_SendMessage(&joinMsg);
|
Support for "Roles" (user, moderator, admin, etc.)
Add scaffodling support for arbitrary roles and permission-based (and
varying!) UI.
A new class, Role, represents a user's role in a given room, with three
values:
* The role's title
* The role's permission-set
* The role's priority
The permission set is a bitmask value for various permissions (e.g.,
PERM_WRITE, PERM_BAN, etc), and priority is position in the hierarchy.
A user with higher priority (and PERM_BAN) can ban a user with lower
priority, but not vice-versa. Two users with the same priority can't
ban/kick/mute each other, etc.
These permissions should be used to determine what UI elements are
displayed― if the user doesn't have permission to ban users, then a
"Ban" button shouldn't exist. If the user is muted, they shouldn't be
able to type. So on and so forth.
For now, permissions are sent with a IM_ROLECHANGE message and stored
by the Conversation, but aren't really in use yet.
This system should be flexible groundwork to account for the varying
administrative hierarchies and norms of different protocols.
2021-06-06 00:41:45 -05:00
|
|
|
|
2021-06-07 00:03:15 -05:00
|
|
|
_RoleChangedMsg(chat_id, user_id, role, aff);
|
2021-06-01 21:53:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2021-06-02 12:34:00 -05:00
|
|
|
JabberHandler::handleMUCMessage(gloox::MUCRoom *room, const gloox::Message &m,
|
2021-06-01 21:53:50 -05:00
|
|
|
bool priv)
|
|
|
|
{
|
2021-06-03 14:25:51 -05:00
|
|
|
BString user_id;
|
2021-06-03 20:24:34 -05:00
|
|
|
BString chat_id = _MUCChatId(room);
|
2021-06-03 14:25:51 -05:00
|
|
|
bool isSelf = _MUCUserId(chat_id, m.from().resource().c_str(), &user_id);
|
|
|
|
|
2021-06-03 20:24:34 -05:00
|
|
|
if (chat_id.IsEmpty() == true || user_id.IsEmpty() == true)
|
|
|
|
return;
|
|
|
|
|
2021-06-03 14:25:51 -05:00
|
|
|
int32 im_what = IM_MESSAGE_RECEIVED;
|
|
|
|
|
2021-06-02 12:34:00 -05:00
|
|
|
// We need a body
|
|
|
|
if (m.body() == "")
|
|
|
|
return;
|
|
|
|
|
2021-06-02 16:58:29 -05:00
|
|
|
|
2021-06-03 14:25:51 -05:00
|
|
|
// If sent from own user, then IM_MESSAGE_SENT
|
|
|
|
if (isSelf == true)
|
|
|
|
im_what = IM_MESSAGE_SENT;
|
2021-06-02 12:34:00 -05:00
|
|
|
|
2021-06-03 14:25:51 -05:00
|
|
|
// when() is only nonzero when sending backdated messages (logs)
|
|
|
|
if (m.when() != 0)
|
2021-06-03 20:24:34 -05:00
|
|
|
im_what = IM_LOGS_RECEIVED;
|
2021-06-02 16:58:29 -05:00
|
|
|
|
2021-06-02 12:34:00 -05:00
|
|
|
// Notify that a chat message was received
|
|
|
|
BMessage msg(IM_MESSAGE);
|
2021-06-02 16:58:29 -05:00
|
|
|
msg.AddInt32("im_what", im_what);
|
|
|
|
msg.AddString("user_id", user_id);
|
2021-06-02 12:34:00 -05:00
|
|
|
msg.AddString("chat_id", chat_id);
|
|
|
|
if (m.subject() != "")
|
|
|
|
msg.AddString("subject", m.subject().c_str());
|
|
|
|
msg.AddString("body", m.body().c_str());
|
|
|
|
_SendMessage(&msg);
|
2021-06-01 21:53:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2021-06-18 01:30:59 -05:00
|
|
|
JabberHandler::handleMUCRoomCreation(gloox::MUCRoom* room)
|
2021-06-01 21:53:50 -05:00
|
|
|
{
|
2021-06-18 01:30:59 -05:00
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddInt32("im_what", IM_ROOM_CREATED);
|
|
|
|
msg.AddString("chat_id", _MUCChatId(room));
|
|
|
|
_SendMessage(&msg);
|
2021-06-01 21:53:50 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleMUCSubject(gloox::MUCRoom *room, const std::string &nick,
|
|
|
|
const std::string &subject)
|
|
|
|
{
|
2021-06-04 13:57:04 -05:00
|
|
|
BString user_id;
|
|
|
|
BString chat_id = _MUCChatId(room);
|
|
|
|
bool isSelf = _MUCUserId(chat_id, nick.c_str(), &user_id);
|
|
|
|
|
|
|
|
if (chat_id.IsEmpty() == true)
|
|
|
|
return;
|
|
|
|
|
|
|
|
BMessage msg(IM_MESSAGE);
|
2021-06-07 11:45:30 -05:00
|
|
|
msg.AddInt32("im_what", IM_ROOM_SUBJECT_SET);
|
2021-06-04 13:57:04 -05:00
|
|
|
msg.AddString("subject", subject.c_str());
|
|
|
|
msg.AddString("chat_id", chat_id);
|
|
|
|
if (user_id.IsEmpty() == false)
|
|
|
|
msg.AddString("user_id", user_id);
|
|
|
|
_SendMessage(&msg);
|
2021-06-01 21:53:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleMUCInviteDecline(gloox::MUCRoom *room, const gloox::JID &invitee,
|
|
|
|
const std::string &reason)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleMUCError(gloox::MUCRoom *room, gloox::StanzaError error)
|
|
|
|
{
|
|
|
|
HandleStanzaError(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleMUCInfo(gloox::MUCRoom *room, int features,
|
|
|
|
const std::string &name, const gloox::DataForm *infoForm)
|
|
|
|
{
|
2021-06-13 01:16:30 -05:00
|
|
|
BString chat_id = _MUCChatId(room);
|
|
|
|
|
|
|
|
BMessage metadata(IM_MESSAGE);
|
|
|
|
metadata.AddInt32("im_what", IM_ROOM_METADATA);
|
|
|
|
metadata.AddString("chat_id", chat_id);
|
|
|
|
metadata.AddString("chat_name", name.c_str());
|
|
|
|
metadata.AddInt32("room_default_flags",
|
|
|
|
0 | ROOM_AUTOJOIN | ROOM_LOG_LOCALLY | ROOM_POPULATE_LOGS);
|
|
|
|
metadata.AddInt32("room_disallowed_flags", 0 | ROOM_AUTOCREATE);
|
|
|
|
_SendMessage(&metadata);
|
2021-06-01 21:53:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleMUCItems(gloox::MUCRoom *room, const gloox::Disco::ItemList &items)
|
|
|
|
{
|
2021-06-03 20:24:34 -05:00
|
|
|
BString chat_id = _MUCChatId(room);
|
2021-06-02 16:58:29 -05:00
|
|
|
BStringList nicks;
|
|
|
|
BStringList ids;
|
|
|
|
|
2021-06-03 20:24:34 -05:00
|
|
|
if (chat_id.IsEmpty() == true)
|
|
|
|
return;
|
2021-06-02 16:58:29 -05:00
|
|
|
|
|
|
|
for (auto item: items) {
|
|
|
|
BString nick = item->jid().resource().c_str();
|
|
|
|
nicks.Add(nick);
|
|
|
|
|
|
|
|
// Unless it's the user, derive ID from room resource
|
|
|
|
if (fNick != nick) {
|
|
|
|
BString user_id(chat_id);
|
|
|
|
user_id << "/" << nick;
|
|
|
|
ids.Add(user_id);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ids.Add(BString(fJid.bare().c_str()));
|
|
|
|
}
|
|
|
|
|
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddStrings("user_id", ids);
|
|
|
|
msg.AddStrings("user_name", nicks);
|
|
|
|
msg.AddString("chat_id", chat_id);
|
|
|
|
msg.AddInt32("im_what", IM_ROOM_PARTICIPANTS);
|
|
|
|
|
|
|
|
_SendMessage(&msg);
|
2021-06-01 21:53:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleMUCConfigList(gloox::MUCRoom* room, const gloox::MUCListItemList &items,
|
|
|
|
gloox::MUCOperation operation)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleMUCConfigForm(gloox::MUCRoom* room, const gloox::DataForm &form)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleMUCConfigResult(gloox::MUCRoom* room, bool success,
|
|
|
|
gloox::MUCOperation operation)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
JabberHandler::handleMUCRequest(gloox::MUCRoom* room, const gloox::DataForm &form)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-08 19:59:22 -05:00
|
|
|
|
|
|
|
|
2010-05-27 20:04:31 -05:00
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleItemAdded(const gloox::JID&)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleItemSubscribed(const gloox::JID&)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleItemUnsubscribed(const gloox::JID&)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleItemRemoved(const gloox::JID&)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleItemUpdated(const gloox::JID&)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleRosterPresence(const gloox::RosterItem& item,
|
2010-05-30 13:57:19 -05:00
|
|
|
const std::string& resource,
|
2010-05-27 20:04:31 -05:00
|
|
|
gloox::Presence::PresenceType type,
|
|
|
|
const std::string& presenceMsg)
|
|
|
|
{
|
2021-06-07 00:03:15 -05:00
|
|
|
_StatusSetMsg(item.jidJID().full().c_str(), type, presenceMsg.c_str(),
|
|
|
|
resource.c_str());
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleSelfPresence(const gloox::RosterItem& item, const std::string&,
|
2010-05-27 20:04:31 -05:00
|
|
|
gloox::Presence::PresenceType type,
|
|
|
|
const std::string& presenceMsg)
|
|
|
|
{
|
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddInt32("im_what", IM_OWN_CONTACT_INFO);
|
Allow multiple protocols per add-on
Now an add-on can contain multiple protocols, and the protocol API has
changed. An add-on must now export protocol_count() and protocol_at(),
with the latter replacing protocol(). protocol_count() returning the
amount of protocols in a given add-on, and protocol_at(i) giving a
new CayaProtocol* "at" the given index.
CayaProtocol has also been changed, adding Signature(),
FriendlySignature(), Icon(), Path(), and SetPath(). The reasoning is
that different protocols (even within a single add-on) will have
different signatures and icons, so this data should be accessible from
the protocol itself.
CayaProtocolAddOn now has CountProtocols() and ProtocolAt(i), allowing
the accessing of multiple protocols. A CayaProtocolAddOn can be given a
default protocol index in the constructor, whose protocol will be
returned with Protocol(). Version() was also moved from CayaProtocol to
CayaProtocolAddOn.
2021-05-21 13:33:43 -05:00
|
|
|
msg.AddString("protocol", Signature());
|
2021-05-24 01:47:21 -05:00
|
|
|
msg.AddString("user_id", item.jidJID().full().c_str());
|
2021-06-07 11:45:30 -05:00
|
|
|
msg.AddString("user_name", item.name().c_str());
|
2010-05-27 20:04:31 -05:00
|
|
|
msg.AddInt32("subscription", item.subscription());
|
2021-06-20 12:44:20 -05:00
|
|
|
msg.AddInt32("status", _GlooxStatusToApp(type));
|
2010-05-27 20:04:31 -05:00
|
|
|
msg.AddString("message", presenceMsg.c_str());
|
2010-05-30 15:50:04 -05:00
|
|
|
|
|
|
|
// Groups
|
|
|
|
gloox::StringList g = item.groups();
|
|
|
|
gloox::StringList::const_iterator it_g = g.begin();
|
|
|
|
for (; it_g != g.end(); ++it_g)
|
|
|
|
msg.AddString("group", (*it_g).c_str());
|
|
|
|
|
|
|
|
// Resources
|
|
|
|
gloox::RosterItem::ResourceMap::const_iterator rit
|
|
|
|
= item.resources().begin();
|
|
|
|
for (; rit != item.resources().end(); ++rit)
|
|
|
|
msg.AddString("resource", (*rit).first.c_str());
|
|
|
|
|
2010-05-30 07:30:47 -05:00
|
|
|
_SendMessage(&msg);
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleSubscriptionRequest(const gloox::JID&, const std::string&)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleUnsubscriptionRequest(const gloox::JID&, const std::string&)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleNonrosterPresence(const gloox::Presence&)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleRosterError(const gloox::IQ&)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleLog(gloox::LogLevel level, gloox::LogArea,
|
2010-05-27 20:04:31 -05:00
|
|
|
const std::string& msg)
|
|
|
|
{
|
|
|
|
if (level >= gloox::LogLevelWarning)
|
2021-07-18 20:03:42 -05:00
|
|
|
std::cout << msg << std::endl;
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleVCard(const gloox::JID& jid, const gloox::VCard* card)
|
2010-05-27 20:04:31 -05:00
|
|
|
{
|
|
|
|
if (!card)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gloox::VCard::Name name = card->name();
|
|
|
|
gloox::VCard::Photo photo = card->photo();
|
2021-06-19 22:03:02 -05:00
|
|
|
BString nick(card->nickname().c_str());
|
|
|
|
|
|
|
|
gloox::RosterItem* item = fClient->rosterManager()->getRosterItem(jid);
|
|
|
|
if (item != NULL)
|
|
|
|
nick = item->name().c_str();
|
2010-05-27 20:04:31 -05:00
|
|
|
|
|
|
|
std::string fullName = name.family + " " + name.given;
|
|
|
|
|
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
msg.AddInt32("im_what", IM_EXTENDED_CONTACT_INFO);
|
2021-05-24 01:47:21 -05:00
|
|
|
msg.AddString("user_id", jid.bare().c_str());
|
2021-06-19 22:03:02 -05:00
|
|
|
msg.AddString("user_name", nick);
|
2021-06-07 11:45:30 -05:00
|
|
|
msg.AddString("family_name", name.family.c_str());
|
|
|
|
msg.AddString("given_name", name.given.c_str());
|
|
|
|
msg.AddString("middle_name", name.middle.c_str());
|
2010-05-27 20:04:31 -05:00
|
|
|
msg.AddString("prefix", name.prefix.c_str());
|
|
|
|
msg.AddString("suffix", name.suffix.c_str());
|
2021-06-07 11:45:30 -05:00
|
|
|
msg.AddString("full_name", fullName.c_str());
|
2010-05-30 07:30:47 -05:00
|
|
|
_SendMessage(&msg);
|
2010-05-29 23:26:36 -05:00
|
|
|
|
|
|
|
// Return if there's no avatar icon
|
|
|
|
if (!photo.binval.c_str())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (_SetupAvatarCache() == B_OK)
|
2010-05-30 07:17:59 -05:00
|
|
|
// Cache avatar icon and notify the change
|
2010-05-29 23:26:36 -05:00
|
|
|
_CacheAvatar(jid.bare().c_str(), photo.binval.c_str(),
|
|
|
|
photo.binval.length());
|
2010-05-27 20:04:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-28 15:41:58 -05:00
|
|
|
JabberHandler::handleVCardResult(gloox::VCardHandler::VCardContext context,
|
2010-05-27 20:04:31 -05:00
|
|
|
const gloox::JID& jid,
|
|
|
|
gloox::StanzaError)
|
|
|
|
{
|
|
|
|
//if (context == gloox::VCardHandler::FetchVCard)
|
|
|
|
//else
|
|
|
|
}
|
2021-06-08 19:59:22 -05:00
|
|
|
|
|
|
|
|
2021-07-18 20:03:42 -05:00
|
|
|
OurClient::OurClient(const gloox::JID jid, const char* password)
|
|
|
|
:
|
|
|
|
gloox::Client(jid, password)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
OurClient::handleTag(gloox::Tag* tag)
|
|
|
|
{
|
|
|
|
if (DEBUG_ENABLED)
|
|
|
|
std::cerr << "Tag\t" << tag->xml() << std::endl;
|
|
|
|
gloox::Client::handleTag(tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-08 19:59:22 -05:00
|
|
|
InviteHandler::InviteHandler(gloox::ClientBase* client, JabberHandler* handler)
|
|
|
|
:
|
|
|
|
gloox::MUCInvitationHandler(client),
|
|
|
|
fHandler(handler)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
InviteHandler::handleMUCInvitation(const gloox::JID& room, const gloox::JID& from,
|
|
|
|
const std::string& reason, const std::string& body,
|
|
|
|
const std::string& password, bool cont,
|
|
|
|
const std::string& thread)
|
|
|
|
{
|
|
|
|
std::string chat_name = room.resource().c_str();
|
|
|
|
BString chat_id = room.full().c_str();
|
|
|
|
|
|
|
|
if (chat_name.empty() == true)
|
|
|
|
chat_name = chat_id.String();
|
|
|
|
if (password.empty() == false)
|
|
|
|
chat_id << "#" << password.c_str();
|
|
|
|
|
|
|
|
BMessage invite(IM_MESSAGE);
|
|
|
|
invite.AddInt32("im_what", IM_ROOM_INVITE_RECEIVED);
|
|
|
|
invite.AddString("chat_id", chat_id);
|
|
|
|
invite.AddString("chat_name", chat_name.c_str());
|
|
|
|
invite.AddString("user_id", from.bare().c_str());
|
|
|
|
if (reason.empty() == false)
|
|
|
|
invite.AddString("body", reason.c_str());
|
|
|
|
invite.AddString("protocol", fHandler->Signature());
|
|
|
|
|
|
|
|
fHandler->MessengerInterface()->SendMessage(new BMessage(invite));
|
|
|
|
}
|
|
|
|
|
|
|
|
|