forked from PsychoticNinja/irssi
337 lines
9.4 KiB
C
337 lines
9.4 KiB
C
/*
|
|
dump.c : proxy plugin - output all information about irc session
|
|
|
|
Copyright (C) 1999-2001 Timo Sirainen
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "module.h"
|
|
#include "network.h"
|
|
#include "net-sendbuffer.h"
|
|
#include "settings.h"
|
|
#include "irssi-version.h"
|
|
#include "recode.h"
|
|
|
|
#include "irc-servers.h"
|
|
#include "irc-channels.h"
|
|
#include "irc-nicklist.h"
|
|
#include "modes.h"
|
|
#include "line-split.h"
|
|
|
|
void proxy_send(CLIENT_REC *client, char *d, int l)
|
|
{
|
|
if(client->listen->use_ssl) {
|
|
SSL_write(client->ssl, d, l);
|
|
return;
|
|
}
|
|
net_sendbuffer_send(client->handle, d, l);
|
|
}
|
|
|
|
int proxy_readline(CLIENT_REC *client, char **str)
|
|
{
|
|
if(client->listen->use_ssl) {
|
|
char tmpbuf[2048];
|
|
int recvlen = 0;
|
|
|
|
recvlen = SSL_read(client->ssl, tmpbuf, sizeof(tmpbuf));
|
|
if(recvlen > 0) {
|
|
return line_split(tmpbuf, recvlen, str, &client->handle->readbuffer);
|
|
} else {
|
|
int err;
|
|
err = SSL_get_error(client->ssl, recvlen);
|
|
/* READ/WRITE are not really errors, they just indicate that atm
|
|
OpenSSL is waiting for more data */
|
|
if(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
|
|
return line_split(tmpbuf, 0, str, &client->handle->readbuffer);
|
|
}
|
|
return recvlen; /* if any other error occurs, this will quit the connection */
|
|
}
|
|
}
|
|
return net_sendbuffer_receive_line(client->handle, str, 1);
|
|
}
|
|
|
|
void proxy_outdata(CLIENT_REC *client, const char *data, ...)
|
|
{
|
|
va_list args;
|
|
char *str;
|
|
|
|
g_return_if_fail(client != NULL);
|
|
g_return_if_fail(data != NULL);
|
|
|
|
va_start(args, data);
|
|
|
|
str = g_strdup_vprintf(data, args);
|
|
proxy_send(client, str, strlen(str));
|
|
g_free(str);
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
void proxy_outdata_all(IRC_SERVER_REC *server, const char *data, ...)
|
|
{
|
|
va_list args;
|
|
GSList *tmp;
|
|
char *str;
|
|
int len;
|
|
|
|
g_return_if_fail(server != NULL);
|
|
g_return_if_fail(data != NULL);
|
|
|
|
va_start(args, data);
|
|
|
|
str = g_strdup_vprintf(data, args);
|
|
len = strlen(str);
|
|
for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
|
|
CLIENT_REC *rec = tmp->data;
|
|
|
|
if (rec->connected && rec->server == server)
|
|
proxy_send(rec, str, len);
|
|
}
|
|
g_free(str);
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
void proxy_outserver(CLIENT_REC *client, const char *data, ...)
|
|
{
|
|
va_list args;
|
|
char *str;
|
|
|
|
g_return_if_fail(client != NULL);
|
|
g_return_if_fail(data != NULL);
|
|
|
|
va_start(args, data);
|
|
|
|
str = g_strdup_vprintf(data, args);
|
|
proxy_outdata(client, ":%s!%s@proxy %s\r\n", client->nick,
|
|
settings_get_str("user_name"), str);
|
|
g_free(str);
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
void proxy_outserver_all(IRC_SERVER_REC *server, const char *data, ...)
|
|
{
|
|
va_list args;
|
|
GSList *tmp;
|
|
char *str;
|
|
|
|
g_return_if_fail(server != NULL);
|
|
g_return_if_fail(data != NULL);
|
|
|
|
va_start(args, data);
|
|
|
|
str = g_strdup_vprintf(data, args);
|
|
for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
|
|
CLIENT_REC *rec = tmp->data;
|
|
|
|
if (rec->connected && rec->server == server) {
|
|
proxy_outdata(rec, ":%s!%s@proxy %s\r\n", rec->nick,
|
|
settings_get_str("user_name"), str);
|
|
}
|
|
}
|
|
g_free(str);
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
void proxy_outserver_all_except(CLIENT_REC *client, const char *data, ...)
|
|
{
|
|
va_list args;
|
|
GSList *tmp;
|
|
char *str;
|
|
|
|
g_return_if_fail(client != NULL);
|
|
g_return_if_fail(data != NULL);
|
|
|
|
va_start(args, data);
|
|
|
|
str = g_strdup_vprintf(data, args);
|
|
for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
|
|
CLIENT_REC *rec = tmp->data;
|
|
|
|
if (rec->connected && rec != client &&
|
|
rec->server == client->server) {
|
|
proxy_outdata(rec, ":%s!%s@proxy %s\r\n", rec->nick,
|
|
settings_get_str("user_name"), str);
|
|
}
|
|
}
|
|
g_free(str);
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
static void create_names_start(GString *str, IRC_CHANNEL_REC *channel,
|
|
CLIENT_REC *client)
|
|
{
|
|
g_string_printf(str, ":%s 353 %s %c %s :",
|
|
client->proxy_address, client->nick,
|
|
channel_mode_is_set(channel, 'p') ? '*' :
|
|
channel_mode_is_set(channel, 's') ? '@' : '=',
|
|
channel->name);
|
|
}
|
|
|
|
static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client)
|
|
{
|
|
GSList *tmp, *nicks;
|
|
GString *str;
|
|
int first;
|
|
char *recoded;
|
|
|
|
proxy_outserver(client, "JOIN %s", channel->name);
|
|
|
|
str = g_string_new(NULL);
|
|
create_names_start(str, channel, client);
|
|
|
|
first = TRUE;
|
|
nicks = nicklist_getnicks(CHANNEL(channel));
|
|
for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
|
|
NICK_REC *nick = tmp->data;
|
|
|
|
if (str->len >= 500) {
|
|
g_string_append(str, "\r\n");
|
|
proxy_outdata(client, "%s", str->str);
|
|
create_names_start(str, channel, client);
|
|
first = TRUE;
|
|
}
|
|
|
|
if (first)
|
|
first = FALSE;
|
|
else
|
|
g_string_append_c(str, ' ');
|
|
|
|
if (nick->prefixes[0])
|
|
g_string_append_c(str, nick->prefixes[0]);
|
|
g_string_append(str, nick->nick);
|
|
}
|
|
g_slist_free(nicks);
|
|
|
|
g_string_append(str, "\r\n");
|
|
proxy_outdata(client, "%s", str->str);
|
|
g_string_free(str, TRUE);
|
|
|
|
proxy_outdata(client, ":%s 366 %s %s :End of /NAMES list.\r\n",
|
|
client->proxy_address, client->nick, channel->name);
|
|
if (channel->topic != NULL) {
|
|
/* this is needed because the topic may be encoded into other charsets internaly */
|
|
recoded = recode_out(SERVER(client->server), channel->topic, channel->name);
|
|
proxy_outdata(client, ":%s 332 %s %s :%s\r\n",
|
|
client->proxy_address, client->nick,
|
|
channel->name, recoded);
|
|
g_free(recoded);
|
|
if (channel->topic_time > 0)
|
|
proxy_outdata(client, ":%s 333 %s %s %s %d\r\n",
|
|
client->proxy_address, client->nick,
|
|
channel->name, channel->topic_by, channel->topic_time);
|
|
}
|
|
}
|
|
|
|
void proxy_client_reset_nick(CLIENT_REC *client)
|
|
{
|
|
if (client->server == NULL ||
|
|
g_strcmp0(client->nick, client->server->nick) == 0)
|
|
return;
|
|
|
|
proxy_outdata(client, ":%s!proxy NICK :%s\r\n",
|
|
client->nick, client->server->nick);
|
|
|
|
g_free(client->nick);
|
|
client->nick = g_strdup(client->server->nick);
|
|
}
|
|
|
|
static void proxy_dump_data_005(gpointer key, gpointer value, gpointer context)
|
|
{
|
|
if (*(char *)value != '\0')
|
|
g_string_append_printf(context, "%s=%s ", (char *)key, (char *)value);
|
|
else
|
|
g_string_append_printf(context, "%s ", (char *)key);
|
|
}
|
|
|
|
void proxy_dump_data(CLIENT_REC *client)
|
|
{
|
|
GString *isupport_out, *paramstr;
|
|
char **paramlist, **tmp;
|
|
int count;
|
|
|
|
proxy_client_reset_nick(client);
|
|
|
|
/* welcome info */
|
|
proxy_outdata(client, ":%s 001 %s :Welcome to the Internet Relay Network %s!%s@proxy\r\n", client->proxy_address, client->nick, client->nick, settings_get_str("user_name"));
|
|
proxy_outdata(client, ":%s 002 %s :Your host is irssi-proxy, running version %s\r\n", client->proxy_address, client->nick, PACKAGE_VERSION);
|
|
proxy_outdata(client, ":%s 003 %s :This server was created ...\r\n", client->proxy_address, client->nick);
|
|
if (client->server == NULL || !client->server->emode_known)
|
|
proxy_outdata(client, ":%s 004 %s %s %s oirw abiklmnopqstv\r\n", client->proxy_address, client->nick, client->proxy_address, PACKAGE_VERSION);
|
|
else
|
|
proxy_outdata(client, ":%s 004 %s %s %s oirw abeIiklmnopqstv\r\n", client->proxy_address, client->nick, client->proxy_address, PACKAGE_VERSION);
|
|
|
|
if (client->server != NULL && client->server->isupport_sent) {
|
|
isupport_out = g_string_new(NULL);
|
|
g_hash_table_foreach(client->server->isupport, proxy_dump_data_005, isupport_out);
|
|
if (isupport_out->len > 0)
|
|
g_string_truncate(isupport_out, isupport_out->len-1);
|
|
|
|
proxy_outdata(client, ":%s 005 %s ", client->proxy_address, client->nick);
|
|
|
|
paramstr = g_string_new(NULL);
|
|
paramlist = g_strsplit(isupport_out->str, " ", -1);
|
|
count = 0;
|
|
tmp = paramlist;
|
|
|
|
for (;; tmp++) {
|
|
if (*tmp != NULL) {
|
|
g_string_append_printf(paramstr, "%s ", *tmp);
|
|
if (++count < 15)
|
|
continue;
|
|
}
|
|
|
|
count = 0;
|
|
if (paramstr->len > 0)
|
|
g_string_truncate(paramstr, paramstr->len-1);
|
|
g_string_append_printf(paramstr, " :are supported by this server\r\n");
|
|
proxy_outdata(client, "%s", paramstr->str);
|
|
g_string_truncate(paramstr, 0);
|
|
g_string_printf(paramstr, ":%s 005 %s ", client->proxy_address, client->nick);
|
|
|
|
if (*tmp == NULL || tmp[1] == NULL)
|
|
break;
|
|
}
|
|
|
|
g_string_free(isupport_out, TRUE);
|
|
g_string_free(paramstr, TRUE);
|
|
g_strfreev(paramlist);
|
|
}
|
|
|
|
proxy_outdata(client, ":%s 251 %s :There are 0 users and 0 invisible on 1 servers\r\n", client->proxy_address, client->nick);
|
|
proxy_outdata(client, ":%s 255 %s :I have 0 clients, 0 services and 0 servers\r\n", client->proxy_address, client->nick);
|
|
proxy_outdata(client, ":%s 422 %s :MOTD File is missing\r\n", client->proxy_address, client->nick);
|
|
|
|
/* user mode / away status */
|
|
if (client->server != NULL) {
|
|
if (client->server->usermode != NULL) {
|
|
proxy_outserver(client, "MODE %s :+%s",
|
|
client->server->nick,
|
|
client->server->usermode);
|
|
}
|
|
if (client->server->usermode_away) {
|
|
proxy_outdata(client, ":%s 306 %s :You have been marked as being away\r\n",
|
|
client->proxy_address, client->nick);
|
|
}
|
|
|
|
/* Send channel joins */
|
|
g_slist_foreach(client->server->channels, (GFunc) dump_join, client);
|
|
}
|
|
}
|