Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Main
Synchronet
Commits
2c5aa02f
Commit
2c5aa02f
authored
May 22, 2021
by
Rob Swindell
💬
Browse files
Merge branch 'master' into 'master'
IRCd 1.9b See merge request
!126
parents
b6fe381f
c04a8dcd
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
3514 additions
and
2917 deletions
+3514
-2917
exec/ircd.js
exec/ircd.js
+96
-266
exec/load/ircd/channel.js
exec/load/ircd/channel.js
+151
-152
exec/load/ircd/config.js
exec/load/ircd/config.js
+73
-67
exec/load/ircd/core.js
exec/load/ircd/core.js
+966
-520
exec/load/ircd/server.js
exec/load/ircd/server.js
+949
-811
exec/load/ircd/unregistered.js
exec/load/ircd/unregistered.js
+287
-246
exec/load/ircd/user.js
exec/load/ircd/user.js
+826
-817
exec/load/irclib.js
exec/load/irclib.js
+158
-32
text/ircmotd.txt
text/ircmotd.txt
+8
-6
No files found.
exec/ircd.js
View file @
2c5aa02f
...
...
@@ -26,6 +26,7 @@ load("sbbsdefs.js");
load
(
"
sockdefs.js
"
);
load
(
"
nodedefs.js
"
);
load
(
"
irclib.js
"
);
load
(
"
dns.js
"
);
/* Libraries specific to the IRCd */
load
(
"
ircd/core.js
"
);
...
...
@@ -35,293 +36,122 @@ load("ircd/channel.js");
load
(
"
ircd/server.js
"
);
load
(
"
ircd/config.js
"
);
/* Global Constants */
const
VERSION
=
"
SynchronetIRCd-1.9a
"
;
/*** Global Constants - Always in ALL_UPPERCASE ***/
const
VERSION
=
"
SynchronetIRCd-1.9b
"
;
const
VERSION_STR
=
format
(
"
Synchronet %s%s-%s%s (IRCd by Randy Sommerfeld)
"
,
system
.
version
,
system
.
revision
,
system
.
platform
,
system
.
beta_version
);
/* This will be replaced with a dynamic CAPAB system later. */
const
Server_CAPAB
=
"
TS3 NOQUIT SSJOIN BURST UNCONNECT NICKIP TSMODE
"
;
// The number of seconds to block before giving up on outbound CONNECT
// attempts (when connecting to another IRC server -- i.e. a hub) This value
// is important because connecing is a BLOCKING operation, so your IRC *will*
// freeze for the amount of time it takes to connect.
const
ob_sock_timeout
=
3
;
// Should we enable the USERS and SUMMON commands? These allow IRC users to
// view users on the local BBS and summon them to IRC via a Synchronet telegram
// message respectively. Some people might be running the ircd standalone, or
// otherwise don't want anonymous IRC users to have access to these commands.
// We enable this by default because there's typically nothing wrong with
// seeing who's on an arbitrary BBS or summoning them to IRC.
const
enable_users_summon
=
true
;
// EVERY server on the network MUST have the same values in ALL of these
// categories. If you change these, you WILL NOT be able to link to the
// Synchronet IRC network. Linking servers with different values here WILL
// cause your network to desynchronize (and possibly crash the IRCD)
// Remember, this is Synchronet, not Desynchronet ;)
const
max_chanlen
=
100
;
// Maximum channel name length.
const
max_nicklen
=
30
;
// Maximum nickname length.
const
max_modes
=
6
;
// Maximum modes on single MODE command
const
max_user_chans
=
100
;
// Maximum channels users can join
const
max_bans
=
25
;
// Maximum bans (+b) per channel
const
max_topiclen
=
307
;
// Maximum length of topic per channel
const
max_kicklen
=
307
;
// Maximum length of kick reasons
const
max_who
=
100
;
// Maximum replies to WHO for non-oper users
const
max_silence
=
10
;
// Maximum entries on a user's SILENCE list
const
server_uptime
=
time
();
/* This will be replaced with a dynamic CAPAB system */
const
SERVER_CAPAB
=
"
TS3 NOQUIT SSJOIN BURST UNCONNECT NICKIP TSMODE
"
;
/* This will be in the configuration for 2.0 */
const
SUMMON
=
true
;
/* Need to detect when a server doesn't line up with these on the network. */
const
MAX_CHANLEN
=
100
;
/* Maximum channel name length. */
const
MAX_NICKLEN
=
30
;
/* Maximum nickname length. */
const
MAX_MODES
=
6
;
/* Maximum modes on single MODE command */
const
MAX_USER_CHANS
=
100
;
/* Maximum channels users can join */
const
MAX_BANS
=
25
;
/* Maximum bans (+b) per channel */
const
MAX_TOPICLEN
=
307
;
/* Maximum length of topic per channel */
const
MAX_KICKLEN
=
307
;
/* Maximum length of kick reasons */
const
MAX_WHO
=
100
;
/* Maximum replies to WHO for non-oper users */
const
MAX_SILENCE
=
10
;
/* Maximum entries on a user's SILENCE list */
const
MAX_WHOWAS
=
1000
;
/* Size of the WHOWAS buffer */
const
MAX_NICKHISTORY
=
1000
;
/* Size of the nick change history buffer */
const
MAX_CLIENT_RECVQ
=
2560
;
/* Maximum size of unregistered & user recvq */
const
MAX_AWAYLEN
=
80
;
/* Maximum away message length */
const
MAX_USERHOST
=
6
;
/* Maximum arguments to USERHOST command */
const
MAX_REALNAME
=
50
;
/* Maximum length of users real name field */
const
SERVER_UPTIME
=
system
.
timer
;
const
SERVER_UPTIME_STRF
=
strftime
(
"
%a %b %d %Y at %H:%M:%S %Z
"
,
time
());
/*** Global Objects, Arrays and Variables - Always in Mixed_Case ***/
/* Global Objects */
var
DNS_Resolver
=
new
DNS
();
/* Every object (unregistered, server, user) is tagged with a unique ID */
var
Assigned_IDs
=
{};
/* Key: Numeric ID */
var
Unregistered
=
{};
/* Key: Numeric ID */
var
Users
=
{};
/* Key: .toUpperCase() nick */
var
Servers
=
{};
/* Key: .toLowerCase() nick */
var
Channels
=
{};
/* Key: .toUpperCase() channel name, including prefix */
var
Local_Users
=
{};
var
Local_Servers
=
{};
var
WhoWas
=
{};
/* Stores uppercase nicks */
var
WhoWasMap
=
[];
/* An array pointing to WhoWas object entries */
var
NickHistory
=
[];
/* Nick change tracking */
var
Profile
=
{};
/* CPU profiling */
/* Global Variables */
var
Default_Port
=
6667
;
// This will dump all I/O to and from the server to your Synchronet console.
// It also enables some more verbose WALLOPS, especially as they pertain to
// blocking functions.
// The special "DEBUG" oper command also switches this value.
var
debug
=
false
;
var
default_port
=
6667
;
/* This was previously on its own in the functions
Maybe there was a reason why? */
var
time_config_read
;
/* Primary arrays */
var
Unregistered
=
new
Object
;
var
Users
=
new
Object
;
var
Servers
=
new
Object
;
var
Channels
=
new
Object
;
var
Local_Sockets
=
new
Object
;
var
Local_Sockets_Map
=
new
Object
;
var
Selectable_Sockets
=
new
Object
;
var
Selectable_Sockets_Map
=
new
Object
;
/* Highest Connection Count tracking */
var
hcc_total
=
0
;
var
hcc_users
=
0
;
var
hcc_counter
=
0
;
var
WhoWas
=
new
Object
;
/* Stores uppercase nicks */
var
WhoWasMap
=
new
Array
;
/* A true push/pop array pointing to WhoWas entries */
var
WhoWas_Buffer
=
1000
;
/* Maximum number of WhoWas entries to keep track of */
var
NickHistory
=
new
Array
;
/* A true array using push and pop */
var
NickHistorySize
=
1000
;
/* Keep track of commands and how long they take to execute. */
var
Profile
=
new
Object
;
/* This is where our unique ID for each client comes from for unreg'd clients. */
var
next_client_id
=
0
;
// An array containing all the objects containing local sockets that we need
// to poll.
var
Local_Users
=
new
Object
;
var
Local_Servers
=
new
Object
;
var
rebuild_socksel_array
=
true
;
var
network_debug
=
false
;
var
last_recvq_check
=
0
;
var
servername
=
"
server.invalid
"
;
var
serverdesc
=
"
No description provided.
"
;
log
(
VERSION
+
"
started.
"
);
// Parse command-line arguments.
var
config_filename
=
""
;
var
cmdline_port
;
var
cmdarg
;
for
(
cmdarg
=
0
;
cmdarg
<
argc
;
cmdarg
++
)
{
switch
(
argv
[
cmdarg
].
toLowerCase
())
{
case
"
-f
"
:
config_filename
=
argv
[
++
cmdarg
];
break
;
case
"
-p
"
:
cmdline_port
=
parseInt
(
argv
[
++
cmdarg
]);
break
;
case
"
-d
"
:
debug
=
true
;
break
;
case
"
-a
"
:
cmdline_addr
=
argv
[
++
cmdarg
].
split
(
'
,
'
);
break
;
}
}
var
Time_Config_Read
;
/* Stores time() of when the config was last read */
/* Temporary hack to make JSexec testing code not complain */
var
mline_port
;
/* Will this server try to enforce good network behaviour? */
/* Setting to "true" results in bouncing bad modes, KILLing bogus NICKs, etc. */
var
Enforcement
=
true
;
read_config_file
();
/* Highest Connection Count ("HCC") tracking */
var
HCC_Total
=
0
;
var
HCC_Users
=
0
;
var
HCC_Counter
=
0
;
/* This tests if we're running from JSexec or not */
if
(
this
.
server
==
undefined
)
{
if
(
!
jsexec_revision_detail
)
var
jsexec_revision_detail
=
"
JSexec
"
;
var
ServerName
;
var
ServerDesc
=
""
;
if
(
cmdline_port
)
default_port
=
cmdline_port
;
else
if
(
typeof
mline_port
!==
undefined
)
default_port
=
mline_port
;
/* Runtime configuration */
var
Config_Filename
=
""
;
var
server
=
{
socket
:
false
,
terminated
:
false
,
version_detail
:
jsexec_revision_detail
,
interface_ip_addr_list
:
[
"
0.0.0.0
"
,
"
::
"
]
};
var
Restart_Password
;
var
Die_Password
;
server
.
socket
=
create_new_socket
(
default_port
)
var
Admin1
;
var
Admin2
;
var
Admin3
;
if
(
!
server
.
socket
)
exit
();
}
var
CLines
=
[];
/* Server [C]onnect lines */
var
NLines
=
[];
/* Server inbound connect lines */
var
HLines
=
[];
/* Hubs */
var
ILines
=
[];
/* IRC Classes */
var
KLines
=
[];
/* user@hostname based bans */
var
OLines
=
[];
/* IRC Operators */
var
PLines
=
[];
/* Ports for the IRCd to listen to */
var
QLines
=
[];
/* [Q]uarantined (reserved) nicknames */
var
ULines
=
[];
/* Servers allowed to send unchecked MODE amongst other things */
var
YLines
=
[];
/* Defines what user & server objects get what settings */
var
ZLines
=
[];
/* IP based bans */
server
.
socket
.
nonblocking
=
true
;
// REQUIRED!
server
.
socket
.
debug
=
false
;
// Will spam your log if true :)
// Now open additional listening sockets as defined on the P:Line in ircd.conf
var
open_plines
=
new
Array
();
/* True Array */
// Make our 'server' object the first open P:Line
open_plines
[
0
]
=
server
.
socket
;
for
(
pl
in
PLines
)
{
var
new_pl_sock
=
create_new_socket
(
PLines
[
pl
]);
if
(
new_pl_sock
)
{
new_pl_sock
.
nonblocking
=
true
;
new_pl_sock
.
debug
=
false
;
open_plines
.
push
(
new_pl_sock
);
}
}
/** Begin executing code **/
js
.
branch_limit
=
0
;
// we're not an infinite loop.
js
.
auto_terminate
=
false
;
// we handle our own termination requests
/*** Main Loop ***/
while
(
!
js
.
terminated
)
{
if
(
file_date
(
system
.
ctrl_dir
+
"
ircd.rehash
"
)
>
time_config_read
)
read_config_file
();
/* Setup a new socket if a connection is accepted. */
for
(
pl
in
open_plines
)
{
if
(
open_plines
[
pl
].
poll
())
{
var
client_sock
=
open_plines
[
pl
].
accept
();
log
(
LOG_DEBUG
,
"
Accepting new connection on port
"
+
client_sock
.
local_port
);
if
(
client_sock
)
{
client_sock
.
nonblocking
=
true
;
switch
(
client_sock
.
local_port
)
{
case
994
:
case
6697
:
client_sock
.
ssl_server
=
1
;
}
if
(
!
client_sock
.
remote_ip_address
)
{
log
(
LOG_DEBUG
,
"
Socket has no IP address. Closing.
"
);
client_sock
.
close
();
}
else
if
(
iszlined
(
client_sock
.
remote_ip_address
))
{
client_sock
.
send
(
format
(
"
:%s 465 * :You've been Z:Lined from this server.
\r\n
"
,
servername
));
client_sock
.
close
();
}
else
{
var
new_id
=
"
id
"
+
next_client_id
;
next_client_id
++
;
if
(
server
.
client_add
!=
undefined
)
server
.
client_add
(
client_sock
);
if
(
server
.
clients
!=
undefined
)
log
(
LOG_DEBUG
,
format
(
"
%d clients
"
,
server
.
clients
));
Unregistered
[
new_id
]
=
new
Unregistered_Client
(
new_id
,
client_sock
);
}
}
else
log
(
LOG_DEBUG
,
"
!ERROR
"
+
open_plines
[
pl
].
error
+
"
accepting connection
"
);
}
}
log
(
LOG_NOTICE
,
VERSION
+
"
started.
"
);
// Check for pending DNS hostname resolutions.
for
(
this_unreg
in
Unregistered
)
{
if
(
Unregistered
[
this_unreg
]
&&
Unregistered
[
this_unreg
].
pending_resolve_time
)
Unregistered
[
this_unreg
].
resolve_check
();
}
/* If we're running from JSexec we don't have a global server object, so fake one. */
if
(
server
===
undefined
)
{
/* Define the global here so Startup() can manipulate it. */
var
server
=
"
JSexec
"
;
}
// Only rebuild our selectable sockets if required.
if
(
rebuild_socksel_array
)
{
Selectable_Sockets
=
new
Array
;
Selectable_Sockets_Map
=
new
Array
;
for
(
i
in
Local_Sockets
)
{
Selectable_Sockets
.
push
(
Local_Sockets
[
i
]);
Selectable_Sockets_Map
.
push
(
Local_Sockets_Map
[
i
]);
}
rebuild_socksel_array
=
false
;
}
Startup
();
/* Check for ping timeouts and process queues. */
/* FIXME/TODO: These need to be changed to a mapping system ASAP. */
for
(
this_sock
in
Selectable_Sockets
)
{
if
(
Selectable_Sockets_Map
[
this_sock
])
{
Selectable_Sockets_Map
[
this_sock
].
check_timeout
();
Selectable_Sockets_Map
[
this_sock
].
check_queues
();
}
}
js
.
do_callbacks
=
true
;
// do some work.
if
(
Selectable_Sockets
.
length
)
{
var
readme
=
socket_select
(
Selectable_Sockets
,
1
/*secs*/
);
try
{
for
(
thisPolled
in
readme
)
{
if
(
Selectable_Sockets_Map
[
readme
[
thisPolled
]])
{
var
conn
=
Selectable_Sockets_Map
[
readme
[
thisPolled
]];
if
(
!
conn
.
socket
.
is_connected
)
{
conn
.
quit
(
"
Connection reset by peer.
"
);
continue
;
}
conn
.
recvq
.
recv
(
conn
.
socket
);
}
}
}
catch
(
e
)
{
gnotice
(
"
FATAL ERROR:
"
+
e
);
log
(
LOG_ERR
,
"
JavaScript exception:
"
+
e
);
terminate_everything
(
"
A fatal error occured!
"
,
/* ERROR? */
true
);
}
}
else
{
/* Nothing's connected to us, so hang out for a bit */
mswait
(
100
);
}
// Scan C:Lines for servers to connect to automatically.
var
my_cline
;
for
(
thisCL
in
CLines
)
{
my_cline
=
CLines
[
thisCL
];
if
(
my_cline
.
port
&&
YLines
[
my_cline
.
ircclass
].
connfreq
&&
(
YLines
[
my_cline
.
ircclass
].
maxlinks
>
YLines
[
my_cline
.
ircclass
].
active
)
&&
(
search_server_only
(
my_cline
.
servername
)
<
1
)
&&
((
time
()
-
my_cline
.
lastconnect
)
>
YLines
[
my_cline
.
ircclass
].
connfreq
)
)
{
umode_notice
(
USERMODE_ROUTING
,
"
Routing
"
,
format
(
"
Auto-connecting to %s (%s)
"
,
CLines
[
thisCL
].
servername
,
CLines
[
thisCL
].
host
)
);
connect_to_server
(
CLines
[
thisCL
]);
}
function
config_rehash_semaphore_check
()
{
if
(
file_date
(
system
.
ctrl_dir
+
"
ircd.rehash
"
)
>
Time_Config_Read
)
{
Read_Config_File
();
}
}
js
.
setInterval
(
config_rehash_semaphore_check
,
1000
/* milliseconds */
);
Open_PLines
();
/* We
've
exit
ed the main loop, so terminate everything
. */
terminate_everything
(
"
Term
in
a
ted.
"
);
/* We exit
here and pass everything to the callback engine
. */
/* Deuce says I can't use exit(). So just pretend it's here
in
s
te
a
d.
*/
exec/load/ircd/channel.js
View file @
2c5aa02f
...
...
@@ -19,69 +19,60 @@
*/
const
CHANMODE_NONE
=
(
1
<<
0
);
// NONE
const
CHANMODE_BAN
=
(
1
<<
1
);
// b
const
CHANMODE_INVITE
=
(
1
<<
2
);
// i
const
CHANMODE_KEY
=
(
1
<<
3
);
// k
const
CHANMODE_LIMIT
=
(
1
<<
4
);
// l
const
CHANMODE_MODERATED
=
(
1
<<
5
);
// m
const
CHANMODE_NOOUTSIDE
=
(
1
<<
6
);
// n
const
CHANMODE_OP
=
(
1
<<
7
);
// o
const
CHANMODE_PRIVATE
=
(
1
<<
8
);
// p
const
CHANMODE_SECRET
=
(
1
<<
9
);
// s
const
CHANMODE_TOPIC
=
(
1
<<
10
);
// t
const
CHANMODE_VOICE
=
(
1
<<
11
);
// v
/* These are used in the mode crunching section to figure out what character
to display in the crunched MODE line. */
function
Mode
(
modechar
,
args
,
state
,
list
,
isnick
)
{
this
.
modechar
=
modechar
;
/* The mode's character */
this
.
args
=
args
;
/* Does this mode take only a single arg? */
this
.
state
=
state
;
/* Stateful? (changes channel behaviour) */
this
.
list
=
list
;
/* Does this mode accept a list? */
this
.
isnick
=
isnick
;
/* Is nick (true) or a n!u@h mask (false) */
}
/* Channel Modes */
const
CHANMODE_NONE
=
(
1
<<
0
);
const
CHANMODE_BAN
=
(
1
<<
1
);
/* +b */
const
CHANMODE_INVITE
=
(
1
<<
2
);
/* +i */
const
CHANMODE_KEY
=
(
1
<<
3
);
/* +k */
const
CHANMODE_LIMIT
=
(
1
<<
4
);
/* +l */
const
CHANMODE_MODERATED
=
(
1
<<
5
);
/* +m */
const
CHANMODE_NOOUTSIDE
=
(
1
<<
6
);
/* +n */
const
CHANMODE_OP
=
(
1
<<
7
);
/* +o */
const
CHANMODE_PRIVATE
=
(
1
<<
8
);
/* +p */
const
CHANMODE_SECRET
=
(
1
<<
9
);
/* +s */
const
CHANMODE_TOPIC
=
(
1
<<
10
);
/* +t */
const
CHANMODE_VOICE
=
(
1
<<
11
);
/* +v */
const
MODE
=
{};
MODE
[
CHANMODE_BAN
]
=
new
IRC_Channel_Mode
(
"
b
"
,
true
,
false
,
true
,
false
);
MODE
[
CHANMODE_INVITE
]
=
new
IRC_Channel_Mode
(
"
i
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_KEY
]
=
new
IRC_Channel_Mode
(
"
k
"
,
true
,
true
,
false
,
false
);
MODE
[
CHANMODE_LIMIT
]
=
new
IRC_Channel_Mode
(
"
l
"
,
true
,
true
,
false
,
false
);
MODE
[
CHANMODE_MODERATED
]
=
new
IRC_Channel_Mode
(
"
m
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_NOOUTSIDE
]
=
new
IRC_Channel_Mode
(
"
n
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_OP
]
=
new
IRC_Channel_Mode
(
"
o
"
,
true
,
false
,
true
,
true
);
MODE
[
CHANMODE_PRIVATE
]
=
new
IRC_Channel_Mode
(
"
p
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_SECRET
]
=
new
IRC_Channel_Mode
(
"
s
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_TOPIC
]
=
new
IRC_Channel_Mode
(
"
t
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_VOICE
]
=
new
IRC_Channel_Mode
(
"
v
"
,
true
,
false
,
true
,
true
);
/* Object Prototypes */
MODE
=
new
Object
;
MODE
[
CHANMODE_BAN
]
=
new
Mode
(
"
b
"
,
true
,
false
,
true
,
false
);
MODE
[
CHANMODE_INVITE
]
=
new
Mode
(
"
i
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_KEY
]
=
new
Mode
(
"
k
"
,
true
,
true
,
false
,
false
);
MODE
[
CHANMODE_LIMIT
]
=
new
Mode
(
"
l
"
,
true
,
true
,
false
,
false
);
MODE
[
CHANMODE_MODERATED
]
=
new
Mode
(
"
m
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_NOOUTSIDE
]
=
new
Mode
(
"
n
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_OP
]
=
new
Mode
(
"
o
"
,
true
,
false
,
true
,
true
);
MODE
[
CHANMODE_PRIVATE
]
=
new
Mode
(
"
p
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_SECRET
]
=
new
Mode
(
"
s
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_TOPIC
]
=
new
Mode
(
"
t
"
,
false
,
true
,
false
,
false
);
MODE
[
CHANMODE_VOICE
]
=
new
Mode
(
"
v
"
,
true
,
false
,
true
,
true
);
////////// Objects //////////
function
Channel
(
nam
)
{
this
.
nam
=
nam
;
this
.
mode
=
CHANMODE_NONE
;
this
.
topic
=
""
;
this
.
topictime
=
0
;
this
.
topicchangedby
=
""
;
this
.
arg
=
new
Object
;
this
.
nam
=
nam
;
this
.
mode
=
CHANMODE_NONE
;
this
.
topic
=
""
;
this
.
topictime
=
0
;
this
.
topicchangedby
=
""
;
this
.
arg
=
{}
;
this
.
arg
[
CHANMODE_LIMIT
]
=
0
;
this
.
arg
[
CHANMODE_KEY
]
=
""
;
this
.
users
=
new
Object
;
this
.
modelist
=
new
Object
;
this
.
modelist
[
CHANMODE_OP
]
=
new
Object
;
this
.
modelist
[
CHANMODE_VOICE
]
=
new
Object
;
this
.
modelist
[
CHANMODE_BAN
]
=
new
Array
;
/* True Array */
this
.
bantime
=
new
Object
;
this
.
bancreator
=
new
Object
;
this
.
created
=
time
();
this
.
chanmode
=
Channel_chanmode
;
this
.
isbanned
=
Channel_isbanned
;
this
.
count_modelist
=
Channel_count_modelist
;
this
.
occupants
=
Channel_occupants
;
this
.
match_list_mask
=
Channel_match_list_mask
;
this
.
users
=
{};
this
.
modelist
=
{};
this
.
modelist
[
CHANMODE_OP
]
=
{};
this
.
modelist
[
CHANMODE_VOICE
]
=
{};
this
.
modelist
[
CHANMODE_BAN
]
=
[];
this
.
bantime
=
{};
this
.
bancreator
=
{};
this
.
created
=
time
();
/* Functions */
this
.
chanmode
=
Channel_chanmode
;
this
.
isbanned
=
Channel_isbanned
;
this
.
count_modelist
=
Channel_count_modelist
;
this
.
occupants
=
Channel_Occupants
;
this
.
match_list_mask
=
Channel_match_list_mask
;
}
////////// Functions //////////
function
ChanMode_tweaktmpmode
(
tmp_bit
,
add
)
{
if
(
!
this
.
chan
.
modelist
[
CHANMODE_OP
][
this
.
user
.
id
]
&&
!
this
.
user
.
server
...
...
@@ -100,7 +91,9 @@ function ChanMode_tweaktmpmode(tmp_bit,add) {
}
}
function
ChanMode_tweaktmpmodelist
(
tmp_bit
,
add
,
arg
)
{
function
ChanMode_tweaktmpmodelist
(
bit
,
add
,
arg
)
{
var
i
;
if
(
!
this
.
chan
.
modelist
[
CHANMODE_OP
][
this
.
user
.
id
]
&&
!
this
.
user
.
server
&&
!
this
.
user
.
uline
...
...
@@ -109,29 +102,24 @@ function ChanMode_tweaktmpmodelist(tmp_bit,add,arg) {
this
.
user
.
numeric482
(
this
.
chan
.
nam
);
return
0
;
}
for
(
lstitem
in
this
.
tmplist
[
tmp_
bit
][
add
])
{
/
/
Is this argument in our list for this mode already?
if
(
this
.
tmplist
[
tmp_
bit
][
add
][
lstitem
].
toUpperCase
()
==
arg
.
toUpperCase
())
for
(
i
in
this
.
tmplist
[
bit
][
add
])
{
/
*
Is this argument in our list for this mode already?
*/
if
(
this
.
tmplist
[
bit
][
add
][
i
].
toUpperCase
()
==
arg
.
toUpperCase
())
return
0
;
}
// It doesn't exist on our mode, push it in.
this
.
tmplist
[
tmp_bit
][
add
].
push
(
arg
);
// Check for it against the other mode, and maybe nuke it.
var
oadd
;
if
(
add
)
oadd
=
false
;
else
oadd
=
true
;
for
(
x
in
this
.
tmplist
[
tmp_bit
][
oadd
])
{
if
(
this
.
tmplist
[
tmp_bit
][
oadd
][
x
].
toUpperCase
()
==
arg
.
toUpperCase
())
{
delete
this
.
tmplist
[
tmp_bit
][
oadd
][
x
];
/* It doesn't exist on our mode, push it in. */
this
.
tmplist
[
bit
][
add
].
push
(
arg
);
/* Check for it against the other mode, and maybe nuke it. */
for
(
i
in
this
.
tmplist
[
bit
][
add
?
false
:
true
])
{
if
(
this
.
tmplist
[
bit
][
add
?
false
:
true
][
i
].
toUpperCase
()
==
arg
.
toUpperCase
())
{
delete
this
.
tmplist
[
bit
][
add
?
false
:
true
][
i
];
return
0
;
}
}
}
function
ChanMode_affect_mode_list
(
list_bit
)
{
var
tmp_nick
;
var
tmp_nick
,
add
,
z
;
for
(
add
in
this
.
tmplist
[
list_bit
])
{
for
(
z
in
this
.
tmplist
[
list_bit
][
add
])
{
tmp_nick
=
Users
[
this
.
tmplist
[
list_bit
][
add
][
z
].
toUpperCase
()];
...
...
@@ -156,12 +144,15 @@ function ChanMode_affect_mode_list(list_bit) {
}
function
Channel_count_modelist
(
list_bit
)
{
var
tmp_counter
=
0
;
for
(
tmp_count
in
this
.
modelist
[
list_bit
])
{
if
(
this
.
modelist
[
list_bit
][
tmp_count
])
tmp_counter
++
;
var
i
;
var
ret
=
0
;
for
(
i
in
this
.
modelist
[
list_bit
])
{
if
(
this
.
modelist
[
list_bit
][
i
])
ret
++
;
}
return
tmp_counter
;
return
ret
;
}
function
Channel_chanmode
(
show_args
)
{
...
...
@@ -194,32 +185,37 @@ function Channel_chanmode(show_args) {
return
tmp_mode
+
tmp_extras
;
}
function
Channel_isbanned
(
banned_nuh
)
{
for
(
this_ban
in
this
.
modelist
[
CHANMODE_BAN
])
{
if
(
wildmatch
(
banned_nuh
,
this
.
modelist
[
CHANMODE_BAN
][
this_ban
]))
function
Channel_isbanned
(
nuh
)
{
var
i
;
for
(
i
in
this
.
modelist
[
CHANMODE_BAN
])
{
if
(
wildmatch
(
nuh
,
this
.
modelist
[
CHANMODE_BAN
][
i
]))
return
1
;
}
return
0
;
}
function
Channel_occupants
()
{
var
chan_occupants
=
""
;
for
(
thisChannel_user
in
this
.
users
)
{
var
Channel_user
=
this
.
users
[
thisChannel_user
];
if
(
Channel_user
.
nick
)
{
if
(
chan_occupants
)
chan_occupants
+=
"
"
;