(irc) Start add-on rewrite
The IRC add-on previously used libircclient, which is becoming inactive, and newer versions don't compile on Haiku easily. A fresh rewrite seems to be a better option. So far it only supports basic connection and receiving the MOTD. :p
This commit is contained in:
parent
9267c740a4
commit
c202ef33ac
|
@ -5,85 +5,46 @@
|
||||||
|
|
||||||
#include "IrcProtocol.h"
|
#include "IrcProtocol.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <iostream>
|
||||||
|
|
||||||
#include <StringList.h>
|
#include <Catalog.h>
|
||||||
|
#include <Resources.h>
|
||||||
|
#include <SecureSocket.h>
|
||||||
|
#include <Socket.h>
|
||||||
|
|
||||||
#include <ChatProtocolMessages.h>
|
#include <ChatProtocolMessages.h>
|
||||||
|
|
||||||
|
#include "Numerics.h"
|
||||||
|
|
||||||
IrcProtocol* current_proto;
|
|
||||||
|
#undef B_TRANSLATION_CONTEXT
|
||||||
|
#define B_TRANSLATION_CONTEXT "IrcProtocol"
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
connect_thread(void* data)
|
connect_thread(void* data)
|
||||||
{
|
{
|
||||||
IrcProtocol* proto = (IrcProtocol*)data;
|
IrcProtocol* protocol = (IrcProtocol*)data;
|
||||||
current_proto = proto;
|
status_t status = protocol->Loop();
|
||||||
|
exit(status);
|
||||||
BMessage* settings = proto->fSettings;
|
|
||||||
if (!settings)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
const char* nick = settings->FindString("nick");
|
|
||||||
const char* ident = settings->FindString("ident");
|
|
||||||
const char* real_name = settings->FindString("real_name");
|
|
||||||
const char* server = settings->FindString("server");
|
|
||||||
const char* password = settings->FindString("password");
|
|
||||||
int32 port = settings->FindInt32("port");
|
|
||||||
bool ssl = false;
|
|
||||||
|
|
||||||
if (!nick || !ident || !server)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
// libircclient wants a "#" in front of SSL addresses
|
|
||||||
BString joinServer;
|
|
||||||
if (ssl == true)
|
|
||||||
joinServer << "#";
|
|
||||||
joinServer << server;
|
|
||||||
|
|
||||||
// Now create the session
|
|
||||||
irc_callbacks_t callbacks = get_callbacks();
|
|
||||||
irc_session_t* session = irc_create_session(&callbacks);
|
|
||||||
proto->fSession = session;
|
|
||||||
|
|
||||||
irc_ctx_t ctx;
|
|
||||||
ctx.nick.SetTo(nick);
|
|
||||||
irc_set_ctx(session, &ctx);
|
|
||||||
|
|
||||||
if (!session)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
// Start connection
|
|
||||||
if (irc_connect(session, joinServer.String(), port, password, nick, ident,
|
|
||||||
real_name))
|
|
||||||
{
|
|
||||||
BMessage error(IM_ERROR);
|
|
||||||
error.AddString("error", "Could not connect");
|
|
||||||
error.AddString("details", irc_strerror(irc_errno(session)));
|
|
||||||
_SendMessage(&error);
|
|
||||||
_SendMessage(new BMessage(IM_PROTOCOL_DISABLE));
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start network loop
|
|
||||||
if (irc_run(session)) {
|
|
||||||
BMessage error(IM_ERROR);
|
|
||||||
error.AddString("error", "Connection or I/O error");
|
|
||||||
error.AddString("details", irc_strerror(irc_errno(session)));
|
|
||||||
_SendMessage(&error);
|
|
||||||
_SendMessage(new BMessage(IM_PROTOCOL_DISABLE));
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IrcProtocol::IrcProtocol()
|
IrcProtocol::IrcProtocol()
|
||||||
|
:
|
||||||
|
fSocket(NULL),
|
||||||
|
fNick(NULL),
|
||||||
|
fIdent(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IrcProtocol::~IrcProtocol()
|
||||||
|
{
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
IrcProtocol::Init(ChatProtocolMessengerInterface* interface)
|
IrcProtocol::Init(ChatProtocolMessengerInterface* interface)
|
||||||
{
|
{
|
||||||
|
@ -95,6 +56,53 @@ IrcProtocol::Init(ChatProtocolMessengerInterface* interface)
|
||||||
status_t
|
status_t
|
||||||
IrcProtocol::Shutdown()
|
IrcProtocol::Shutdown()
|
||||||
{
|
{
|
||||||
|
BString cmd = "QUIT";
|
||||||
|
cmd << " :" << fPartText << "\n";
|
||||||
|
_SendIrc(cmd);
|
||||||
|
|
||||||
|
kill_thread(fRecvThread);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
IrcProtocol::UpdateSettings(BMessage* settings)
|
||||||
|
{
|
||||||
|
fNick = settings->FindString("nick");
|
||||||
|
fPartText = settings->GetString("part", "Cardie[0.1]: i've been liquified!");
|
||||||
|
const char* ident = settings->FindString("ident");
|
||||||
|
const char* real_name = settings->FindString("real_name");
|
||||||
|
const char* server = settings->FindString("server");
|
||||||
|
const char* password = settings->FindString("password");
|
||||||
|
int32 port = settings->FindInt32("port");
|
||||||
|
bool ssl = settings->GetBool("ssl", false);
|
||||||
|
|
||||||
|
fSocket = ssl ? new BSecureSocket : new BSocket;
|
||||||
|
|
||||||
|
if (fSocket->Connect(BNetworkAddress(server, port)) != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
if (password != NULL) {
|
||||||
|
BString passMsg = "PASS ";
|
||||||
|
passMsg << password << "\n";
|
||||||
|
_SendIrc(passMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
BString userMsg = "USER ";
|
||||||
|
userMsg << ident << " * 0 :" << real_name << "\n";
|
||||||
|
_SendIrc(userMsg);
|
||||||
|
|
||||||
|
BString nickMsg = "NICK ";
|
||||||
|
nickMsg << fNick << "\n";
|
||||||
|
_SendIrc(nickMsg);
|
||||||
|
|
||||||
|
fRecvThread = spawn_thread(connect_thread, "what_a_tangled_web_we_weave",
|
||||||
|
B_NORMAL_PRIORITY, (void*)this);
|
||||||
|
|
||||||
|
if (fRecvThread < B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
resume_thread(fRecvThread);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,243 +110,97 @@ IrcProtocol::Shutdown()
|
||||||
status_t
|
status_t
|
||||||
IrcProtocol::Process(BMessage* msg)
|
IrcProtocol::Process(BMessage* msg)
|
||||||
{
|
{
|
||||||
BString chat_id;
|
int32 im_what = msg->FindInt32("im_what");
|
||||||
if (msg->FindString("chat_id", &chat_id) != B_OK)
|
switch (im_what) {
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
switch (msg->FindInt32("im_what"))
|
|
||||||
{
|
|
||||||
case IM_SEND_MESSAGE:
|
|
||||||
{
|
|
||||||
BString body;
|
|
||||||
if (msg->FindString("body", &body) != B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
irc_cmd_msg(fSession, chat_id.String(), body.String());
|
|
||||||
|
|
||||||
irc_ctx_t* ctx = (irc_ctx_t*)irc_get_ctx(fSession);
|
|
||||||
|
|
||||||
BMessage sendMsg(*msg);
|
|
||||||
sendMsg.ReplaceInt32("im_what", IM_MESSAGE_SENT);
|
|
||||||
sendMsg.AddString("user_id", ctx->id);
|
|
||||||
_SendMessage(&sendMsg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IM_JOIN_ROOM:
|
case IM_JOIN_ROOM:
|
||||||
case IM_CREATE_ROOM:
|
|
||||||
{
|
{
|
||||||
irc_cmd_join(fSession, chat_id.String(), "");
|
BString chat_id;
|
||||||
break;
|
if (msg->FindString("chat_id", &chat_id) == B_OK) {
|
||||||
}
|
BString cmd = "JOIN ";
|
||||||
case IM_LEAVE_ROOM:
|
cmd << chat_id << "\n";
|
||||||
{
|
_SendIrc(cmd);
|
||||||
irc_cmd_part(fSession, chat_id.String());
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IM_GET_ROOM_PARTICIPANTS:
|
|
||||||
{
|
|
||||||
irc_cmd_names(fSession, chat_id.String());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IM_ROOM_SEND_INVITE:
|
|
||||||
{
|
|
||||||
BString user_id;
|
|
||||||
if (msg->FindString("user_id", &user_id) != B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
irc_cmd_invite(fSession, user_id.String(), chat_id.String());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IM_ROOM_KICK_PARTICIPANT:
|
|
||||||
{
|
|
||||||
BString user_id;
|
|
||||||
if (msg->FindString("user_id", &user_id) != B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
irc_cmd_kick(fSession, user_id.String(), chat_id.String(),
|
|
||||||
msg->FindString("body"));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
std::cout << "Unhandled message for IRC:\n";
|
||||||
|
msg->PrintToStream();
|
||||||
}
|
}
|
||||||
return B_OK;
|
return B_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
IrcProtocol::UpdateSettings(BMessage* msg)
|
|
||||||
{
|
|
||||||
fSettings = msg;
|
|
||||||
fServerThread = spawn_thread(connect_thread, "connect_thread",
|
|
||||||
B_NORMAL_PRIORITY, (void*)this);
|
|
||||||
|
|
||||||
if (fServerThread < B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
resume_thread(fServerThread);
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BMessage
|
BMessage
|
||||||
IrcProtocol::SettingsTemplate(const char* name)
|
IrcProtocol::SettingsTemplate(const char* name)
|
||||||
{
|
{
|
||||||
size_t size;
|
BMessage settings;
|
||||||
BMessage temp;
|
if (strcmp(name, "account") == 0)
|
||||||
const void* buff = fResources.LoadResource(B_MESSAGE_TYPE, name, &size);
|
settings = _AccountTemplate();
|
||||||
|
else if (strcmp(name, "join_room") == 0 || strcmp(name, "create_room") == 0)
|
||||||
if (buff != NULL)
|
settings = _RoomTemplate();
|
||||||
temp.Unflatten((const char*)buff);
|
return settings;
|
||||||
return temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BObjectList<BMessage>
|
status_t
|
||||||
IrcProtocol::Commands()
|
IrcProtocol::Loop()
|
||||||
{
|
{
|
||||||
return BObjectList<BMessage>();
|
while (fSocket != NULL && fSocket->IsConnected() == true)
|
||||||
}
|
_ProcessLine(_ReadUntilNewline(fSocket, &fRemainingBuf));
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
BObjectList<BMessage>
|
|
||||||
IrcProtocol::UserPopUpItems()
|
|
||||||
{
|
|
||||||
return BObjectList<BMessage>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BObjectList<BMessage>
|
|
||||||
IrcProtocol::ChatPopUpItems()
|
|
||||||
{
|
|
||||||
return BObjectList<BMessage>();
|
|
||||||
}
|
|
||||||
|
|
||||||
BObjectList<BMessage>
|
|
||||||
IrcProtocol::MenuBarItems()
|
|
||||||
{
|
|
||||||
return BObjectList<BMessage>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char*
|
|
||||||
IrcProtocol::Signature() const
|
|
||||||
{
|
|
||||||
return "irc";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char*
|
|
||||||
IrcProtocol::FriendlySignature() const
|
|
||||||
{
|
|
||||||
return "IRC";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BBitmap*
|
|
||||||
IrcProtocol::Icon() const
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IrcProtocol::SetAddOnPath(BPath path)
|
IrcProtocol::_ProcessLine(BString line)
|
||||||
{
|
{
|
||||||
fAddOnPath = path;
|
BStringList words;
|
||||||
fResources.SetTo(path.Path());
|
line.Split(" ", true, words);
|
||||||
}
|
BString sender = _LineSender(words);
|
||||||
|
BString code = _LineCode(words);
|
||||||
|
BStringList params = _LineParameters(words);
|
||||||
|
BString body = _LineBody(line);
|
||||||
|
|
||||||
|
int32 numeric;
|
||||||
BPath
|
if ((numeric = atoi(code.String())) > 0)
|
||||||
IrcProtocol::AddOnPath()
|
_ProcessNumeric(numeric, sender, params, body);
|
||||||
{
|
else
|
||||||
return fAddOnPath;
|
_ProcessCommand(code, sender, params, body);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char*
|
|
||||||
IrcProtocol::GetName()
|
|
||||||
{
|
|
||||||
return fName.String();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IrcProtocol::SetName(const char* name)
|
IrcProtocol::_ProcessNumeric(int32 numeric, BString sender, BStringList params,
|
||||||
|
BString body)
|
||||||
{
|
{
|
||||||
fName.SetTo(name);
|
switch (numeric) {
|
||||||
}
|
case RPL_WELCOME:
|
||||||
|
|
||||||
|
|
||||||
uint32
|
|
||||||
IrcProtocol::GetEncoding()
|
|
||||||
{
|
|
||||||
return 0xffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ChatProtocolMessengerInterface*
|
|
||||||
IrcProtocol::MessengerInterface() const
|
|
||||||
{
|
|
||||||
return fMessenger;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
irc_callbacks_t
|
|
||||||
get_callbacks()
|
|
||||||
{
|
|
||||||
irc_callbacks_t callbacks;
|
|
||||||
callbacks.event_connect = event_connect;
|
|
||||||
callbacks.event_numeric = event_numeric;
|
|
||||||
callbacks.event_join = event_join;
|
|
||||||
callbacks.event_part = event_part;
|
|
||||||
callbacks.event_channel = event_channel;
|
|
||||||
callbacks.event_privmsg = event_privmsg;
|
|
||||||
callbacks.event_nick = event_nick;
|
|
||||||
return callbacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
event_connect(irc_session_t* session, const char* event,
|
|
||||||
const char* origin, const char** params, unsigned int count)
|
|
||||||
{
|
|
||||||
BMessage readyMsg(IM_MESSAGE);
|
|
||||||
readyMsg.AddInt32("im_what", IM_PROTOCOL_READY);
|
|
||||||
_SendMessage(&readyMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
event_numeric(irc_session_t* session, unsigned int event,
|
|
||||||
const char* origin, const char** params, unsigned int count)
|
|
||||||
{
|
|
||||||
irc_ctx_t* ctx = (irc_ctx_t*)irc_get_ctx(session);
|
|
||||||
|
|
||||||
switch (event) {
|
|
||||||
case LIBIRC_RFC_RPL_NAMREPLY:
|
|
||||||
{
|
{
|
||||||
BStringList user_id;
|
BMessage ready(IM_MESSAGE);
|
||||||
|
ready.AddInt32("im_what", IM_PROTOCOL_READY);
|
||||||
|
_SendMsg(&ready);
|
||||||
|
|
||||||
BString user_list(params[3]);
|
BMessage self(IM_MESSAGE);
|
||||||
user_list.Split(" ", false, user_id);
|
self.AddInt32("im_what", IM_OWN_CONTACT_INFO);
|
||||||
|
self.AddString("user_id", fNick);
|
||||||
BStringList user_name(user_id);
|
_SendMsg(&self);
|
||||||
int32 index = user_name.IndexOf(ctx->nick);
|
|
||||||
if (index >= 0)
|
|
||||||
user_id.Replace(index, BString(ctx->id));
|
|
||||||
|
|
||||||
BMessage list(IM_MESSAGE);
|
|
||||||
list.AddInt32("im_what", IM_ROOM_PARTICIPANTS);
|
|
||||||
list.AddString("chat_id", params[2]);
|
|
||||||
list.AddStrings("user_id", user_id);
|
|
||||||
list.AddStrings("user_name", user_name);
|
|
||||||
_SendMessage(&list);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LIBIRC_RFC_RPL_TOPIC:
|
case RPL_MOTD:
|
||||||
{
|
{
|
||||||
BMessage topic(IM_MESSAGE);
|
BMessage send(IM_MESSAGE);
|
||||||
topic.AddInt32("im_what", IM_ROOM_SUBJECT_SET);
|
send.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
||||||
topic.AddString("chat_id", params[1]);
|
send.AddString("chat_id", sender);
|
||||||
topic.AddString("subject", params[2]);
|
send.AddString("body", body);
|
||||||
_SendMessage(&topic);
|
_SendMsg(&send);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ERR_NICKNAMEINUSE:
|
||||||
|
{
|
||||||
|
fNick << "_";
|
||||||
|
BString cmd("NICK ");
|
||||||
|
cmd << fNick << "\n";
|
||||||
|
_SendIrc(cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,128 +208,199 @@ event_numeric(irc_session_t* session, unsigned int event,
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
event_join(irc_session_t* session, const char* event, const char* joiner,
|
IrcProtocol::_ProcessCommand(BString command, BString sender,
|
||||||
const char** channel, unsigned int count)
|
BStringList params, BString body)
|
||||||
{
|
{
|
||||||
int32 im_what = IM_ROOM_PARTICIPANT_JOINED;
|
if (command == "PING") {
|
||||||
|
BString cmd = "PONG ";
|
||||||
irc_ctx_t* ctx = (irc_ctx_t*)irc_get_ctx(session);
|
cmd << body.RemoveChars(0, 1) << "\n";
|
||||||
if (_IsOwnUser(joiner, session) == true)
|
_SendIrc(cmd);
|
||||||
im_what = IM_ROOM_JOINED;
|
|
||||||
|
|
||||||
BMessage joinedMsg(IM_MESSAGE);
|
|
||||||
joinedMsg.AddInt32("im_what", im_what);
|
|
||||||
joinedMsg.AddString("user_id", joiner);
|
|
||||||
joinedMsg.AddString("chat_id", channel[0]);
|
|
||||||
_SendMessage(&joinedMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
event_part(irc_session_t* session, const char* event, const char* quitter,
|
|
||||||
const char** chanReason, unsigned int count)
|
|
||||||
{
|
|
||||||
int32 im_what = IM_ROOM_PARTICIPANT_LEFT;
|
|
||||||
if (_IsOwnUser(quitter, session) == true)
|
|
||||||
im_what = IM_ROOM_LEFT;
|
|
||||||
|
|
||||||
BString body;
|
|
||||||
if (chanReason[1] != NULL)
|
|
||||||
body << chanReason[1];
|
|
||||||
|
|
||||||
BMessage quitMsg(IM_MESSAGE);
|
|
||||||
quitMsg.AddInt32("im_what", im_what);
|
|
||||||
quitMsg.AddString("user_id", quitter);
|
|
||||||
quitMsg.AddString("chat_id", chanReason[0]);
|
|
||||||
if (body.IsEmpty() == false)
|
|
||||||
quitMsg.AddString("body", body);
|
|
||||||
_SendMessage(&quitMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
event_channel(irc_session_t* session, const char* event, const char* sender,
|
|
||||||
const char** chanBody, unsigned int count)
|
|
||||||
{
|
|
||||||
BMessage msgMsg(IM_MESSAGE);
|
|
||||||
msgMsg.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
|
||||||
msgMsg.AddString("user_id", sender);
|
|
||||||
msgMsg.AddString("chat_id", chanBody[0]);
|
|
||||||
msgMsg.AddString("body", chanBody[1]);
|
|
||||||
_SendMessage(&msgMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
event_privmsg(irc_session_t* session, const char* event, const char* sender,
|
|
||||||
const char** selfBody, unsigned int count)
|
|
||||||
{
|
|
||||||
BMessage msgMsg(IM_MESSAGE);
|
|
||||||
msgMsg.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
|
||||||
msgMsg.AddString("user_id", sender);
|
|
||||||
msgMsg.AddString("chat_id", _UserNick(sender));
|
|
||||||
msgMsg.AddString("body", selfBody[1]);
|
|
||||||
_SendMessage(&msgMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: Nick-change API
|
|
||||||
void
|
|
||||||
event_nick(irc_session_t* session, const char* event, const char* oldNick,
|
|
||||||
const char** newNick, unsigned int count)
|
|
||||||
{
|
|
||||||
irc_ctx_t* ctx = (irc_ctx_t*)irc_get_ctx(session);
|
|
||||||
|
|
||||||
if (_IsOwnUser(oldNick, session) == true) {
|
|
||||||
ctx->nick.SetTo(newNick[0]);
|
|
||||||
irc_set_ctx(session, ctx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BString
|
BString
|
||||||
_UserNick(const char* userId)
|
IrcProtocol::_LineSender(BStringList words)
|
||||||
{
|
{
|
||||||
BStringList split;
|
BString sender;
|
||||||
BString id(userId);
|
if (words.CountStrings() > 1)
|
||||||
id.Split("!", false, split);
|
sender = words.StringAt(0).RemoveChars(0, 1);
|
||||||
|
return sender;
|
||||||
BString name = split.StringAt(0);
|
|
||||||
if (name.StartsWith("@") == true)
|
|
||||||
name.RemoveFirst("@");
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
BString
|
||||||
_IsOwnUser(const char* userId, irc_session_t* session)
|
IrcProtocol::_LineCode(BStringList words)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
BString code;
|
||||||
irc_ctx_t* ctx = (irc_ctx_t*)irc_get_ctx(session);
|
if (words.CountStrings() > 2)
|
||||||
|
code = words.StringAt(1);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->nick == _UserNick(userId)) {
|
|
||||||
ret = true;
|
BStringList
|
||||||
if (ctx->id.IsEmpty() == true) {
|
IrcProtocol::_LineParameters(BStringList words)
|
||||||
ctx->id.SetTo(userId);
|
{
|
||||||
irc_set_ctx(session, ctx);
|
BStringList params;
|
||||||
|
BString current;
|
||||||
// The app hasn't been informed of user_id, then!
|
for (int i = 2; i < words.CountStrings(); i++)
|
||||||
BMessage ownInfo(IM_MESSAGE);
|
if ((current = words.StringAt(i)).StartsWith(":") == false)
|
||||||
ownInfo.AddInt32("im_what", IM_OWN_CONTACT_INFO);
|
params.Add(current);
|
||||||
ownInfo.AddString("user_id", userId);
|
else
|
||||||
_SendMessage(&ownInfo);
|
break;
|
||||||
}
|
return params;
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
IrcProtocol::_LineBody(BString line)
|
||||||
|
{
|
||||||
|
BString body;
|
||||||
|
int32 index = line.RemoveChars(0, 1).FindFirst(":");
|
||||||
|
if (index != B_ERROR)
|
||||||
|
body = line.RemoveChars(0, index + 1);
|
||||||
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_SendMessage(BMessage* msg)
|
IrcProtocol::_SendMsg(BMessage* msg)
|
||||||
{
|
{
|
||||||
if (!msg)
|
fMessenger->SendMessage(msg);
|
||||||
return;
|
}
|
||||||
msg->AddString("protocol", current_proto->Signature());
|
|
||||||
current_proto->MessengerInterface()->SendMessage(msg);
|
|
||||||
|
void
|
||||||
|
IrcProtocol::_SendIrc(BString cmd)
|
||||||
|
{
|
||||||
|
if (fSocket != NULL && fSocket->IsConnected() == true)
|
||||||
|
fSocket->Write(cmd.String(), cmd.CountChars());
|
||||||
|
else {
|
||||||
|
BMessage disable(IM_MESSAGE);
|
||||||
|
disable.AddInt32("im_what", IM_PROTOCOL_DISABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
IrcProtocol::_ReadUntilNewline(BDataIO* io, BString* extraBuffer)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!(strstr(buf, "\n"))) {
|
||||||
|
io->Read(buf, 1023);
|
||||||
|
std::cerr << buf << std::endl;
|
||||||
|
total << buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
BString currentLine = _TrimStringToNewline(&total);
|
||||||
|
extraBuffer->SetTo(total);
|
||||||
|
return currentLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
IrcProtocol::_TrimStringToNewline(BString* str)
|
||||||
|
{
|
||||||
|
BString line;
|
||||||
|
int32 lineEnd = str->FindFirst('\n');
|
||||||
|
|
||||||
|
if (lineEnd != B_ERROR) {
|
||||||
|
str->CopyCharsInto(line, 0, lineEnd + 1);
|
||||||
|
str->RemoveChars(0, lineEnd + 1);
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessage
|
||||||
|
IrcProtocol::_AccountTemplate()
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
ssl.AddString("description", B_TRANSLATE("SSL:"));
|
||||||
|
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");
|
||||||
|
ident.AddString("description", B_TRANSLATE("Ident:"));
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessage
|
||||||
|
IrcProtocol::_RoomTemplate()
|
||||||
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,101 +5,82 @@
|
||||||
#ifndef _IRC_PROTOCOL_H
|
#ifndef _IRC_PROTOCOL_H
|
||||||
#define _IRC_PROTOCOL_H
|
#define _IRC_PROTOCOL_H
|
||||||
|
|
||||||
#include <Path.h>
|
|
||||||
#include <Resources.h>
|
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
#include <StringList.h>
|
||||||
#include <libircclient.h>
|
|
||||||
#include <libirc_rfcnumeric.h>
|
|
||||||
|
|
||||||
#include <ChatProtocol.h>
|
#include <ChatProtocol.h>
|
||||||
|
|
||||||
|
class BSocket;
|
||||||
status_t connect_thread(void* data);
|
class BDataIO;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
BString nick;
|
|
||||||
BString id;
|
|
||||||
} irc_ctx_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class IrcProtocol : public ChatProtocol {
|
class IrcProtocol : public ChatProtocol {
|
||||||
public:
|
public:
|
||||||
IrcProtocol();
|
IrcProtocol();
|
||||||
|
~IrcProtocol();
|
||||||
|
|
||||||
// ChatProtocol inheritance
|
// ChatProtocol inheritance
|
||||||
virtual status_t Init(ChatProtocolMessengerInterface* interface);
|
virtual status_t Init(ChatProtocolMessengerInterface* interface);
|
||||||
virtual status_t Shutdown();
|
virtual status_t Shutdown();
|
||||||
|
|
||||||
|
virtual status_t UpdateSettings(BMessage* settings);
|
||||||
|
|
||||||
virtual status_t Process(BMessage* msg);
|
virtual status_t Process(BMessage* msg);
|
||||||
|
|
||||||
virtual status_t UpdateSettings(BMessage* msg);
|
|
||||||
virtual BMessage SettingsTemplate(const char* name);
|
virtual BMessage SettingsTemplate(const char* name);
|
||||||
|
|
||||||
virtual BObjectList<BMessage> Commands();
|
virtual const char* Signature() const { return "irc"; }
|
||||||
virtual BObjectList<BMessage> UserPopUpItems();
|
virtual const char* FriendlySignature() const { return "IRC"; }
|
||||||
virtual BObjectList<BMessage> ChatPopUpItems();
|
|
||||||
virtual BObjectList<BMessage> MenuBarItems();
|
|
||||||
|
|
||||||
virtual const char* Signature() const;
|
virtual void SetAddOnPath(BPath path) { fAddOnPath = path; }
|
||||||
virtual const char* FriendlySignature() const;
|
virtual BPath AddOnPath() { return fAddOnPath; }
|
||||||
|
|
||||||
virtual BBitmap* Icon() const;
|
virtual const char* GetName() { return fName; }
|
||||||
|
virtual void SetName(const char* name) { fName = name; }
|
||||||
virtual void SetAddOnPath(BPath path);
|
|
||||||
virtual BPath AddOnPath();
|
|
||||||
|
|
||||||
virtual const char* GetName();
|
|
||||||
virtual void SetName(const char* name);
|
|
||||||
|
|
||||||
virtual uint32 GetEncoding();
|
|
||||||
|
|
||||||
virtual ChatProtocolMessengerInterface*
|
virtual ChatProtocolMessengerInterface*
|
||||||
MessengerInterface() const;
|
MessengerInterface() const { return fMessenger; }
|
||||||
|
|
||||||
// IRC
|
// IRC
|
||||||
|
status_t Loop();
|
||||||
|
|
||||||
BMessage* fSettings;
|
BMessage* fSettings;
|
||||||
irc_session_t* fSession;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ChatProtocolMessengerInterface* fMessenger;
|
void _ProcessLine(BString line);
|
||||||
|
void _ProcessNumeric(int32 numeric, BString sender,
|
||||||
|
BStringList params, BString message);
|
||||||
|
void _ProcessCommand(BString command, BString sender,
|
||||||
|
BStringList params, BString message);
|
||||||
|
|
||||||
thread_id fServerThread;
|
BString _LineSender(BStringList words);
|
||||||
|
BString _LineCode(BStringList words);
|
||||||
|
BStringList _LineParameters(BStringList words);
|
||||||
|
BString _LineBody(BString line);
|
||||||
|
|
||||||
|
void _SendMsg(BMessage* msg);
|
||||||
|
void _SendIrc(BString cmd);
|
||||||
|
|
||||||
|
// Read a data stream until newline found; if data found past newline,
|
||||||
|
// append to given buffer for later use
|
||||||
|
BString _ReadUntilNewline(BDataIO* data, BString* extraBuffer);
|
||||||
|
// Trim given string until newline hit, return trimmed part
|
||||||
|
BString _TrimStringToNewline(BString* str);
|
||||||
|
|
||||||
|
// GUI templates
|
||||||
|
BMessage _AccountTemplate();
|
||||||
|
BMessage _RoomTemplate();
|
||||||
|
|
||||||
|
BSocket* fSocket;
|
||||||
|
BString fRemainingBuf;
|
||||||
|
thread_id fRecvThread;
|
||||||
|
|
||||||
|
BString fNick;
|
||||||
|
const char* fIdent;
|
||||||
|
BString fPartText;
|
||||||
|
|
||||||
BString fName;
|
|
||||||
BPath fAddOnPath;
|
BPath fAddOnPath;
|
||||||
BResources fResources;
|
BString fName;
|
||||||
|
ChatProtocolMessengerInterface* fMessenger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
irc_callbacks_t get_callbacks();
|
|
||||||
|
|
||||||
void event_connect(irc_session_t* session, const char* event,
|
|
||||||
const char* origin, const char** params,
|
|
||||||
unsigned int count);
|
|
||||||
|
|
||||||
void event_numeric(irc_session_t* session, unsigned int event,
|
|
||||||
const char* origin, const char** params, unsigned int count);
|
|
||||||
|
|
||||||
void event_join(irc_session_t* session, const char* event,
|
|
||||||
const char* joiner, const char** channel, unsigned int count);
|
|
||||||
void event_part(irc_session_t* session, const char* event,
|
|
||||||
const char* quitter, const char** chanReason, unsigned int count);
|
|
||||||
|
|
||||||
void event_channel(irc_session_t* session, const char* event,
|
|
||||||
const char* sender, const char** chanBody, unsigned int count);
|
|
||||||
void event_privmsg(irc_session_t* session, const char* event,
|
|
||||||
const char* sender, const char** selfBody, unsigned int count);
|
|
||||||
|
|
||||||
void event_nick(irc_session_t* session, const char* event,
|
|
||||||
const char* oldNick, const char** newNick, unsigned int count);
|
|
||||||
|
|
||||||
|
|
||||||
BString _UserNick(const char* userId);
|
|
||||||
bool _IsOwnUser(const char* userId, irc_session_t* session);
|
|
||||||
|
|
||||||
void _SendMessage(BMessage* msg);
|
|
||||||
|
|
||||||
#endif // _IRC_PROTOCOL_H
|
#endif // _IRC_PROTOCOL_H
|
||||||
|
|
|
@ -18,7 +18,8 @@ NAME = protocols/irc
|
||||||
TYPE = SHARED
|
TYPE = SHARED
|
||||||
|
|
||||||
# If you plan to use localization, specify the application's MIME signature.
|
# If you plan to use localization, specify the application's MIME signature.
|
||||||
APP_MIME_SIG =
|
APP_MIME_SIG = application/x-vnd.cardie.irc
|
||||||
|
|
||||||
|
|
||||||
# The following lines tell Pe and Eddie where the SRCS, RDEFS, and RSRCS are
|
# The following lines tell Pe and Eddie where the SRCS, RDEFS, and RSRCS are
|
||||||
# so that Pe and Eddie can fill them in for you.
|
# so that Pe and Eddie can fill them in for you.
|
||||||
|
@ -38,8 +39,7 @@ SRCS = \
|
||||||
# Specify the resource definition files to use. Full or relative paths can be
|
# Specify the resource definition files to use. Full or relative paths can be
|
||||||
# used.
|
# used.
|
||||||
RDEFS = \
|
RDEFS = \
|
||||||
protocols/irc/irc.rdef \
|
# protocols/irc/irc.rdef \
|
||||||
protocols/irc/Templates.rdef \
|
|
||||||
|
|
||||||
# Specify the resource files to use. Full or relative paths can be used.
|
# Specify the resource files to use. Full or relative paths can be used.
|
||||||
# Both RDEFS and RSRCS can be utilized in the same Makefile.
|
# Both RDEFS and RSRCS can be utilized in the same Makefile.
|
||||||
|
@ -61,7 +61,7 @@ RSRCS =
|
||||||
# - if your library does not follow the standard library naming scheme,
|
# - if your library does not follow the standard library naming scheme,
|
||||||
# you need to specify the path to the library and it's name.
|
# you need to specify the path to the library and it's name.
|
||||||
# (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a")
|
# (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a")
|
||||||
LIBS = be crypto network support ssl ircclient z $(STDCPPLIBS)
|
LIBS = be bnetapi localestub network support $(STDCPPLIBS)
|
||||||
|
|
||||||
|
|
||||||
# Specify additional paths to directories following the standard libXXX.so
|
# Specify additional paths to directories following the standard libXXX.so
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
// "account" settings template
|
|
||||||
resource(1000, "account") message('IMst')
|
|
||||||
{
|
|
||||||
"setting" = message
|
|
||||||
{
|
|
||||||
"name" = "nick",
|
|
||||||
"description" = "Nickname:",
|
|
||||||
"default" = "Haikunaut",
|
|
||||||
"error" = "You need a default nickname― The Nameless are not welcome on IRC.",
|
|
||||||
int32 "type" = 'CSTR'
|
|
||||||
},
|
|
||||||
"setting" = message
|
|
||||||
{
|
|
||||||
"name" = "ident",
|
|
||||||
"description" = "Ident:",
|
|
||||||
int32 "type" = 'CSTR'
|
|
||||||
},
|
|
||||||
"setting" = message
|
|
||||||
{
|
|
||||||
"name" = "password",
|
|
||||||
"description" = "Password:",
|
|
||||||
bool "is_secret" = true,
|
|
||||||
int32 "type" = 'CSTR'
|
|
||||||
},
|
|
||||||
"setting" = message
|
|
||||||
{
|
|
||||||
"name" = "real_name",
|
|
||||||
"description" = "Real Name:",
|
|
||||||
"default" = "Mx. Catbird",
|
|
||||||
int32 "type" = 'CSTR'
|
|
||||||
},
|
|
||||||
"setting" = message
|
|
||||||
{
|
|
||||||
"name" = "server",
|
|
||||||
"description" = "Server:",
|
|
||||||
"default" = "127.0.0.1",
|
|
||||||
"error" = "Please enter a valid server address.",
|
|
||||||
int32 "type" = 'CSTR'
|
|
||||||
},
|
|
||||||
"setting" = message
|
|
||||||
{
|
|
||||||
"name" = "port",
|
|
||||||
"description" = "Port:",
|
|
||||||
int32 "default" = 10025,
|
|
||||||
"error" = "Without a port, we don't know which door to knock on.\nIt's likely 10025/6667.",
|
|
||||||
int32 "type" = 'LONG'
|
|
||||||
}
|
|
||||||
};
|
|
Ŝarĝante…
Reference in New Issue