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
c04a8dcd
Commit
c04a8dcd
authored
May 22, 2021
by
Randy Sommerfeld
Committed by
Rob Swindell
May 22, 2021
Browse files
IRCd 1.9b
parent
b6fe381f
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 @
c04a8dcd
...
...
@@ -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 @
c04a8dcd
...
...
@@ -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
+=
"
"
;
if
(
this
.
modelist
[
CHANMODE_OP
]