2021-06-20 22:17:24 -05:00
|
|
|
|
/*
|
|
|
|
|
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
|
2021-08-16 21:52:28 -05:00
|
|
|
|
* Copyright 2017, Akshay Agarwal <agarwal.akshay.akshay8@gmail.com>
|
2021-06-20 22:17:24 -05:00
|
|
|
|
* All rights reserved. Distributed under the terms of the MIT license.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "IrcProtocol.h"
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
#include <iostream>
|
2021-06-20 22:17:24 -05:00
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
#include <Catalog.h>
|
2021-08-16 00:42:39 -05:00
|
|
|
|
#include <Directory.h>
|
|
|
|
|
#include <FindDirectory.h>
|
2021-08-12 20:16:22 -05:00
|
|
|
|
#include <Font.h>
|
2021-08-09 14:06:04 -05:00
|
|
|
|
#include <Resources.h>
|
|
|
|
|
#include <SecureSocket.h>
|
|
|
|
|
#include <Socket.h>
|
2021-06-21 01:54:42 -05:00
|
|
|
|
|
2021-08-11 17:40:03 -05:00
|
|
|
|
#include <libinterface/BitmapUtils.h>
|
|
|
|
|
|
2021-08-11 18:51:41 -05:00
|
|
|
|
#include <AppConstants.h>
|
2021-08-16 00:42:39 -05:00
|
|
|
|
#include <Cardie.h>
|
2021-06-21 01:54:42 -05:00
|
|
|
|
#include <ChatProtocolMessages.h>
|
2021-08-09 22:08:50 -05:00
|
|
|
|
#include <Flags.h>
|
2021-06-21 01:54:42 -05:00
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
|
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
|
#define B_TRANSLATION_CONTEXT "IrcProtocol"
|
2021-06-21 01:54:42 -05:00
|
|
|
|
|
2021-06-20 22:17:24 -05:00
|
|
|
|
|
2021-08-16 01:25:30 -05:00
|
|
|
|
const int32 IRC_CMD = 'ICmd';
|
|
|
|
|
|
|
|
|
|
|
2021-06-20 22:17:24 -05:00
|
|
|
|
status_t
|
|
|
|
|
connect_thread(void* data)
|
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
IrcProtocol* protocol = (IrcProtocol*)data;
|
2021-08-13 14:32:46 -05:00
|
|
|
|
protocol->Connect();
|
2021-08-09 14:06:04 -05:00
|
|
|
|
status_t status = protocol->Loop();
|
|
|
|
|
exit(status);
|
|
|
|
|
}
|
2021-06-20 22:17:24 -05:00
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
IrcProtocol::IrcProtocol()
|
|
|
|
|
:
|
|
|
|
|
fSocket(NULL),
|
|
|
|
|
fNick(NULL),
|
2021-08-09 19:03:37 -05:00
|
|
|
|
fIdent(NULL),
|
2021-08-10 12:53:20 -05:00
|
|
|
|
fReady(false),
|
|
|
|
|
fWriteLocked(false)
|
2021-08-09 14:06:04 -05:00
|
|
|
|
{
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
IrcProtocol::~IrcProtocol()
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
Shutdown();
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
IrcProtocol::Init(ChatProtocolMessengerInterface* interface)
|
|
|
|
|
{
|
|
|
|
|
fMessenger = interface;
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
IrcProtocol::Shutdown()
|
|
|
|
|
{
|
2021-08-16 00:42:39 -05:00
|
|
|
|
_SaveContacts();
|
|
|
|
|
|
2021-08-09 22:08:50 -05:00
|
|
|
|
BString cmd = "QUIT :";
|
2021-08-12 13:55:32 -05:00
|
|
|
|
cmd << fPartText;
|
2021-08-09 14:06:04 -05:00
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
|
|
|
|
|
kill_thread(fRecvThread);
|
2021-06-20 22:17:24 -05:00
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
2021-08-09 14:06:04 -05:00
|
|
|
|
IrcProtocol::UpdateSettings(BMessage* settings)
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
fNick = settings->FindString("nick");
|
|
|
|
|
fPartText = settings->GetString("part", "Cardie[0.1]: i've been liquified!");
|
2021-08-09 19:03:37 -05:00
|
|
|
|
fUser = settings->FindString("ident");
|
2021-08-13 14:32:46 -05:00
|
|
|
|
fRealName = settings->FindString("real_name");
|
|
|
|
|
fServer = settings->FindString("server");
|
|
|
|
|
fPassword = settings->FindString("password");
|
|
|
|
|
fPort = settings->FindInt32("port");
|
|
|
|
|
fSsl = settings->GetBool("ssl", false);
|
2021-08-09 14:06:04 -05:00
|
|
|
|
|
|
|
|
|
fRecvThread = spawn_thread(connect_thread, "what_a_tangled_web_we_weave",
|
2021-06-21 01:54:42 -05:00
|
|
|
|
B_NORMAL_PRIORITY, (void*)this);
|
2021-06-20 22:17:24 -05:00
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
if (fRecvThread < B_OK)
|
2021-06-20 22:17:24 -05:00
|
|
|
|
return B_ERROR;
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
status_t
|
|
|
|
|
IrcProtocol::Process(BMessage* msg)
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
int32 im_what = msg->FindInt32("im_what");
|
|
|
|
|
switch (im_what) {
|
2021-08-16 01:25:30 -05:00
|
|
|
|
case IRC_CMD:
|
|
|
|
|
{
|
|
|
|
|
BStringList words;
|
|
|
|
|
BString line = msg->GetString("misc_str", "");
|
|
|
|
|
line.Split(" ", true, words);
|
|
|
|
|
|
|
|
|
|
BString command = words.First();
|
|
|
|
|
if (command.ICompare("WHOIS") == 0)
|
|
|
|
|
fWhoIsRequested = true;
|
|
|
|
|
else if (command.ICompare("WHO") == 0)
|
|
|
|
|
fWhoRequested = true;
|
|
|
|
|
|
|
|
|
|
_SendIrc(line);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-13 14:32:46 -05:00
|
|
|
|
case IM_SET_OWN_STATUS:
|
|
|
|
|
{
|
|
|
|
|
int32 status = msg->FindInt32("status");
|
|
|
|
|
BString status_msg = msg->FindString("message");
|
|
|
|
|
|
|
|
|
|
BMessage statusSet(IM_MESSAGE);
|
|
|
|
|
statusSet.AddInt32("im_what", IM_OWN_STATUS_SET);
|
|
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
|
case STATUS_ONLINE:
|
|
|
|
|
statusSet.AddInt32("status", STATUS_ONLINE);
|
|
|
|
|
resume_thread(fRecvThread);
|
|
|
|
|
break;
|
|
|
|
|
case STATUS_OFFLINE:
|
|
|
|
|
statusSet.AddInt32("status", STATUS_OFFLINE);
|
|
|
|
|
Shutdown();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (status == STATUS_ONLINE || status == STATUS_OFFLINE)
|
|
|
|
|
_SendMsg(&statusSet);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-09 23:08:40 -05:00
|
|
|
|
case IM_SEND_MESSAGE:
|
|
|
|
|
{
|
|
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
|
BString body = msg->FindString("body");
|
|
|
|
|
if (chat_id.IsEmpty() == false || body.IsEmpty() == false) {
|
|
|
|
|
BStringList lines;
|
|
|
|
|
body.Split("\n", true, lines);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < lines.CountStrings(); i++) {
|
|
|
|
|
BString cmd = "PRIVMSG ";
|
2021-08-12 13:55:32 -05:00
|
|
|
|
cmd << chat_id << " :" << lines.StringAt(i);
|
2021-08-09 23:08:40 -05:00
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
|
|
|
|
|
BMessage sent(IM_MESSAGE);
|
|
|
|
|
sent.AddInt32("im_what", IM_MESSAGE_SENT);
|
|
|
|
|
sent.AddString("user_id", fIdent);
|
|
|
|
|
sent.AddString("chat_id", chat_id);
|
|
|
|
|
sent.AddString("body", lines.StringAt(i));
|
|
|
|
|
_SendMsg(&sent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-15 20:44:34 -05:00
|
|
|
|
case IM_CREATE_CHAT:
|
|
|
|
|
{
|
|
|
|
|
BString user_id;
|
|
|
|
|
if (msg->FindString("user_id", &user_id) != B_OK)
|
|
|
|
|
break;
|
|
|
|
|
BString user_name = _IdentNick(user_id);
|
|
|
|
|
|
|
|
|
|
if (user_name != user_id) {
|
|
|
|
|
BMessage created(IM_MESSAGE);
|
|
|
|
|
created.AddInt32("im_what", IM_CHAT_CREATED);
|
|
|
|
|
created.AddString("chat_id", user_name);
|
|
|
|
|
created.AddString("user_id", user_id);
|
|
|
|
|
_SendMsg(&created);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
fChannels.Add(user_name);
|
2021-08-15 20:44:34 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-15 21:54:24 -05:00
|
|
|
|
// If it's not a known user, we need to get their ID/nick somehow
|
|
|
|
|
// … that is, through the WHO.
|
2021-08-15 20:44:34 -05:00
|
|
|
|
fWhoIm = user_id;
|
2021-08-15 21:54:24 -05:00
|
|
|
|
BString cmd("WHOIS ");
|
2021-08-15 20:44:34 -05:00
|
|
|
|
cmd << user_id << "\n";
|
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
2021-08-09 14:06:04 -05:00
|
|
|
|
case IM_JOIN_ROOM:
|
2021-08-15 20:44:34 -05:00
|
|
|
|
case IM_CREATE_ROOM:
|
|
|
|
|
case IM_ROOM_INVITE_ACCEPT:
|
2021-08-09 14:06:04 -05:00
|
|
|
|
{
|
|
|
|
|
BString chat_id;
|
|
|
|
|
if (msg->FindString("chat_id", &chat_id) == B_OK) {
|
|
|
|
|
BString cmd = "JOIN ";
|
2021-08-12 13:55:32 -05:00
|
|
|
|
cmd << chat_id;
|
2021-08-09 14:06:04 -05:00
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-09 22:33:56 -05:00
|
|
|
|
case IM_LEAVE_ROOM:
|
|
|
|
|
{
|
|
|
|
|
BString chat_id;
|
|
|
|
|
if (msg->FindString("chat_id", &chat_id) == B_OK) {
|
2021-08-10 12:53:20 -05:00
|
|
|
|
if (_IsChannelName(chat_id) == true) {
|
|
|
|
|
BString cmd = "PART ";
|
2021-08-12 13:55:32 -05:00
|
|
|
|
cmd << chat_id << " * :" << fPartText;
|
2021-08-10 12:53:20 -05:00
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BMessage left(IM_MESSAGE);
|
|
|
|
|
left.AddInt32("im_what", IM_ROOM_LEFT);
|
|
|
|
|
left.AddString("chat_id", chat_id);
|
|
|
|
|
_SendMsg(&left);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
fChannels.Remove(chat_id);
|
2021-08-10 12:53:20 -05:00
|
|
|
|
}
|
2021-08-09 22:33:56 -05:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-09 22:08:50 -05:00
|
|
|
|
case IM_GET_ROOM_METADATA:
|
|
|
|
|
{
|
|
|
|
|
BString chat_id;
|
|
|
|
|
if (msg->FindString("chat_id", &chat_id) == B_OK) {
|
|
|
|
|
BMessage meta(IM_MESSAGE);
|
|
|
|
|
meta.AddInt32("im_what", IM_ROOM_METADATA);
|
|
|
|
|
meta.AddString("chat_id", chat_id);
|
|
|
|
|
meta.AddInt32("room_default_flags",
|
2021-08-10 12:53:20 -05:00
|
|
|
|
ROOM_LOG_LOCALLY | ROOM_POPULATE_LOGS);
|
2021-08-09 22:08:50 -05:00
|
|
|
|
_SendMsg(&meta);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-15 21:54:24 -05:00
|
|
|
|
case IM_GET_ROOM_PARTICIPANTS:
|
|
|
|
|
{
|
|
|
|
|
BString chat_id;
|
|
|
|
|
if (msg->FindString("chat_id", &chat_id) != B_OK)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// Rooms are populated with RPL_WHOREPLY, chats RPL_WHOISUSER
|
|
|
|
|
BString cmd;
|
|
|
|
|
if (_IsChannelName(chat_id) == true)
|
|
|
|
|
cmd = "WHO ";
|
|
|
|
|
else
|
|
|
|
|
cmd = "WHOIS ";
|
|
|
|
|
cmd << chat_id << "\n";
|
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-16 18:04:50 -05:00
|
|
|
|
case IM_ROOM_BAN_PARTICIPANT:
|
|
|
|
|
case IM_ROOM_KICK_PARTICIPANT:
|
|
|
|
|
{
|
|
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
|
BString user_id = msg->FindString("user_id");
|
|
|
|
|
BString body;
|
|
|
|
|
|
|
|
|
|
if (chat_id.IsEmpty() == true || user_id.IsEmpty() == true)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (im_what == IM_ROOM_BAN_PARTICIPANT) {
|
|
|
|
|
BString cmd("MODE ");
|
|
|
|
|
cmd << chat_id << " +b " << _IdentNick(user_id) << "!*@*";
|
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (msg->FindString("body", &body) != B_OK
|
|
|
|
|
&& im_what == IM_ROOM_BAN_PARTICIPANT)
|
|
|
|
|
body = B_TRANSLATE("You've been banned, nerd");
|
|
|
|
|
else if (body.IsEmpty() == true)
|
|
|
|
|
body = B_TRANSLATE("Watch the door on your way out");
|
|
|
|
|
|
|
|
|
|
BString cmd("KICK ");
|
|
|
|
|
cmd << chat_id << " " << _IdentNick(user_id);
|
|
|
|
|
cmd << " :" << body;
|
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-16 18:18:22 -05:00
|
|
|
|
case IM_ROOM_UNBAN_PARTICIPANT:
|
|
|
|
|
{
|
|
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
|
BString user_id = msg->FindString("user_id");
|
|
|
|
|
|
|
|
|
|
if (chat_id.IsEmpty() == false && user_id.IsEmpty() == false) {
|
|
|
|
|
BString cmd("MODE ");
|
|
|
|
|
cmd << chat_id << " -b " << _IdentNick(user_id) << "!*@*";
|
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-10 00:03:28 -05:00
|
|
|
|
case IM_ROOM_SEND_INVITE:
|
|
|
|
|
{
|
|
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
|
BString user_id = msg->FindString("user_id");
|
2021-08-16 18:04:50 -05:00
|
|
|
|
if (chat_id.IsEmpty() == false && user_id.IsEmpty() == false) {
|
2021-08-10 00:03:28 -05:00
|
|
|
|
BString cmd("INVITE ");
|
2021-08-12 13:55:32 -05:00
|
|
|
|
cmd << _IdentNick(user_id) << " " << chat_id;
|
2021-08-10 00:03:28 -05:00
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-10 10:54:06 -05:00
|
|
|
|
case IM_SET_OWN_NICKNAME:
|
|
|
|
|
{
|
|
|
|
|
BString user_name;
|
|
|
|
|
if (msg->FindString("user_name", &user_name) == B_OK) {
|
|
|
|
|
BString cmd("NICK ");
|
2021-08-12 13:55:32 -05:00
|
|
|
|
cmd << user_name;
|
2021-08-10 10:54:06 -05:00
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-16 00:42:39 -05:00
|
|
|
|
case IM_ROSTER_ADD_CONTACT:
|
|
|
|
|
{
|
|
|
|
|
BString user_nick;
|
|
|
|
|
if (msg->FindString("user_id", &user_nick) == B_OK)
|
|
|
|
|
_AddContact(user_nick);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_ROSTER_REMOVE_CONTACT:
|
|
|
|
|
{
|
|
|
|
|
BString user_id;
|
|
|
|
|
if (msg->FindString("user_id", &user_id) == B_OK)
|
|
|
|
|
_RemoveContact(_NickIdent(user_id));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_GET_CONTACT_INFO:
|
|
|
|
|
case IM_GET_EXTENDED_CONTACT_INFO:
|
|
|
|
|
{
|
|
|
|
|
BString user_id;
|
|
|
|
|
if (msg->FindString("user_id", &user_id) != B_OK)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
BMessage info(IM_MESSAGE);
|
|
|
|
|
if (im_what == IM_GET_CONTACT_INFO)
|
|
|
|
|
info.AddInt32("im_what", IM_CONTACT_INFO);
|
|
|
|
|
else
|
|
|
|
|
info.AddInt32("im_what", IM_EXTENDED_CONTACT_INFO);
|
|
|
|
|
info.AddString("user_id", user_id);
|
|
|
|
|
info.AddString("user_name", _IdentNick(user_id));
|
|
|
|
|
if (fOfflineContacts.HasString(_IdentNick(user_id)) == true)
|
|
|
|
|
info.AddInt32("status", (int32)STATUS_OFFLINE);
|
|
|
|
|
else
|
|
|
|
|
info.AddInt32("status", (int32)STATUS_ONLINE);
|
|
|
|
|
_SendMsg(&info);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-18 12:58:52 -05:00
|
|
|
|
case IM_SET_ROOM_SUBJECT:
|
|
|
|
|
{
|
|
|
|
|
BString chat_id;
|
|
|
|
|
BString body = msg->FindString("subject");
|
|
|
|
|
if (msg->FindString("chat_id", &chat_id) == B_OK) {
|
|
|
|
|
BString cmd("TOPIC ");
|
|
|
|
|
cmd << chat_id << " :" << body;
|
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-09 14:06:04 -05:00
|
|
|
|
default:
|
2021-08-11 18:51:41 -05:00
|
|
|
|
std::cout << "Unhandled message for IRC:\n";
|
2021-08-09 14:06:04 -05:00
|
|
|
|
msg->PrintToStream();
|
2021-08-09 23:08:40 -05:00
|
|
|
|
return B_ERROR;
|
2021-08-09 14:06:04 -05:00
|
|
|
|
}
|
2021-08-09 23:08:40 -05:00
|
|
|
|
return B_OK;
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BMessage
|
|
|
|
|
IrcProtocol::SettingsTemplate(const char* name)
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BMessage settings;
|
|
|
|
|
if (strcmp(name, "account") == 0)
|
|
|
|
|
settings = _AccountTemplate();
|
|
|
|
|
else if (strcmp(name, "join_room") == 0 || strcmp(name, "create_room") == 0)
|
|
|
|
|
settings = _RoomTemplate();
|
2021-08-16 00:42:39 -05:00
|
|
|
|
else if (strcmp(name, "roster") == 0)
|
|
|
|
|
settings = _RosterTemplate();
|
2021-08-09 14:06:04 -05:00
|
|
|
|
return settings;
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-16 01:25:30 -05:00
|
|
|
|
BObjectList<BMessage>
|
|
|
|
|
IrcProtocol::Commands()
|
|
|
|
|
{
|
|
|
|
|
BMessage handle(IM_MESSAGE);
|
|
|
|
|
handle.AddInt32("im_what", IRC_CMD);
|
|
|
|
|
handle.AddString("cmd_name", "/");
|
|
|
|
|
|
|
|
|
|
BMessage* cmd = new BMessage();
|
|
|
|
|
cmd->AddString("_name", "/");
|
|
|
|
|
cmd->AddString("_desc", B_TRANSLATE("Send a raw IRC command to the server. E.g., '// HELP' or '// WHOIS'."));
|
|
|
|
|
cmd->AddBool("_proto", true);
|
|
|
|
|
cmd->AddMessage("_msg", &handle);
|
|
|
|
|
cmd->AddString("class", "ChatCommand");
|
|
|
|
|
|
|
|
|
|
BObjectList<BMessage> cmds;
|
|
|
|
|
cmds.AddItem(cmd);
|
|
|
|
|
return cmds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-11 17:40:03 -05:00
|
|
|
|
BBitmap*
|
|
|
|
|
IrcProtocol::Icon() const
|
|
|
|
|
{
|
|
|
|
|
return ReadNodeIcon(fAddOnPath.Path(), B_LARGE_ICON, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-13 14:32:46 -05:00
|
|
|
|
status_t
|
|
|
|
|
IrcProtocol::Connect()
|
|
|
|
|
{
|
|
|
|
|
fSocket = fSsl ? new BSecureSocket : new BSocket;
|
|
|
|
|
|
|
|
|
|
if (fSocket->Connect(BNetworkAddress(fServer, fPort)) != B_OK)
|
|
|
|
|
return B_ERROR;
|
|
|
|
|
|
|
|
|
|
if (fPassword.IsEmpty() == false) {
|
|
|
|
|
BString passMsg = "PASS ";
|
|
|
|
|
passMsg << fPassword;
|
|
|
|
|
_SendIrc(passMsg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BString userMsg = "USER ";
|
|
|
|
|
userMsg << fUser << " * 0 :" << fRealName;
|
|
|
|
|
_SendIrc(userMsg);
|
|
|
|
|
|
|
|
|
|
BString nickMsg = "NICK ";
|
|
|
|
|
nickMsg << fNick;
|
|
|
|
|
_SendIrc(nickMsg);
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
status_t
|
|
|
|
|
IrcProtocol::Loop()
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-15 21:54:24 -05:00
|
|
|
|
fWhoIsRequested = false;
|
|
|
|
|
fWhoRequested = false;
|
2021-08-09 14:06:04 -05:00
|
|
|
|
while (fSocket != NULL && fSocket->IsConnected() == true)
|
|
|
|
|
_ProcessLine(_ReadUntilNewline(fSocket, &fRemainingBuf));
|
|
|
|
|
return B_OK;
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2021-08-09 14:06:04 -05:00
|
|
|
|
IrcProtocol::_ProcessLine(BString line)
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BStringList words;
|
2021-08-09 22:08:50 -05:00
|
|
|
|
line.RemoveCharsSet("\n\r");
|
2021-08-09 14:06:04 -05:00
|
|
|
|
line.Split(" ", true, words);
|
|
|
|
|
BString sender = _LineSender(words);
|
|
|
|
|
BString code = _LineCode(words);
|
2021-08-09 19:03:37 -05:00
|
|
|
|
BStringList params = _LineParameters(words, line);
|
2021-08-09 14:06:04 -05:00
|
|
|
|
|
|
|
|
|
int32 numeric;
|
|
|
|
|
if ((numeric = atoi(code.String())) > 0)
|
2021-08-12 10:14:46 -05:00
|
|
|
|
_ProcessNumeric(numeric, sender, params, line);
|
2021-08-09 14:06:04 -05:00
|
|
|
|
else
|
2021-08-12 10:14:46 -05:00
|
|
|
|
_ProcessCommand(code, sender, params, line);
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2021-08-12 10:14:46 -05:00
|
|
|
|
IrcProtocol::_ProcessNumeric(int32 numeric, BString sender, BStringList params,
|
|
|
|
|
BString line)
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-09 19:03:37 -05:00
|
|
|
|
if (numeric > 400) {
|
2021-08-12 10:14:46 -05:00
|
|
|
|
_ProcessNumericError(numeric, sender, params, line);
|
2021-08-09 19:03:37 -05:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-16 01:25:30 -05:00
|
|
|
|
// Act on the numeric as appropriate
|
2021-08-09 14:06:04 -05:00
|
|
|
|
switch (numeric) {
|
|
|
|
|
case RPL_WELCOME:
|
|
|
|
|
{
|
2021-08-11 20:47:40 -05:00
|
|
|
|
if (params.CountStrings() == 2)
|
|
|
|
|
fNick = params.First();
|
2021-08-15 21:54:24 -05:00
|
|
|
|
BString cmd("WHOIS ");
|
2021-08-09 19:03:37 -05:00
|
|
|
|
cmd << fNick << "\n";
|
|
|
|
|
_SendIrc(cmd);
|
2021-08-09 14:06:04 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-15 21:54:24 -05:00
|
|
|
|
case RPL_WHOISUSER:
|
2021-08-09 19:03:37 -05:00
|
|
|
|
{
|
2021-08-15 21:54:24 -05:00
|
|
|
|
BString nick = params.StringAt(1);
|
2021-08-09 19:03:37 -05:00
|
|
|
|
BString user = params.StringAt(2);
|
|
|
|
|
BString host = params.StringAt(3);
|
2021-08-09 22:08:50 -05:00
|
|
|
|
BString ident = user;
|
|
|
|
|
ident << "@" << host;
|
|
|
|
|
|
2021-08-15 21:54:24 -05:00
|
|
|
|
fIdentNicks.RemoveItemFor(ident);
|
|
|
|
|
fIdentNicks.AddItem(ident, nick);
|
|
|
|
|
|
2021-08-16 00:42:39 -05:00
|
|
|
|
// If is a contact, let's go!
|
|
|
|
|
_UpdateContact(nick, ident, true);
|
|
|
|
|
|
2021-08-15 21:54:24 -05:00
|
|
|
|
// Contains the own user's contact info― protocol ready!
|
2021-08-10 10:00:26 -05:00
|
|
|
|
if (fReady == false && nick == fNick) {
|
2021-08-09 19:03:37 -05:00
|
|
|
|
fUser = user.String();
|
2021-08-10 10:00:26 -05:00
|
|
|
|
_MakeReady(nick, ident);
|
2021-08-09 19:03:37 -05:00
|
|
|
|
}
|
2021-08-15 21:54:24 -05:00
|
|
|
|
// Used in the creation of a one-on-one chat
|
2021-08-15 20:44:34 -05:00
|
|
|
|
else if (fWhoIm == user || fWhoIm == nick) {
|
|
|
|
|
fWhoIm = "";
|
|
|
|
|
BMessage created(IM_MESSAGE);
|
|
|
|
|
created.AddInt32("im_what", IM_CHAT_CREATED);
|
|
|
|
|
created.AddString("chat_id", nick);
|
|
|
|
|
created.AddString("user_id", ident);
|
|
|
|
|
_SendMsg(&created);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
fChannels.Add(nick);
|
2021-08-15 20:44:34 -05:00
|
|
|
|
}
|
2021-08-15 21:54:24 -05:00
|
|
|
|
// Used to populate a one-on-one chat's userlist… lol, I know.
|
2021-08-16 00:42:39 -05:00
|
|
|
|
else if (fWhoIsRequested == false && fChannels.HasString(nick)) {
|
2021-08-15 21:54:24 -05:00
|
|
|
|
BMessage user(IM_MESSAGE);
|
|
|
|
|
user.AddInt32("im_what", IM_ROOM_PARTICIPANTS);
|
|
|
|
|
user.AddString("chat_id", nick);
|
|
|
|
|
user.AddString("user_id", ident);
|
|
|
|
|
user.AddString("user_name", nick);
|
|
|
|
|
_SendMsg(&user);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case RPL_WHOREPLY:
|
|
|
|
|
{
|
|
|
|
|
BString channel = params.StringAt(1);
|
|
|
|
|
BString user = params.StringAt(2);
|
|
|
|
|
BString host = params.StringAt(3);
|
|
|
|
|
BString nick = params.StringAt(5);
|
2021-08-16 16:11:37 -05:00
|
|
|
|
BString role = params.StringAt(6);
|
2021-08-15 21:54:24 -05:00
|
|
|
|
BString ident = user;
|
|
|
|
|
ident << "@" << host;
|
|
|
|
|
|
|
|
|
|
fIdentNicks.RemoveItemFor(ident);
|
|
|
|
|
fIdentNicks.AddItem(ident, nick);
|
|
|
|
|
|
|
|
|
|
// Used to populate a room's userlist (one-by-one… :p)
|
|
|
|
|
if (fWhoRequested == false && _IsChannelName(channel)) {
|
2021-08-16 16:11:37 -05:00
|
|
|
|
// Send the participant themself
|
2021-08-15 21:54:24 -05:00
|
|
|
|
BMessage user(IM_MESSAGE);
|
|
|
|
|
user.AddInt32("im_what", IM_ROOM_PARTICIPANTS);
|
|
|
|
|
user.AddString("chat_id", channel);
|
|
|
|
|
user.AddString("user_id", ident);
|
|
|
|
|
user.AddString("user_name", nick);
|
|
|
|
|
_SendMsg(&user);
|
2021-08-16 16:11:37 -05:00
|
|
|
|
|
|
|
|
|
// Now let's crunch the appropriate role…
|
|
|
|
|
bool away = false;
|
|
|
|
|
UserRole priority = ROOM_MEMBER;
|
|
|
|
|
for (int i=0; i < role.CountBytes(0, role.CountChars()); i++) {
|
|
|
|
|
char c = role.ByteAt(i);
|
|
|
|
|
switch (c) {
|
|
|
|
|
case 'G':
|
|
|
|
|
case 'H':
|
|
|
|
|
away = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'A':
|
|
|
|
|
away = true;
|
|
|
|
|
break;
|
|
|
|
|
case '%':
|
|
|
|
|
priority = ROOM_HALFOP;
|
|
|
|
|
break;
|
|
|
|
|
case '@':
|
|
|
|
|
priority = ROOM_OPERATOR;
|
|
|
|
|
break;
|
|
|
|
|
case '*':
|
|
|
|
|
priority = IRC_OPERATOR;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// And send the user's role
|
|
|
|
|
BMessage sensei(IM_MESSAGE);
|
|
|
|
|
sensei.AddInt32("im_what", IM_ROOM_ROLECHANGED);
|
|
|
|
|
sensei.AddString("chat_id", channel);
|
|
|
|
|
sensei.AddString("user_id", ident);
|
|
|
|
|
sensei.AddInt32("role_priority", priority);
|
|
|
|
|
sensei.AddString("role_title", _RoleTitle(priority));
|
|
|
|
|
sensei.AddInt32("role_perms", _RolePerms(priority));
|
|
|
|
|
_SendMsg(&sensei);
|
|
|
|
|
|
|
|
|
|
// Also status! Can't forget that
|
|
|
|
|
BMessage status(IM_MESSAGE);
|
|
|
|
|
status.AddInt32("im_what", IM_USER_STATUS_SET);
|
|
|
|
|
status.AddString("user_id", ident);
|
|
|
|
|
if (away == true)
|
|
|
|
|
status.AddInt32("status", STATUS_AWAY);
|
|
|
|
|
else
|
|
|
|
|
status.AddInt32("status", STATUS_ONLINE);
|
|
|
|
|
_SendMsg(&status);
|
2021-08-15 21:54:24 -05:00
|
|
|
|
}
|
2021-08-09 22:08:50 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case RPL_TOPIC:
|
|
|
|
|
{
|
|
|
|
|
BString chat_id = params.StringAt(1);
|
|
|
|
|
BString subject = params.Last();
|
|
|
|
|
|
|
|
|
|
BMessage topic(IM_MESSAGE);
|
|
|
|
|
topic.AddInt32("im_what", IM_ROOM_SUBJECT_SET);
|
|
|
|
|
topic.AddString("subject", subject);
|
|
|
|
|
topic.AddString("chat_id", chat_id);
|
|
|
|
|
_SendMsg(&topic);
|
2021-08-09 19:03:37 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-16 01:25:30 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now, to determine if the line should be sent to system buffer
|
|
|
|
|
switch (numeric) {
|
|
|
|
|
case RPL_ENDOFWHO:
|
|
|
|
|
fWhoRequested = false;
|
|
|
|
|
break;
|
|
|
|
|
case RPL_ENDOFWHOIS:
|
|
|
|
|
fWhoIsRequested = false;
|
|
|
|
|
break;
|
2021-08-09 19:03:37 -05:00
|
|
|
|
case RPL_MOTDSTART:
|
2021-08-09 14:06:04 -05:00
|
|
|
|
case RPL_MOTD:
|
2021-08-09 19:03:37 -05:00
|
|
|
|
case RPL_ENDOFMOTD:
|
2021-08-09 14:06:04 -05:00
|
|
|
|
{
|
2021-08-09 19:03:37 -05:00
|
|
|
|
BString body = params.Last();
|
|
|
|
|
if (numeric == RPL_MOTDSTART)
|
|
|
|
|
body = "――MOTD start――";
|
|
|
|
|
else if (numeric == RPL_ENDOFMOTD)
|
|
|
|
|
body = "――MOTD end――";
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BMessage send(IM_MESSAGE);
|
|
|
|
|
send.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
|
|
|
|
send.AddString("body", body);
|
|
|
|
|
_SendMsg(&send);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-16 01:25:30 -05:00
|
|
|
|
case RPL_WHOREPLY:
|
|
|
|
|
if (fWhoRequested == false)
|
|
|
|
|
break;
|
|
|
|
|
case RPL_WHOISUSER:
|
|
|
|
|
if (fWhoIsRequested == false)
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
BMessage send(IM_MESSAGE);
|
|
|
|
|
send.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
|
|
|
|
send.AddString("body", line);
|
|
|
|
|
_SendMsg(&send);
|
2021-08-09 19:03:37 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
IrcProtocol::_ProcessNumericError(int32 numeric, BString sender,
|
2021-08-12 10:14:46 -05:00
|
|
|
|
BStringList params, BString line)
|
2021-08-09 19:03:37 -05:00
|
|
|
|
{
|
|
|
|
|
switch (numeric) {
|
2021-08-09 14:06:04 -05:00
|
|
|
|
case ERR_NICKNAMEINUSE:
|
|
|
|
|
{
|
|
|
|
|
fNick << "_";
|
|
|
|
|
BString cmd("NICK ");
|
|
|
|
|
cmd << fNick << "\n";
|
|
|
|
|
_SendIrc(cmd);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-11 20:47:40 -05:00
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
BMessage err(IM_MESSAGE);
|
|
|
|
|
err.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
2021-08-12 10:14:46 -05:00
|
|
|
|
err.AddString("body", line);
|
2021-08-11 20:47:40 -05:00
|
|
|
|
_SendMsg(&err);
|
|
|
|
|
}
|
2021-08-09 14:06:04 -05:00
|
|
|
|
}
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
void
|
|
|
|
|
IrcProtocol::_ProcessCommand(BString command, BString sender,
|
2021-08-12 10:14:46 -05:00
|
|
|
|
BStringList params, BString line)
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-10 10:00:26 -05:00
|
|
|
|
// If protocol uninitialized and the user's ident is mentioned― use it!
|
|
|
|
|
if (fReady == false && _SenderNick(sender) == fNick)
|
|
|
|
|
_MakeReady(_SenderNick(sender), _SenderIdent(sender));
|
|
|
|
|
|
2021-08-10 12:53:20 -05:00
|
|
|
|
if (sender == "PING")
|
2021-08-09 19:03:37 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BString cmd = "PONG ";
|
2021-08-09 19:03:37 -05:00
|
|
|
|
cmd << params.Last() << "\n";
|
2021-08-09 14:06:04 -05:00
|
|
|
|
_SendIrc(cmd);
|
2021-08-09 19:03:37 -05:00
|
|
|
|
}
|
2021-08-09 23:08:40 -05:00
|
|
|
|
else if (command == "PRIVMSG")
|
|
|
|
|
{
|
|
|
|
|
BString chat_id = params.First();
|
|
|
|
|
BString user_id = _SenderIdent(sender);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
BString user_name = _SenderNick(sender);
|
2021-08-12 20:16:22 -05:00
|
|
|
|
BString body = params.Last();
|
2021-08-10 12:53:20 -05:00
|
|
|
|
if (_IsChannelName(chat_id) == false)
|
2021-08-09 23:08:40 -05:00
|
|
|
|
chat_id = _SenderNick(sender);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
if (fChannels.HasString(chat_id) == false)
|
|
|
|
|
fChannels.Add(chat_id);
|
|
|
|
|
|
|
|
|
|
_UpdateContact(user_name, user_id, true);
|
2021-08-09 23:08:40 -05:00
|
|
|
|
|
|
|
|
|
BMessage chat(IM_MESSAGE);
|
|
|
|
|
chat.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
|
|
|
|
chat.AddString("chat_id", chat_id);
|
|
|
|
|
chat.AddString("user_id", user_id);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
chat.AddString("user_name", user_name);
|
2021-08-12 20:16:22 -05:00
|
|
|
|
_AddFormatted(&chat, "body", body);
|
2021-08-09 23:08:40 -05:00
|
|
|
|
_SendMsg(&chat);
|
|
|
|
|
}
|
2021-08-09 19:03:37 -05:00
|
|
|
|
else if (command == "NOTICE")
|
|
|
|
|
{
|
|
|
|
|
BString chat_id = params.First();
|
|
|
|
|
BMessage send(IM_MESSAGE);
|
|
|
|
|
send.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
2021-08-15 20:34:30 -05:00
|
|
|
|
|
|
|
|
|
if (_IsChannelName(chat_id) == false)
|
|
|
|
|
chat_id = _SenderNick(sender);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
if (fChannels.HasString(chat_id) == false)
|
|
|
|
|
fChannels.Add(chat_id);
|
2021-08-15 20:34:30 -05:00
|
|
|
|
|
|
|
|
|
if (chat_id != "AUTH" || chat_id != "*")
|
2021-08-12 15:47:06 -05:00
|
|
|
|
send.AddString("chat_id", chat_id);
|
2021-08-15 20:34:30 -05:00
|
|
|
|
|
|
|
|
|
if (sender.IsEmpty() == false) {
|
|
|
|
|
send.AddString("user_id", _SenderIdent(sender));
|
|
|
|
|
send.AddString("user_name", _SenderNick(sender));
|
2021-08-12 15:47:06 -05:00
|
|
|
|
}
|
2021-08-09 19:03:37 -05:00
|
|
|
|
send.AddString("body", params.Last());
|
|
|
|
|
_SendMsg(&send);
|
2021-08-09 14:06:04 -05:00
|
|
|
|
}
|
2021-08-09 22:08:50 -05:00
|
|
|
|
else if (command == "TOPIC")
|
|
|
|
|
{
|
|
|
|
|
BString chat_id = params.First();
|
|
|
|
|
BString subject = params.Last();
|
|
|
|
|
|
|
|
|
|
BMessage topic(IM_MESSAGE);
|
|
|
|
|
topic.AddInt32("im_what", IM_ROOM_SUBJECT_SET);
|
|
|
|
|
topic.AddString("subject", subject);
|
|
|
|
|
topic.AddString("chat_id", chat_id);
|
|
|
|
|
_SendMsg(&topic);
|
|
|
|
|
}
|
|
|
|
|
else if (command == "JOIN")
|
|
|
|
|
{
|
|
|
|
|
BString chat_id = params.First();
|
2021-08-16 00:42:39 -05:00
|
|
|
|
BString user_id = _SenderIdent(sender);
|
|
|
|
|
BString user_name = _SenderNick(sender);
|
|
|
|
|
_UpdateContact(user_name, user_id, true);
|
2021-08-09 22:08:50 -05:00
|
|
|
|
|
|
|
|
|
BMessage joined(IM_MESSAGE);
|
|
|
|
|
joined.AddString("chat_id", chat_id);
|
|
|
|
|
if (_SenderIdent(sender) == fIdent) {
|
|
|
|
|
joined.AddInt32("im_what", IM_ROOM_JOINED);
|
2021-08-11 18:51:41 -05:00
|
|
|
|
fChannels.Add(chat_id);
|
2021-08-09 22:08:50 -05:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
joined.AddInt32("im_what", IM_ROOM_PARTICIPANT_JOINED);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
joined.AddString("user_id", user_id);
|
|
|
|
|
joined.AddString("user_name", user_name);
|
|
|
|
|
fIdentNicks.AddItem(user_id, user_name);
|
2021-08-09 22:08:50 -05:00
|
|
|
|
}
|
|
|
|
|
_SendMsg(&joined);
|
2021-08-16 16:11:37 -05:00
|
|
|
|
|
|
|
|
|
BMessage status(IM_MESSAGE);
|
|
|
|
|
status.AddInt32("im_what", IM_USER_STATUS_SET);
|
|
|
|
|
status.AddString("user_id", user_id);
|
|
|
|
|
status.AddInt32("status", STATUS_ONLINE);
|
|
|
|
|
_SendMsg(&status);
|
2021-08-09 22:08:50 -05:00
|
|
|
|
}
|
2021-08-11 18:51:41 -05:00
|
|
|
|
else if (command == "PART")
|
2021-08-09 22:33:56 -05:00
|
|
|
|
{
|
2021-08-11 18:51:41 -05:00
|
|
|
|
BString chat_id = params.First();
|
2021-08-09 22:33:56 -05:00
|
|
|
|
BString body = B_TRANSLATE("left: ");
|
|
|
|
|
body << params.Last();
|
|
|
|
|
|
|
|
|
|
BMessage left(IM_MESSAGE);
|
2021-08-11 18:51:41 -05:00
|
|
|
|
left.AddString("chat_id", chat_id);
|
2021-08-09 22:33:56 -05:00
|
|
|
|
left.AddString("body", body);
|
2021-08-11 18:51:41 -05:00
|
|
|
|
if (_SenderIdent(sender) == fIdent) {
|
2021-08-09 22:33:56 -05:00
|
|
|
|
left.AddInt32("im_what", IM_ROOM_LEFT);
|
2021-08-11 18:51:41 -05:00
|
|
|
|
fChannels.Remove(chat_id);
|
|
|
|
|
}
|
2021-08-09 22:33:56 -05:00
|
|
|
|
else {
|
|
|
|
|
left.AddInt32("im_what", IM_ROOM_PARTICIPANT_LEFT);
|
|
|
|
|
left.AddString("user_id", _SenderIdent(sender));
|
|
|
|
|
left.AddString("user_name", _SenderNick(sender));
|
|
|
|
|
}
|
|
|
|
|
_SendMsg(&left);
|
|
|
|
|
}
|
2021-08-16 18:04:50 -05:00
|
|
|
|
else if (command == "KICK")
|
|
|
|
|
{
|
|
|
|
|
BString chat_id = params.First();
|
|
|
|
|
BString user_id = params.StringAt(1);
|
|
|
|
|
|
|
|
|
|
BMessage foot(IM_MESSAGE);
|
|
|
|
|
foot.AddInt32("im_what", IM_ROOM_PARTICIPANT_KICKED);
|
|
|
|
|
foot.AddString("chat_id", chat_id);
|
2021-08-16 18:18:22 -05:00
|
|
|
|
foot.AddString("user_name", _IdentNick(user_id));
|
2021-08-16 18:04:50 -05:00
|
|
|
|
foot.AddString("user_id", _NickIdent(user_id));
|
|
|
|
|
if (params.CountStrings() == 3)
|
|
|
|
|
foot.AddString("body", params.StringAt(2));
|
|
|
|
|
_SendMsg(&foot);
|
|
|
|
|
}
|
2021-08-11 18:51:41 -05:00
|
|
|
|
else if (command == "QUIT")
|
|
|
|
|
{
|
2021-08-16 00:42:39 -05:00
|
|
|
|
BString user_id = _SenderIdent(sender);
|
|
|
|
|
BString user_name = _SenderNick(sender);
|
|
|
|
|
_UpdateContact(user_name, user_id, false);
|
|
|
|
|
|
2021-08-11 18:51:41 -05:00
|
|
|
|
BString body = B_TRANSLATE("quit: ");
|
|
|
|
|
body << params.Last();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < fChannels.CountStrings(); i++) {
|
2021-08-16 00:42:39 -05:00
|
|
|
|
if (_IsChannelName(fChannels.StringAt(i)) == false)
|
|
|
|
|
continue;
|
2021-08-11 18:51:41 -05:00
|
|
|
|
BMessage left(IM_MESSAGE);
|
|
|
|
|
left.AddInt32("im_what", IM_ROOM_PARTICIPANT_LEFT);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
left.AddString("user_id", user_id);
|
|
|
|
|
left.AddString("user_name", user_name);
|
2021-08-11 18:51:41 -05:00
|
|
|
|
left.AddString("chat_id", fChannels.StringAt(i));
|
|
|
|
|
_SendMsg(&left);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BMessage status(IM_MESSAGE);
|
|
|
|
|
status.AddInt32("im_what", IM_USER_STATUS_SET);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
status.AddString("user_id", user_id);
|
2021-08-11 18:51:41 -05:00
|
|
|
|
status.AddInt32("status", STATUS_OFFLINE);
|
|
|
|
|
_SendMsg(&status);
|
|
|
|
|
}
|
2021-08-10 00:03:28 -05:00
|
|
|
|
else if (command == "INVITE")
|
|
|
|
|
{
|
|
|
|
|
BMessage invite(IM_MESSAGE);
|
|
|
|
|
invite.AddInt32("im_what", IM_ROOM_INVITE_RECEIVED);
|
|
|
|
|
invite.AddString("chat_id", params.Last());
|
|
|
|
|
invite.AddString("user_id", _SenderIdent(sender));
|
|
|
|
|
_SendMsg(&invite);
|
|
|
|
|
}
|
2021-08-10 10:54:06 -05:00
|
|
|
|
else if (command == "NICK")
|
|
|
|
|
{
|
2021-08-10 12:53:20 -05:00
|
|
|
|
BString ident = _SenderIdent(sender);
|
|
|
|
|
BString user_name = params.Last();
|
|
|
|
|
|
2021-08-10 10:54:06 -05:00
|
|
|
|
BMessage nick(IM_MESSAGE);
|
2021-08-10 12:53:20 -05:00
|
|
|
|
nick.AddString("user_name", user_name);
|
|
|
|
|
if (ident == fIdent) {
|
2021-08-10 10:54:06 -05:00
|
|
|
|
nick.AddInt32("im_what", IM_OWN_NICKNAME_SET);
|
2021-08-10 12:53:20 -05:00
|
|
|
|
fNick = user_name;
|
2021-08-10 10:54:06 -05:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
nick.AddInt32("im_what", IM_USER_NICKNAME_SET);
|
2021-08-10 12:53:20 -05:00
|
|
|
|
nick.AddString("user_id", ident);
|
2021-08-16 00:42:39 -05:00
|
|
|
|
|
|
|
|
|
_RenameContact(ident, user_name);
|
2021-08-10 12:53:20 -05:00
|
|
|
|
fIdentNicks.RemoveItemFor(ident);
|
|
|
|
|
fIdentNicks.AddItem(ident, user_name);
|
2021-08-10 10:54:06 -05:00
|
|
|
|
}
|
|
|
|
|
_SendMsg(&nick);
|
|
|
|
|
}
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-10 10:00:26 -05:00
|
|
|
|
void
|
|
|
|
|
IrcProtocol::_MakeReady(BString nick, BString ident)
|
|
|
|
|
{
|
|
|
|
|
fNick = nick;
|
|
|
|
|
fIdent = ident;
|
|
|
|
|
|
|
|
|
|
fReady = true;
|
|
|
|
|
BMessage ready(IM_MESSAGE);
|
|
|
|
|
ready.AddInt32("im_what", IM_PROTOCOL_READY);
|
|
|
|
|
_SendMsg(&ready);
|
|
|
|
|
|
|
|
|
|
BMessage self(IM_MESSAGE);
|
|
|
|
|
self.AddInt32("im_what", IM_OWN_CONTACT_INFO);
|
|
|
|
|
self.AddString("user_id", fIdent);
|
|
|
|
|
self.AddString("user_name", fNick);
|
|
|
|
|
_SendMsg(&self);
|
|
|
|
|
|
|
|
|
|
_SendIrc("MOTD\n");
|
2021-08-16 00:42:39 -05:00
|
|
|
|
|
|
|
|
|
_LoadContacts();
|
2021-08-10 10:00:26 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BString
|
|
|
|
|
IrcProtocol::_LineSender(BStringList words)
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BString sender;
|
2021-08-15 20:34:30 -05:00
|
|
|
|
if (words.CountStrings() > 1) {
|
|
|
|
|
sender = words.First();
|
|
|
|
|
if (sender.StartsWith(":") == true)
|
|
|
|
|
sender.RemoveFirst(":");
|
|
|
|
|
else if (sender.StartsWith("*:") == true)
|
|
|
|
|
sender.RemoveFirst("*:");
|
|
|
|
|
}
|
2021-08-09 14:06:04 -05:00
|
|
|
|
return sender;
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BString
|
|
|
|
|
IrcProtocol::_LineCode(BStringList words)
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BString code;
|
|
|
|
|
if (words.CountStrings() > 2)
|
|
|
|
|
code = words.StringAt(1);
|
|
|
|
|
return code;
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BStringList
|
2021-08-09 19:03:37 -05:00
|
|
|
|
IrcProtocol::_LineParameters(BStringList words, BString line)
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BStringList params;
|
|
|
|
|
BString current;
|
|
|
|
|
for (int i = 2; i < words.CountStrings(); i++)
|
|
|
|
|
if ((current = words.StringAt(i)).StartsWith(":") == false)
|
|
|
|
|
params.Add(current);
|
|
|
|
|
else
|
2021-06-21 01:54:42 -05:00
|
|
|
|
break;
|
|
|
|
|
|
2021-08-09 19:03:37 -05:00
|
|
|
|
// Last parameter is preceded by a colon
|
2021-08-11 10:22:32 -05:00
|
|
|
|
int32 index = line.RemoveChars(0, 1).FindFirst(" :");
|
2021-08-09 14:06:04 -05:00
|
|
|
|
if (index != B_ERROR)
|
2021-08-11 10:22:32 -05:00
|
|
|
|
params.Add(line.RemoveChars(0, index + 2));
|
2021-08-09 19:03:37 -05:00
|
|
|
|
return params;
|
2021-06-21 01:54:42 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2021-08-09 14:06:04 -05:00
|
|
|
|
IrcProtocol::_SendMsg(BMessage* msg)
|
2021-06-21 01:54:42 -05:00
|
|
|
|
{
|
2021-08-09 19:03:37 -05:00
|
|
|
|
msg->AddString("protocol", Signature());
|
|
|
|
|
if (fReady == true)
|
|
|
|
|
fMessenger->SendMessage(msg);
|
2021-08-15 20:44:34 -05:00
|
|
|
|
else if (DEBUG_ENABLED == true) {
|
2021-08-11 18:51:41 -05:00
|
|
|
|
std::cout << "Tried sending message when not ready: \n";
|
2021-08-09 19:03:37 -05:00
|
|
|
|
msg->PrintToStream();
|
|
|
|
|
}
|
2021-06-21 01:54:42 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2021-08-09 14:06:04 -05:00
|
|
|
|
IrcProtocol::_SendIrc(BString cmd)
|
2021-06-21 01:54:42 -05:00
|
|
|
|
{
|
2021-08-12 13:55:32 -05:00
|
|
|
|
cmd << "\r\n";
|
2021-08-10 12:53:20 -05:00
|
|
|
|
if (fSocket != NULL && fSocket->IsConnected() == true) {
|
|
|
|
|
while (fWriteLocked == true)
|
|
|
|
|
snooze(1000);
|
|
|
|
|
fWriteLocked = true;
|
2021-08-12 13:55:32 -05:00
|
|
|
|
fSocket->Write(cmd.String(), cmd.CountBytes(0, cmd.CountChars()));
|
2021-08-10 12:53:20 -05:00
|
|
|
|
fWriteLocked = false;
|
|
|
|
|
}
|
2021-08-09 14:06:04 -05:00
|
|
|
|
else {
|
|
|
|
|
BMessage disable(IM_MESSAGE);
|
|
|
|
|
disable.AddInt32("im_what", IM_PROTOCOL_DISABLE);
|
|
|
|
|
}
|
2021-06-21 01:54:42 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 22:08:50 -05:00
|
|
|
|
BString
|
|
|
|
|
IrcProtocol::_SenderNick(BString sender)
|
|
|
|
|
{
|
|
|
|
|
BStringList split;
|
|
|
|
|
sender.Split("!", true, split);
|
|
|
|
|
return split.First();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BString
|
|
|
|
|
IrcProtocol::_SenderIdent(BString sender)
|
|
|
|
|
{
|
|
|
|
|
BStringList split;
|
|
|
|
|
sender.Split("!", true, split);
|
|
|
|
|
return split.Last();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-10 00:03:28 -05:00
|
|
|
|
BString
|
|
|
|
|
IrcProtocol::_IdentNick(BString ident)
|
|
|
|
|
{
|
|
|
|
|
bool found = false;
|
|
|
|
|
BString nick = fIdentNicks.ValueFor(ident, &found);
|
|
|
|
|
if (found == true)
|
|
|
|
|
return nick;
|
|
|
|
|
return ident;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-16 00:42:39 -05:00
|
|
|
|
BString
|
|
|
|
|
IrcProtocol::_NickIdent(BString nick)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < fIdentNicks.CountItems(); i++)
|
|
|
|
|
if (fIdentNicks.ValueAt(i) == nick)
|
|
|
|
|
return fIdentNicks.KeyAt(i);
|
|
|
|
|
return nick;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-10 12:53:20 -05:00
|
|
|
|
bool
|
|
|
|
|
IrcProtocol::_IsChannelName(BString name)
|
|
|
|
|
{
|
|
|
|
|
return (name.StartsWith("!") || name.StartsWith("&") || name.StartsWith("#")
|
|
|
|
|
|| name.StartsWith("+"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-13 13:00:32 -05:00
|
|
|
|
#define disable_all_faces(current) { \
|
2021-08-16 21:52:28 -05:00
|
|
|
|
if (bold > -1) _FormatToggleFace(msg, B_BOLD_FACE, &bold, current); \
|
|
|
|
|
if (italics > -1) _FormatToggleFace(msg, B_ITALIC_FACE, &italics, current); \
|
|
|
|
|
if (strike > -1) _FormatToggleFace(msg, B_STRIKEOUT_FACE, &strike, current); \
|
|
|
|
|
if (underline > -1) _FormatToggleFace(msg, B_UNDERSCORE_FACE, &underline, current); \
|
|
|
|
|
if (reverse > -1) _FormatToggleFace(msg, B_NEGATIVE_FACE, &reverse, current); \
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define disable_color(current) { \
|
|
|
|
|
if (colorStart > -1) { \
|
|
|
|
|
msg->AddInt32("color_start", colorStart); \
|
|
|
|
|
msg->AddInt32("color_length", current - colorStart); \
|
|
|
|
|
msg->AddColor("color", _IntToRgb(color)); \
|
|
|
|
|
colorStart = -1; \
|
|
|
|
|
color = -1; \
|
|
|
|
|
} \
|
2021-08-13 13:00:32 -05:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2021-08-12 20:16:22 -05:00
|
|
|
|
void
|
|
|
|
|
IrcProtocol::_AddFormatted(BMessage* msg, const char* name, BString text)
|
|
|
|
|
{
|
|
|
|
|
BString newText;
|
|
|
|
|
int32 italics = -1, bold = -1, underline = -1, strike = -1, mono = -1;
|
2021-08-16 21:52:28 -05:00
|
|
|
|
int32 reverse = -1;
|
|
|
|
|
int32 color = -1, colorStart = -1;
|
2021-08-12 20:16:22 -05:00
|
|
|
|
|
2021-08-13 13:00:32 -05:00
|
|
|
|
int32 length = text.CountBytes(0, text.CountChars());
|
|
|
|
|
for (int32 j=0, i=0; j < length; j++) {
|
2021-08-12 20:16:22 -05:00
|
|
|
|
char c = text.ByteAt(j);
|
|
|
|
|
|
|
|
|
|
switch (c) {
|
2021-08-16 21:52:28 -05:00
|
|
|
|
case FORMAT_COLOR:
|
|
|
|
|
{
|
|
|
|
|
// Apply and reset previous color, if existant
|
|
|
|
|
disable_color(i);
|
|
|
|
|
|
|
|
|
|
char one = text.ByteAt(j + 1);
|
|
|
|
|
char two = text.ByteAt(j + 2);
|
|
|
|
|
|
|
|
|
|
// Try and get colors from either two-digits or one-digits
|
|
|
|
|
int32 colorIndex = -1;
|
|
|
|
|
if (isdigit(one) == true && isdigit(two) == true) {
|
|
|
|
|
char num[3] = { one, two, '\0' };
|
|
|
|
|
colorIndex = atoi(num);
|
|
|
|
|
if (colorIndex >= 0 && colorIndex <= 99)
|
|
|
|
|
j += 2;
|
|
|
|
|
}
|
|
|
|
|
else if (isdigit(one) == true) {
|
|
|
|
|
char num[2] = { one, '\0' };
|
|
|
|
|
colorIndex = atoi(num);
|
|
|
|
|
if (colorIndex >= 0 && colorIndex <= 99)
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// Use color if valid
|
|
|
|
|
if (colorIndex >= 0 && colorIndex <= 99) {
|
|
|
|
|
int colors[FORMAT_COLOR_COUNT] = FORMAT_COLORS;
|
|
|
|
|
color = colors[colorIndex];
|
|
|
|
|
colorStart = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ignore setting of background
|
|
|
|
|
if (text.ByteAt(j + 1) == ',')
|
|
|
|
|
if (isdigit(text.ByteAt(j+2)) && isdigit(text.ByteAt(j+3)))
|
|
|
|
|
j += 3;
|
|
|
|
|
else if (isdigit(text.ByteAt(j + 2)))
|
|
|
|
|
j += 2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case FORMAT_BOLD:
|
|
|
|
|
_FormatToggleFace(msg, B_BOLD_FACE, &bold, i);
|
|
|
|
|
break;
|
|
|
|
|
case FORMAT_ITALIC:
|
|
|
|
|
_FormatToggleFace(msg, B_ITALIC_FACE, &italics, i);
|
2021-08-12 20:16:22 -05:00
|
|
|
|
break;
|
2021-08-16 21:52:28 -05:00
|
|
|
|
case FORMAT_UNDERSCORE:
|
|
|
|
|
_FormatToggleFace(msg, B_UNDERSCORE_FACE, &underline, i);
|
2021-08-12 20:16:22 -05:00
|
|
|
|
break;
|
2021-08-16 21:52:28 -05:00
|
|
|
|
case FORMAT_STRIKEOUT:
|
|
|
|
|
_FormatToggleFace(msg, B_STRIKEOUT_FACE, &strike, i);
|
2021-08-12 20:16:22 -05:00
|
|
|
|
break;
|
2021-08-16 21:52:28 -05:00
|
|
|
|
case FORMAT_REVERSE:
|
|
|
|
|
_FormatToggleFace(msg, B_NEGATIVE_FACE, &reverse, i);
|
2021-08-12 20:16:22 -05:00
|
|
|
|
break;
|
2021-08-16 21:52:28 -05:00
|
|
|
|
case FORMAT_RESET:
|
2021-08-13 13:00:32 -05:00
|
|
|
|
disable_all_faces(i);
|
2021-08-16 21:52:28 -05:00
|
|
|
|
disable_color(i);
|
2021-08-12 20:16:22 -05:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
newText << c;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-13 13:00:32 -05:00
|
|
|
|
disable_all_faces(length);
|
2021-08-16 21:52:28 -05:00
|
|
|
|
disable_color(length);
|
2021-08-12 20:16:22 -05:00
|
|
|
|
msg->AddString(name, newText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2021-08-16 21:52:28 -05:00
|
|
|
|
IrcProtocol::_FormatToggleFace(BMessage* msg, uint16 face, int32* start,
|
2021-08-12 20:16:22 -05:00
|
|
|
|
int32 current)
|
|
|
|
|
{
|
|
|
|
|
if (*start == -1)
|
|
|
|
|
*start = current;
|
|
|
|
|
else {
|
|
|
|
|
msg->AddInt32("face_start", *start);
|
|
|
|
|
msg->AddInt32("face_length", current - *start);
|
2021-08-13 13:00:32 -05:00
|
|
|
|
msg->AddUInt16("face", face);
|
2021-08-12 20:16:22 -05:00
|
|
|
|
*start = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-16 00:42:39 -05:00
|
|
|
|
void
|
|
|
|
|
IrcProtocol::_UpdateContact(BString nick, BString ident, bool online)
|
|
|
|
|
{
|
|
|
|
|
if (fContacts.HasString(nick) == false)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (online == true && fOfflineContacts.HasString(nick) == true) {
|
|
|
|
|
_RemoveContact(nick);
|
|
|
|
|
_AddContact(ident);
|
|
|
|
|
fOfflineContacts.Remove(nick);
|
|
|
|
|
}
|
|
|
|
|
else if (online == false && fOfflineContacts.HasString(nick) == false) {
|
|
|
|
|
fOfflineContacts.Add(nick);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
IrcProtocol::_AddContact(BString nick)
|
|
|
|
|
{
|
|
|
|
|
fContacts.Add(nick);
|
|
|
|
|
BString user_id = _NickIdent(nick);
|
|
|
|
|
|
|
|
|
|
BMessage added(IM_MESSAGE);
|
|
|
|
|
added.AddInt32("im_what", IM_ROSTER);
|
|
|
|
|
added.AddString("user_id", user_id);
|
|
|
|
|
_SendMsg(&added);
|
|
|
|
|
|
|
|
|
|
if (user_id == nick)
|
|
|
|
|
fOfflineContacts.Add(nick);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
IrcProtocol::_RemoveContact(BString user_id)
|
|
|
|
|
{
|
|
|
|
|
BString nick = _IdentNick(user_id);
|
|
|
|
|
fContacts.Remove(nick);
|
|
|
|
|
fOfflineContacts.Remove(nick);
|
|
|
|
|
|
|
|
|
|
BMessage removed(IM_MESSAGE);
|
|
|
|
|
removed.AddInt32("im_what", IM_ROSTER_CONTACT_REMOVED);
|
|
|
|
|
removed.AddString("user_id", _NickIdent(user_id));
|
|
|
|
|
_SendMsg(&removed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
IrcProtocol::_RenameContact(BString user_id, BString newNick)
|
|
|
|
|
{
|
|
|
|
|
BString oldNick = _IdentNick(user_id);
|
|
|
|
|
|
|
|
|
|
if (fContacts.HasString(oldNick) == true) {
|
|
|
|
|
fContacts.Remove(_IdentNick(user_id));
|
|
|
|
|
fOfflineContacts.Remove(_IdentNick(user_id));
|
|
|
|
|
fContacts.Add(newNick);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
IrcProtocol::_LoadContacts()
|
|
|
|
|
{
|
|
|
|
|
BMessage contacts;
|
|
|
|
|
BFile file(_ContactsCache(), B_READ_ONLY);
|
|
|
|
|
if (file.InitCheck() == B_OK)
|
|
|
|
|
contacts.Unflatten(&file);
|
|
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
BString user_name;
|
|
|
|
|
while (contacts.FindString("user_name", i, &user_name) == B_OK) {
|
|
|
|
|
_AddContact(user_name);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
IrcProtocol::_SaveContacts()
|
|
|
|
|
{
|
|
|
|
|
BMessage contacts;
|
|
|
|
|
for (int i = 0; i < fContacts.CountStrings(); i++)
|
|
|
|
|
contacts.AddString("user_name", fContacts.StringAt(i));
|
|
|
|
|
|
|
|
|
|
BFile file(_ContactsCache(), B_WRITE_ONLY | B_CREATE_FILE);
|
|
|
|
|
if (file.InitCheck() == B_OK)
|
|
|
|
|
contacts.Flatten(&file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-16 16:11:37 -05:00
|
|
|
|
int32
|
|
|
|
|
IrcProtocol::_RolePerms(UserRole role)
|
|
|
|
|
{
|
|
|
|
|
switch (role) {
|
|
|
|
|
case ROOM_HALFOP:
|
|
|
|
|
return PERM_READ | PERM_WRITE | PERM_NICK | PERM_KICK
|
|
|
|
|
| PERM_ROOM_SUBJECT;
|
|
|
|
|
case IRC_OPERATOR:
|
|
|
|
|
case ROOM_OPERATOR:
|
|
|
|
|
return PERM_READ | PERM_WRITE | PERM_NICK | PERM_KICK | PERM_BAN
|
|
|
|
|
| PERM_ROOM_SUBJECT | PERM_ROLECHANGE;
|
|
|
|
|
}
|
|
|
|
|
return PERM_READ | PERM_WRITE | PERM_NICK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char*
|
|
|
|
|
IrcProtocol::_RoleTitle(UserRole role)
|
|
|
|
|
{
|
|
|
|
|
switch (role) {
|
|
|
|
|
case ROOM_HALFOP:
|
|
|
|
|
return B_TRANSLATE("Half-Op");
|
|
|
|
|
case ROOM_OPERATOR:
|
|
|
|
|
return B_TRANSLATE("Operator");
|
|
|
|
|
case IRC_OPERATOR:
|
|
|
|
|
return B_TRANSLATE("IRC Wizard");
|
|
|
|
|
}
|
|
|
|
|
return B_TRANSLATE("Member");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-16 00:42:39 -05:00
|
|
|
|
const char*
|
|
|
|
|
IrcProtocol::_CachePath()
|
|
|
|
|
{
|
|
|
|
|
BPath path;
|
|
|
|
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
|
|
|
|
|
return NULL;
|
|
|
|
|
path.Append(APP_NAME "/Cache/Accounts");
|
|
|
|
|
path.Append(fName);
|
|
|
|
|
if (create_directory(path.Path(), 0755) != B_OK)
|
|
|
|
|
return NULL;
|
|
|
|
|
return path.Path();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char*
|
|
|
|
|
IrcProtocol::_ContactsCache()
|
|
|
|
|
{
|
|
|
|
|
BPath path(_CachePath());
|
|
|
|
|
path.Append("contact_list");
|
|
|
|
|
return path.Path();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BString
|
|
|
|
|
IrcProtocol::_ReadUntilNewline(BDataIO* io, BString* extraBuffer)
|
2021-06-21 01:54:42 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BString total;
|
|
|
|
|
char buf[1024] = { '\0' };
|
|
|
|
|
|
|
|
|
|
// Use buffer from last read if any text remains
|
|
|
|
|
if (extraBuffer->IsEmpty() == false) {
|
|
|
|
|
BString trimRet = _TrimStringToNewline(extraBuffer);
|
|
|
|
|
if (trimRet.IsEmpty() == true)
|
|
|
|
|
total << extraBuffer;
|
|
|
|
|
else
|
|
|
|
|
return trimRet;
|
|
|
|
|
}
|
2021-06-21 01:54:42 -05:00
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
while (!(strstr(buf, "\n"))) {
|
|
|
|
|
io->Read(buf, 1023);
|
2021-08-12 10:14:46 -05:00
|
|
|
|
total << buf;
|
2021-08-11 18:51:41 -05:00
|
|
|
|
if (DEBUG_ENABLED)
|
2021-08-12 10:14:46 -05:00
|
|
|
|
std::cerr << buf << std::endl;
|
2021-06-21 01:54:42 -05:00
|
|
|
|
}
|
2021-08-09 14:06:04 -05:00
|
|
|
|
|
|
|
|
|
BString currentLine = _TrimStringToNewline(&total);
|
|
|
|
|
extraBuffer->SetTo(total);
|
|
|
|
|
return currentLine;
|
2021-06-21 01:54:42 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BString
|
2021-08-09 14:06:04 -05:00
|
|
|
|
IrcProtocol::_TrimStringToNewline(BString* str)
|
2021-06-21 01:54:42 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BString line;
|
|
|
|
|
int32 lineEnd = str->FindFirst('\n');
|
2021-06-21 01:54:42 -05:00
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
if (lineEnd != B_ERROR) {
|
|
|
|
|
str->CopyCharsInto(line, 0, lineEnd + 1);
|
|
|
|
|
str->RemoveChars(0, lineEnd + 1);
|
|
|
|
|
}
|
|
|
|
|
return line;
|
2021-06-21 01:54:42 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-16 21:52:28 -05:00
|
|
|
|
rgb_color
|
|
|
|
|
IrcProtocol::_IntToRgb(int rgb)
|
|
|
|
|
{
|
|
|
|
|
uint8 r = rgb >> 16;
|
|
|
|
|
uint8 g = rgb >> 8 & 0xFF;
|
|
|
|
|
uint8 b = rgb & 0xFF;
|
|
|
|
|
return (rgb_color){r, g, b};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BMessage
|
|
|
|
|
IrcProtocol::_AccountTemplate()
|
2021-06-21 01:54:42 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BMessage settings;
|
|
|
|
|
|
|
|
|
|
BMessage server;
|
|
|
|
|
server.AddString("name", "server");
|
|
|
|
|
server.AddString("description", B_TRANSLATE("Server:"));
|
|
|
|
|
server.AddString("default", "irc.oftc.net");
|
|
|
|
|
server.AddString("error", B_TRANSLATE("Please enter a valid server address."));
|
|
|
|
|
server.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
settings.AddMessage("setting", &server);
|
|
|
|
|
|
|
|
|
|
BMessage port;
|
|
|
|
|
port.AddString("name", "port");
|
|
|
|
|
port.AddString("description", B_TRANSLATE("Port:"));
|
|
|
|
|
port.AddInt32("default", 6697);
|
|
|
|
|
port.AddString("error", B_TRANSLATE("We need a port-number to know which door to knock on! Likely 6667/6697."));
|
|
|
|
|
port.AddInt32("type", B_INT32_TYPE);
|
|
|
|
|
settings.AddMessage("setting", &port);
|
|
|
|
|
|
|
|
|
|
BMessage ssl;
|
|
|
|
|
ssl.AddString("name", "ssl");
|
2021-08-10 10:54:06 -05:00
|
|
|
|
ssl.AddString("description", B_TRANSLATE("SSL"));
|
2021-08-09 14:06:04 -05:00
|
|
|
|
ssl.AddBool("default", true);
|
|
|
|
|
ssl.AddInt32("type", B_BOOL_TYPE);
|
|
|
|
|
settings.AddMessage("setting", &ssl);
|
|
|
|
|
|
|
|
|
|
BMessage nick;
|
|
|
|
|
nick.AddString("name", "nick");
|
|
|
|
|
nick.AddString("description", B_TRANSLATE("Nickname:"));
|
|
|
|
|
nick.AddString("default", "Haikunaut");
|
|
|
|
|
nick.AddString("error", B_TRANSLATE("You need a default nickname― The Nameless are not welcome on IRC."));
|
|
|
|
|
nick.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
settings.AddMessage("setting", &nick);
|
|
|
|
|
|
|
|
|
|
BMessage ident;
|
|
|
|
|
ident.AddString("name", "ident");
|
2021-08-09 19:03:37 -05:00
|
|
|
|
ident.AddString("description", B_TRANSLATE("Username:"));
|
2021-08-09 14:06:04 -05:00
|
|
|
|
ident.AddString("error", B_TRANSLATE("You need a username in order to connect!"));
|
|
|
|
|
ident.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
settings.AddMessage("setting", &ident);
|
|
|
|
|
|
|
|
|
|
BMessage password;
|
|
|
|
|
password.AddString("name", "password");
|
|
|
|
|
password.AddString("description", B_TRANSLATE("Password:"));
|
|
|
|
|
password.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
settings.AddMessage("setting", &password);
|
|
|
|
|
|
|
|
|
|
BMessage realName;
|
|
|
|
|
realName.AddString("name", "real_name");
|
|
|
|
|
realName.AddString("description", B_TRANSLATE("Real name:"));
|
|
|
|
|
realName.AddInt32("type", B_STRING_TYPE);
|
2021-08-18 15:30:20 -05:00
|
|
|
|
realName.AddString("default", "Gord the Destroyer");
|
|
|
|
|
realName.AddString("error", B_TRANSLATE("A real name must be defined. (P.S.: You can lie!)"));
|
2021-08-09 14:06:04 -05:00
|
|
|
|
settings.AddMessage("setting", &realName);
|
|
|
|
|
|
|
|
|
|
BMessage part;
|
|
|
|
|
part.AddString("name", "part");
|
|
|
|
|
part.AddString("description", B_TRANSLATE("Part message:"));
|
|
|
|
|
part.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
part.AddString("default", "Cardie[0.1]: i've been liquified!");
|
|
|
|
|
settings.AddMessage("setting", &part);
|
|
|
|
|
|
|
|
|
|
return settings;
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BMessage
|
|
|
|
|
IrcProtocol::_RoomTemplate()
|
2021-06-20 22:17:24 -05:00
|
|
|
|
{
|
2021-08-09 14:06:04 -05:00
|
|
|
|
BMessage settings;
|
|
|
|
|
|
|
|
|
|
BMessage id;
|
|
|
|
|
id.AddString("name", "chat_id");
|
|
|
|
|
id.AddString("description", B_TRANSLATE("Channel:"));
|
|
|
|
|
id.AddString("error", B_TRANSLATE("Please enter a channel― skipping it doesn't make sense!"));
|
|
|
|
|
id.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
settings.AddMessage("setting", &id);
|
|
|
|
|
|
|
|
|
|
return settings;
|
2021-06-20 22:17:24 -05:00
|
|
|
|
}
|
2021-08-16 00:42:39 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BMessage
|
|
|
|
|
IrcProtocol::_RosterTemplate()
|
|
|
|
|
{
|
|
|
|
|
BMessage settings;
|
|
|
|
|
|
|
|
|
|
BMessage nick;
|
|
|
|
|
nick.AddString("name", "user_id");
|
|
|
|
|
nick.AddString("description", B_TRANSLATE("Nick:"));
|
|
|
|
|
nick.AddString("error", B_TRANSLATE("How can someone be your friend if you don't know their name?"));
|
|
|
|
|
nick.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
settings.AddMessage("setting", &nick);
|
|
|
|
|
|
|
|
|
|
return settings;
|
|
|
|
|
}
|