Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commit 65cdfc94 authored by Deucе's avatar Deucе 👌🏾

Merge branch 'deuce-says-so' into 'master'

First IRCd 1.9 changes

See merge request !125
parents 7dc22c07 43891e3c
This diff is collapsed.
// $Id: ircd_channel.js,v 1.34 2019/08/06 20:44:39 deuce Exp $ /*
//
// ircd_channel.js ircd/channel.js
//
// This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version. (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details: GNU General Public License for more details:
// http://www.gnu.org/licenses/gpl.txt https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
//
// Synchronet IRC Daemon as per RFC 1459, link compatible with Bahamut 1.4 Everything related to channels in the IRCd and their operation.
//
// Copyright 2003-2009 Randolph Erwin Sommerfeld <sysop@rrx.ca> Copyright 2003-2021 Randy Sommerfeld <cyan@synchro.net>
//
// ** Everything related to channels and their operation. */
//
////////// Constants / Defines //////////
const CHANNEL_REVISION = "$Revision: 1.34 $".split(' ')[1];
const CHANMODE_NONE =(1<<0); // NONE const CHANMODE_NONE =(1<<0); // NONE
const CHANMODE_BAN =(1<<1); // b const CHANMODE_BAN =(1<<1); // b
...@@ -87,8 +83,11 @@ function Channel(nam) { ...@@ -87,8 +83,11 @@ function Channel(nam) {
////////// Functions ////////// ////////// Functions //////////
function ChanMode_tweaktmpmode(tmp_bit,add) { function ChanMode_tweaktmpmode(tmp_bit,add) {
if (!this.chan.modelist[CHANMODE_OP][this.user.id] && if ( !this.chan.modelist[CHANMODE_OP][this.user.id]
!this.user.server && !this.user.uline && !(this.mode&USERMODE_ADMIN)) { && !this.user.server
&& !this.user.uline
&& !(this.mode&USERMODE_ADMIN)
) {
this.user.numeric482(this.chan.nam); this.user.numeric482(this.chan.nam);
return 0; return 0;
} }
...@@ -102,15 +101,17 @@ function ChanMode_tweaktmpmode(tmp_bit,add) { ...@@ -102,15 +101,17 @@ function ChanMode_tweaktmpmode(tmp_bit,add) {
} }
function ChanMode_tweaktmpmodelist(tmp_bit,add,arg) { function ChanMode_tweaktmpmodelist(tmp_bit,add,arg) {
if (!this.chan.modelist[CHANMODE_OP][this.user.id] && if ( !this.chan.modelist[CHANMODE_OP][this.user.id]
!this.user.server && !this.user.uline && !(this.mode&USERMODE_ADMIN)) { && !this.user.server
&& !this.user.uline
&& !(this.mode&USERMODE_ADMIN)
) {
this.user.numeric482(this.chan.nam); this.user.numeric482(this.chan.nam);
return 0; return 0;
} }
for (lstitem in this.tmplist[tmp_bit][add]) { for (lstitem in this.tmplist[tmp_bit][add]) {
// Is this argument in our list for this mode already? // Is this argument in our list for this mode already?
if (this.tmplist[tmp_bit][add][lstitem].toUpperCase() == if (this.tmplist[tmp_bit][add][lstitem].toUpperCase() == arg.toUpperCase())
arg.toUpperCase())
return 0; return 0;
} }
// It doesn't exist on our mode, push it in. // It doesn't exist on our mode, push it in.
...@@ -122,8 +123,7 @@ function ChanMode_tweaktmpmodelist(tmp_bit,add,arg) { ...@@ -122,8 +123,7 @@ function ChanMode_tweaktmpmodelist(tmp_bit,add,arg) {
else else
oadd = true; oadd = true;
for (x in this.tmplist[tmp_bit][oadd]) { for (x in this.tmplist[tmp_bit][oadd]) {
if (this.tmplist[tmp_bit][oadd][x].toUpperCase() == if (this.tmplist[tmp_bit][oadd][x].toUpperCase() == arg.toUpperCase()) {
arg.toUpperCase()) {
delete this.tmplist[tmp_bit][oadd][x]; delete this.tmplist[tmp_bit][oadd][x];
return 0; return 0;
} }
...@@ -137,13 +137,14 @@ function ChanMode_affect_mode_list(list_bit) { ...@@ -137,13 +137,14 @@ function ChanMode_affect_mode_list(list_bit) {
tmp_nick = Users[this.tmplist[list_bit][add][z].toUpperCase()]; tmp_nick = Users[this.tmplist[list_bit][add][z].toUpperCase()];
if (!tmp_nick) if (!tmp_nick)
tmp_nick = search_nickbuf(this.tmplist[list_bit][add][z]); tmp_nick = search_nickbuf(this.tmplist[list_bit][add][z]);
if (tmp_nick && (add=="true") && if (tmp_nick && (add=="true") && !this.chan.modelist[list_bit][tmp_nick.id]) {
!this.chan.modelist[list_bit][tmp_nick.id]) {
this.addmodes += MODE[list_bit].modechar; this.addmodes += MODE[list_bit].modechar;
this.addmodeargs += " " + tmp_nick.nick; this.addmodeargs += " " + tmp_nick.nick;
this.chan.modelist[list_bit][tmp_nick.id] = tmp_nick; this.chan.modelist[list_bit][tmp_nick.id] = tmp_nick;
} else if (tmp_nick && (add=="false") && } else if (tmp_nick
this.chan.modelist[list_bit][tmp_nick.id]) { && (add=="false")
&& this.chan.modelist[list_bit][tmp_nick.id]
) {
this.delmodes += MODE[list_bit].modechar; this.delmodes += MODE[list_bit].modechar;
this.delmodeargs += " " + tmp_nick.nick; this.delmodeargs += " " + tmp_nick.nick;
delete this.chan.modelist[list_bit][tmp_nick.id]; delete this.chan.modelist[list_bit][tmp_nick.id];
...@@ -382,14 +383,24 @@ function IRCClient_set_chanmode(chan,modeline,bounce_modes) { ...@@ -382,14 +383,24 @@ function IRCClient_set_chanmode(chan,modeline,bounce_modes) {
// later display. We also play with the channel bit switches here. // later display. We also play with the channel bit switches here.
for (cm in MODE) { for (cm in MODE) {
if (MODE[cm].state) { if (MODE[cm].state) {
if ((cm&CHANMODE_KEY) && (cmode.addbits&CHANMODE_KEY)&& if ( (cm&CHANMODE_KEY)
cmode.state_arg[cm] && chan.arg[cm] && && (cmode.addbits&CHANMODE_KEY)
!this.server && !this.parent && !bounce_modes) { && cmode.state_arg[cm]
this.numeric(467, chan.nam + && chan.arg[cm]
" :Channel key already set."); && !this.server
} else if ((cmode.addbits&cm) && (!(chan.mode&cm) || && !this.parent
((cm==CHANMODE_LIMIT)&&(chan.arg[CHANMODE_LIMIT]!= && !bounce_modes
cmode.state_arg[CHANMODE_LIMIT])) ) ) { ) {
this.numeric(467, format("%s :Channel key already set.", chan.nam));
} else if ( (cmode.addbits&cm)
&& (
!(chan.mode&cm)
|| (
(cm==CHANMODE_LIMIT)
&&(chan.arg[CHANMODE_LIMIT]!=cmode.state_arg[CHANMODE_LIMIT])
)
)
) {
cmode.addmodes += MODE[cm].modechar; cmode.addmodes += MODE[cm].modechar;
chan.mode |= cm; chan.mode |= cm;
if (MODE[cm].args && MODE[cm].state) { if (MODE[cm].args && MODE[cm].state) {
...@@ -413,7 +424,13 @@ function IRCClient_set_chanmode(chan,modeline,bounce_modes) { ...@@ -413,7 +424,13 @@ function IRCClient_set_chanmode(chan,modeline,bounce_modes) {
// we simply display a list of bans on the channel. // we simply display a list of bans on the channel.
if (cmode.addbits&CHANMODE_BAN) { if (cmode.addbits&CHANMODE_BAN) {
for (the_ban in chan.modelist[CHANMODE_BAN]) { for (the_ban in chan.modelist[CHANMODE_BAN]) {
this.numeric(367, chan.nam + " " + chan.modelist[CHANMODE_BAN][the_ban] + " " + chan.bancreator[the_ban] + " " + chan.bantime[the_ban]); this.numeric(367, format(
"%s %s %s %s",
chan.nam,
chan.modelist[CHANMODE_BAN][the_ban],
chan.bancreator[the_ban],
chan.bantime[the_ban]
));
} }
this.numeric(368, chan.nam + " :End of Channel Ban List."); this.numeric(368, chan.nam + " :End of Channel Ban List.");
} }
...@@ -422,8 +439,10 @@ function IRCClient_set_chanmode(chan,modeline,bounce_modes) { ...@@ -422,8 +439,10 @@ function IRCClient_set_chanmode(chan,modeline,bounce_modes) {
for (z in cmode.tmplist[CHANMODE_BAN][true]) { // +b for (z in cmode.tmplist[CHANMODE_BAN][true]) { // +b
var set_ban = create_ban_mask( var set_ban = create_ban_mask(
cmode.tmplist[CHANMODE_BAN][add][z]); cmode.tmplist[CHANMODE_BAN][add][z]);
if ((chan.count_modelist(CHANMODE_BAN) >= max_bans) && if ( (chan.count_modelist(CHANMODE_BAN) >= max_bans)
!this.server && !this.parent) { && !this.server
&& !this.parent
) {
this.numeric(478, chan.nam + " " + set_ban + " :" + this.numeric(478, chan.nam + " " + set_ban + " :" +
"Cannot add ban, channel's ban list is full."); "Cannot add ban, channel's ban list is full.");
} else if (set_ban && !chan.isbanned(set_ban)) { } else if (set_ban && !chan.isbanned(set_ban)) {
...@@ -437,8 +456,9 @@ function IRCClient_set_chanmode(chan,modeline,bounce_modes) { ...@@ -437,8 +456,9 @@ function IRCClient_set_chanmode(chan,modeline,bounce_modes) {
for (z in cmode.tmplist[CHANMODE_BAN][false]) { // -b for (z in cmode.tmplist[CHANMODE_BAN][false]) { // -b
for (ban in chan.modelist[CHANMODE_BAN]) { for (ban in chan.modelist[CHANMODE_BAN]) {
if (cmode.tmplist[CHANMODE_BAN][false][z].toUpperCase() if ( cmode.tmplist[CHANMODE_BAN][false][z].toUpperCase()
== chan.modelist[CHANMODE_BAN][ban].toUpperCase()) { == chan.modelist[CHANMODE_BAN][ban].toUpperCase()
) {
cmode.delmodes += "b"; cmode.delmodes += "b";
cmode.delmodeargs += " " + cmode.delmodeargs += " " +
cmode.tmplist[CHANMODE_BAN][false][z]; cmode.tmplist[CHANMODE_BAN][false][z];
...@@ -559,8 +579,9 @@ function IRCClient_do_join(chan_name,join_key) { ...@@ -559,8 +579,9 @@ function IRCClient_do_join(chan_name,join_key) {
+ " :Cannot join channel (+i: invite only)"); + " :Cannot join channel (+i: invite only)");
return 0; return 0;
} }
if ((chan.mode&CHANMODE_LIMIT) && (true_array_len(chan.users) if ( (chan.mode&CHANMODE_LIMIT)
>= chan.arg[CHANMODE_LIMIT]) ) { && (true_array_len(chan.users) >= chan.arg[CHANMODE_LIMIT])
) {
this.numeric("471", chan.nam this.numeric("471", chan.nam
+ " :Cannot join channel (+l: channel is full)"); + " :Cannot join channel (+l: channel is full)");
return 0; return 0;
...@@ -592,10 +613,13 @@ function IRCClient_do_join(chan_name,join_key) { ...@@ -592,10 +613,13 @@ function IRCClient_do_join(chan_name,join_key) {
} }
} }
if (chan_name[0] != "&") { if (chan_name[0] != "&") {
this.bcast_to_servers_raw(":" + this.nick + " SJOIN " this.bcast_to_servers_raw(
+ chan.created + " " + chan.nam,BAHAMUT); format(":%s SJOIN %s %s",
this.bcast_to_servers_raw(":" + this.nick + " JOIN " this.nick,
+ chan.nam + " " + chan.created,DREAMFORGE); chan.created,
chan.nam
)
);
} }
} else { } else {
// create a new channel // create a new channel
...@@ -610,16 +634,16 @@ function IRCClient_do_join(chan_name,join_key) { ...@@ -610,16 +634,16 @@ function IRCClient_do_join(chan_name,join_key) {
chan.modelist[CHANMODE_OP][this.id] = this; chan.modelist[CHANMODE_OP][this.id] = this;
} }
if (chan_name[0] != "&") { if (chan_name[0] != "&") {
this.bcast_to_servers_raw(":" + servername + " SJOIN " this.bcast_to_servers_raw(
+ chan.created + " " + chan.nam + " " format(":%s SJOIN %s %s %s :%s%s",
+ chan.chanmode() + " :" + create_op + this.nick,BAHAMUT); servername,
this.bcast_to_servers_raw(":" + this.nick + " JOIN " chan.created,
+ chan.nam,DREAMFORGE); chan.nam,
if (create_op) { chan.chanmode(),
server_bcast_to_servers(":" + servername + " MODE " create_op,
+ chan.nam + " +o " + this.nick + " " this.nick
+ chan.created,DREAMFORGE); )
} );
} }
} }
if (this.invited.toUpperCase() == chan.nam.toUpperCase()) if (this.invited.toUpperCase() == chan.nam.toUpperCase())
......
/*
ircd/config.js
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:
https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
Anything that handles manipulating the IRCd configuration.
Copyright 2003-2021 Randy Sommerfeld <cyan@synchro.net>
*/
function parse_nline_flags(flags) {
var nline_flags = 0;
for(thisflag in flags) {
switch(flags[thisflag]) {
case "q":
nline_flags |= NLINE_CHECK_QWKPASSWD;
break;
case "w":
nline_flags |= NLINE_IS_QWKMASTER;
break;
case "k":
nline_flags |= NLINE_CHECK_WITH_QWKMASTER;
break;
default:
log(LOG_WARNING,"!WARNING Unknown N:Line flag '"
+ flags[thisflag] + "' in config.");
break;
}
}
return nline_flags;
}
function parse_oline_flags(flags) {
var oline_flags = 0;
for(thisflag in flags) {
switch(flags[thisflag]) {
case "r":
oline_flags |= OLINE_CAN_REHASH;
break;
case "R":
oline_flags |= OLINE_CAN_RESTART;
break;
case "D":
oline_flags |= OLINE_CAN_DIE;
break;
case "g":
oline_flags |= OLINE_CAN_GLOBOPS;
break;
case "w":
oline_flags |= OLINE_CAN_WALLOPS;
break;
case "l":
oline_flags |= OLINE_CAN_LOCOPS;
break;
case "c":
oline_flags |= OLINE_CAN_LSQUITCON;
break;
case "C":
oline_flags |= OLINE_CAN_GSQUITCON;
break;
case "k":
oline_flags |= OLINE_CAN_LKILL;
break;
case "K":
oline_flags |= OLINE_CAN_GKILL;
break;
case "b":
oline_flags |= OLINE_CAN_KLINE;
break;
case "B":
oline_flags |= OLINE_CAN_UNKLINE;
break;
case "n":
oline_flags |= OLINE_CAN_LGNOTICE;
break;
case "N":
oline_flags |= OLINE_CAN_GGNOTICE;
break;
case "u":
oline_flags |= OLINE_CAN_UMODEC;
break;
case "A":
oline_flags |= OLINE_IS_ADMIN;
break;
case "a":
case "f":
case "F":
break; // All reserved for future use.
case "s":
oline_flags |= OLINE_CAN_CHATOPS;
break;
case "S":
oline_flags |= OLINE_CHECK_SYSPASSWD;
break;
case "x":
case "X":
oline_flags |= OLINE_CAN_DEBUG;
break;
case "O":
oline_flags |= OLINE_IS_GOPER;
oline_flags |= OLINE_CAN_GSQUITCON;
oline_flags |= OLINE_CAN_GKILL;
oline_flags |= OLINE_CAN_GGNOTICE;
oline_flags |= OLINE_CAN_CHATOPS;
case "o":
oline_flags |= OLINE_CAN_REHASH;
oline_flags |= OLINE_CAN_GLOBOPS;
oline_flags |= OLINE_CAN_WALLOPS;
oline_flags |= OLINE_CAN_LOCOPS;
oline_flags |= OLINE_CAN_LSQUITCON;
oline_flags |= OLINE_CAN_LKILL;
oline_flags |= OLINE_CAN_KLINE;
oline_flags |= OLINE_CAN_UNKLINE;
oline_flags |= OLINE_CAN_LGNOTICE;
oline_flags |= OLINE_CAN_UMODEC;
break;
default:
log(LOG_WARNING,"!WARNING Unknown O:Line flag '"
+ flags[thisflag] + "' in config.");
break;
}
}
return oline_flags;
}
function read_config_file() {
/* All of these variables are global. */
Admin1 = "";
Admin2 = "";
Admin3 = "";
CLines = new Array;
HLines = new Array;
ILines = new Array;
KLines = new Array;
NLines = new Array;
OLines = new Array;
PLines = new Array;
QLines = new Array;
ULines = new Array;
diepass = "";
restartpass = "";
YLines = new Array;
ZLines = new Array;
/* End of global variables */
var fname="";
if (config_filename && config_filename.length) {
if(config_filename.indexOf('/')>=0 || config_filename.indexOf('\\')>=0)
fname=config_filename;
else
fname=system.ctrl_dir + config_filename;
} else {
fname=system.ctrl_dir + "ircd." + system.local_host_name + ".conf";
if(!file_exists(fname))
fname=system.ctrl_dir + "ircd." + system.host_name + ".conf";
if(!file_exists(fname))
fname=system.ctrl_dir + "ircd.conf";
}
log(LOG_INFO,"Trying to read configuration from: " + fname);
var file_handle = new File(fname);
if (file_handle.open("r")) {
if (fname.substr(fname.length-3,3) == "ini")
read_ini_config(file_handle);
else
read_conf_config(file_handle);
file_handle.close();
} else {
log("Couldn't open configuration file! Proceeding with defaults.");
}
time_config_read = time();
scan_for_klined_clients();
YLines[0] = new YLine(120,600,1,5050000); // default irc class
}
function ini_sections() {
this.IRCdInfo = ini_IRCdInfo;
this.Port = ini_Port;
this.ConnectClass = ini_ConnectClass;
this.Allow = ini_Allow;
this.Operator = ini_Operator;
this.Services = ini_Services;
this.Ban = ini_Ban;
this.Restrict = ini_Restrict;
this.Hub = ini_Hub;
}
function ini_IRCdInfo(arg, ini) {
log("ircdinfo " + ini.Hostname);
servername=ini.Hostname;
serverdesc=ini.Info;
Admin1=ini.Admin1;
Admin2=ini.Admin2;
Admin3=ini.Admin3;
}
/* Former M:Line */
function ini_Port(arg, ini) {
mline_port = arg;
}
/* Former Y:Line */
function ini_ConnectClass(arg, ini) {
YLines[arg] = new YLine(
parseInt(ini.PingFrequency),
parseInt(ini.ConnectFrequency),
parseInt(ini.Maximum),
parseInt(ini.SendQ)
);
}
/* Former I:Line */
function ini_Allow(arg, ini) {
ILines[arg] = new ILine(
ini.Mask,
null, /* password */
ini.Mask, /* hostmask */
null, /* port */
0 /* irc class */
);
}
/* Former O:Line */
function ini_Operator(arg, ini) {
}
/* Former U:Line */
function ini_Services(arg, ini) {
}
/* Former K:Line & Z:Line */
function ini_Ban(arg, ini) {
}
function ini_Restrict(arg, ini) {
}
/* Former H:Line */
function ini_Hub(arg, ini) {
HLines.push(new HLine(
"*", /* servermask permitted */
arg /* servername */
));
}
function read_ini_config(conf) {
var ini = conf.iniGetAllObjects();
var split;
var section_name;
var section_arg;
var Sections = new ini_sections();
for each(var i in ini) {
split = i.name.split(":");
section_name = split[0];
section_arg = split[1];
if (typeof Sections[section_name] === 'function')
Sections[section_name](section_arg, i);
}
}
function read_conf_config(conf) {
function fancy_split(line) {
var ret = [];
var i;
var s = 0;
var inb = false;
var str;
for (i = 0; i < line.length; i++) {
if (line[i] == ':') {
if (inb)
continue;
if (i > 0 && line[i-1] == ']')
str = line.slice(s, i-1);
else
str = line.slice(s, i);
ret.push(str);
s = i + 1;
}
else if (!inb && line[i] == '[' && s == i) {
inb = true;
s = i + 1;
}
else if (line[i] == ']' && (i+1 == line.length || line[i+1] == ':')) {
inb = false;
}
}
if (s < line.length) {
if (i > 0 && line[i-1] == ']')
str = line.slice(s, i-1);
else
str = line.slice(s, i);
ret.push(str);
}
return ret;
}
while (!conf.eof) {
var conf_line = conf.readln();
if ((conf_line != null) && conf_line.match("[:]")) {
var arg = fancy_split(conf_line);