1 /*
2  * Written for BitchX by Colten Edwards (c) Feb 1999
3  */
4 
5 #include "irc.h"
6 static char cvsrevision[] = "$Id: struct.c 110 2011-02-02 12:34:13Z keaston $";
7 CVS_REVISION(struct_c)
8 #include "struct.h"
9 #include "hash.h"
10 #include "hash2.h"
11 #include "misc.h"
12 #include "names.h"
13 #include "window.h"
14 #include "server.h"
15 #define MAIN_SOURCE
16 #include "modval.h"
17 
18 extern char *after_expando(char *, int, int *);
19 
20 /* the types of IrcVariables (repeated in vars.h) */
21 #define BOOL_TYPE_VAR		0
22 #define CHAR_TYPE_VAR		1
23 #define INT_TYPE_VAR		2
24 #define STR_TYPE_VAR		3
25 #define SPECIAL_TYPE_VAR	4
26 
27 #define VAR_READ_WRITE		0
28 #define VAR_READ_ONLY		1
29 
30 static char *struct_name[] = {"WINDOW", "CHANNEL", "NICK", "DCC", "CSET", "USERLIST", "SHITLIST", "BANS", "EXEMPTBANS", "SERVER", "" };
31 
32 #define WINDOW_LOOKUP		0
33 #define CHANNEL_LOOKUP		1
34 #define NICKLIST_LOOKUP 	2
35 #define DCC_LOOKUP		3
36 #define CSET_LOOKUP		4
37 #define USERLIST_LOOKUP		5
38 #define SHITLIST_LOOKUP		6
39 #define BANS_LOOKUP		7
40 #define EXEMPT_LOOKUP		8
41 #define SERVER_LOOKUP		9
42 
43 typedef struct _lookup_struct
44 {
45 	char *code;
46 	int offset;
47 	int type;
48 	int readwrite;
49 } LookupStruct;
50 
51 static LookupStruct server_struct[] = {
52 	{ "NAME",		offsetof(Server, name), STR_TYPE_VAR, VAR_READ_ONLY },
53 	{ "ITSNAME",		offsetof(Server, itsname), STR_TYPE_VAR, VAR_READ_ONLY },
54 	{ "PASSWORD",		offsetof(Server, password), STR_TYPE_VAR, VAR_READ_WRITE },
55 	{ "SNETWORK",		offsetof(Server, snetwork), STR_TYPE_VAR, VAR_READ_WRITE },
56 	{ "COOKIE",		offsetof(Server, cookie), STR_TYPE_VAR, VAR_READ_ONLY },
57 	{ "PORT",		offsetof(Server, port), INT_TYPE_VAR, VAR_READ_ONLY },
58 
59 	{ "NICKNAME",		offsetof(Server, nickname), STR_TYPE_VAR, VAR_READ_ONLY },
60 	{ "USERHOST",		offsetof(Server, userhost), STR_TYPE_VAR, VAR_READ_WRITE },
61 	{ "NICKNAME_PENDING",	offsetof(Server, nickname_pending), INT_TYPE_VAR, VAR_READ_ONLY },
62 	{ "ORIGNICK_PENDING",	offsetof(Server, orignick_pending), INT_TYPE_VAR, VAR_READ_ONLY },
63 
64 	{ "AWAY",		offsetof(Server, away), STR_TYPE_VAR, VAR_READ_WRITE },
65 	{ "AWAYTIME",		offsetof(Server, awaytime), INT_TYPE_VAR, VAR_READ_WRITE },
66 	{ "OPERATOR",		offsetof(Server, operator), BOOL_TYPE_VAR, VAR_READ_ONLY },
67 	{ "SERVER2_8",		offsetof(Server, server2_8), BOOL_TYPE_VAR, VAR_READ_WRITE },
68 	{ "VERSION",		offsetof(Server, version), INT_TYPE_VAR, VAR_READ_WRITE },
69 	{ "VERSION_STRING",	offsetof(Server, version_string), STR_TYPE_VAR, VAR_READ_ONLY },
70 
71 	{ "UMODES",		offsetof(Server, umodes), STR_TYPE_VAR, VAR_READ_ONLY },
72 	{ "UMODE",		offsetof(Server, umode),  CHAR_TYPE_VAR, VAR_READ_ONLY },
73 
74 	{ "CONNECTED",		offsetof(Server, connected), BOOL_TYPE_VAR, VAR_READ_ONLY },
75 
76 	{ "WRITE",		offsetof(Server, write), INT_TYPE_VAR, VAR_READ_ONLY },
77 	{ "READ",		offsetof(Server, read), INT_TYPE_VAR, VAR_READ_ONLY },
78 	{ "EOF",		offsetof(Server, eof), INT_TYPE_VAR, VAR_READ_ONLY },
79 
80 
81 	{ "CHANNEL",		offsetof(Server, chan_list), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
82 	{ "ORIGNICK",		offsetof(Server, orignick), STR_TYPE_VAR, VAR_READ_WRITE },
83 	{ "LAG",		offsetof(Server, lag),	INT_TYPE_VAR, VAR_READ_ONLY },
84 	{ NULL,			0,				0, 0 }
85 };
86 
87 static LookupStruct channel_struct[] = {
88 	{ "CHANNEL",		offsetof(ChannelList, channel), STR_TYPE_VAR, VAR_READ_ONLY },
89 	{ "SERVER",		offsetof(ChannelList, server), INT_TYPE_VAR, VAR_READ_ONLY  },
90 	{ "MODE",		offsetof(ChannelList, s_mode), STR_TYPE_VAR, VAR_READ_ONLY  },
91 	{ "TOPIC",		offsetof(ChannelList, topic), STR_TYPE_VAR, VAR_READ_WRITE  },
92 	{ "TOPIC_LOCK",		offsetof(ChannelList, topic_lock), INT_TYPE_VAR, VAR_READ_WRITE  },
93 
94 	{ "LIMIT",		offsetof(ChannelList, limit), INT_TYPE_VAR, VAR_READ_ONLY  },
95 	{ "KEY",		offsetof(ChannelList, key), STR_TYPE_VAR, VAR_READ_ONLY  },
96 	{ "CHOP",		offsetof(ChannelList, have_op), INT_TYPE_VAR, VAR_READ_ONLY  },
97 	{ "HOP",		offsetof(ChannelList, hop), INT_TYPE_VAR, VAR_READ_ONLY  },
98 	{ "VOICE",		offsetof(ChannelList, voice), INT_TYPE_VAR, VAR_READ_ONLY  },
99 	{ "BOUND",		offsetof(ChannelList, bound), INT_TYPE_VAR, VAR_READ_ONLY  },
100 	{ "CHANPASS",		offsetof(ChannelList, chanpass), STR_TYPE_VAR, VAR_READ_ONLY  },
101 	{ "CONNECTED",		offsetof(ChannelList, connected), INT_TYPE_VAR, VAR_READ_ONLY  },
102 	{ "REFNUM",		offsetof(ChannelList, refnum), INT_TYPE_VAR, VAR_READ_ONLY  },
103 	{ "WINDOW",		offsetof(ChannelList, window), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
104 
105 	{ "NICK",		offsetof(ChannelList, NickListTable), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
106 
107 	{ "MAXIDLE",		offsetof(ChannelList, max_idle), INT_TYPE_VAR, VAR_READ_WRITE  },
108 	{ "TOG_LIMIT",		offsetof(ChannelList, tog_limit), BOOL_TYPE_VAR, VAR_READ_WRITE  },
109 	{ "CHECK_IDLE",		offsetof(ChannelList, check_idle), BOOL_TYPE_VAR, VAR_READ_WRITE  },
110 	{ "DO_SCAN",		offsetof(ChannelList, do_scan), INT_TYPE_VAR, VAR_READ_ONLY  },
111 #if 0
112 	struct timeval	channel_create;		/* time for channel creation */
113 	struct timeval	join_time;		/* time of last join */
114 #endif
115 
116 	{ "STATS_OPS",		offsetof(ChannelList, stats_ops), INT_TYPE_VAR, VAR_READ_WRITE  },
117 	{ "STATS_DOPS",		offsetof(ChannelList, stats_dops), INT_TYPE_VAR, VAR_READ_WRITE  },
118 	{ "STATS_BANS",		offsetof(ChannelList, stats_bans), INT_TYPE_VAR, VAR_READ_WRITE  },
119 	{ "STATS_UNBANS",	offsetof(ChannelList, stats_unbans), INT_TYPE_VAR, VAR_READ_WRITE  },
120 
121 	{ "STATS_SOPS",		offsetof(ChannelList, stats_sops), INT_TYPE_VAR, VAR_READ_WRITE  },
122 	{ "STATS_SDOPS",	offsetof(ChannelList, stats_sdops), INT_TYPE_VAR, VAR_READ_WRITE  },
123 	{ "STATS_SHOPS",	offsetof(ChannelList, stats_shops), INT_TYPE_VAR, VAR_READ_WRITE  },
124 	{ "STATS_SDEHOPS",	offsetof(ChannelList, stats_sdehops), INT_TYPE_VAR, VAR_READ_WRITE  },
125 	{ "STATS_SEBANS",	offsetof(ChannelList, stats_sebans), INT_TYPE_VAR, VAR_READ_WRITE  },
126 	{ "STATS_SUNEBANS",	offsetof(ChannelList, stats_sunebans), INT_TYPE_VAR, VAR_READ_WRITE  },
127 	{ "STATS_SBANS",	offsetof(ChannelList, stats_sbans), INT_TYPE_VAR, VAR_READ_WRITE  },
128 	{ "STATS_SUNBANS",	offsetof(ChannelList, stats_sunbans), INT_TYPE_VAR, VAR_READ_WRITE  },
129 
130 	{ "STATS_TOPICS",	offsetof(ChannelList, stats_topics), INT_TYPE_VAR, VAR_READ_WRITE  },
131 	{ "STATS_KICKS",	offsetof(ChannelList, stats_kicks), INT_TYPE_VAR, VAR_READ_WRITE  },
132 	{ "STATS_PUBS",		offsetof(ChannelList, stats_pubs), INT_TYPE_VAR , VAR_READ_WRITE },
133 	{ "STATS_PARTS",	offsetof(ChannelList, stats_parts), INT_TYPE_VAR , VAR_READ_WRITE },
134 	{ "STATS_SIGNOFFS",	offsetof(ChannelList, stats_signoffs), INT_TYPE_VAR , VAR_READ_WRITE },
135 	{ "STATS_JOINS",	offsetof(ChannelList, stats_joins), INT_TYPE_VAR , VAR_READ_WRITE },
136 	{ "STATS_EBANS",	offsetof(ChannelList, stats_ebans), INT_TYPE_VAR , VAR_READ_WRITE },
137 	{ "STATS_UNEBANS",	offsetof(ChannelList, stats_unebans), INT_TYPE_VAR , VAR_READ_WRITE },
138 	{ "STATS_CHANPASS",	offsetof(ChannelList, stats_chanpass), INT_TYPE_VAR , VAR_READ_WRITE },
139 	{ "STATS_HOPS",		offsetof(ChannelList, stats_hops), INT_TYPE_VAR , VAR_READ_WRITE },
140 	{ "STATS_DHOPS",	offsetof(ChannelList, stats_dhops), INT_TYPE_VAR , VAR_READ_WRITE },
141 	{ "CSET",		offsetof(ChannelList, csets), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
142 
143 	{ "MSGLOG",		offsetof(ChannelList, msglog_on), BOOL_TYPE_VAR , VAR_READ_WRITE },
144 	{ "MSGLOG_FILE",	offsetof(ChannelList, logfile), STR_TYPE_VAR , VAR_READ_WRITE },
145 
146 	{ "TOTALNICKS",		offsetof(ChannelList, totalnicks), INT_TYPE_VAR , VAR_READ_ONLY },
147 	{ "MAXNICKS",		offsetof(ChannelList, maxnicks), INT_TYPE_VAR , VAR_READ_ONLY },
148 	{ "MAXNICKSTIME",	offsetof(ChannelList, maxnickstime), INT_TYPE_VAR , VAR_READ_ONLY },
149 	{ "TOTALBANS",		offsetof(ChannelList, totalbans), INT_TYPE_VAR , VAR_READ_ONLY },
150 	{ "MAXBANS",		offsetof(ChannelList, maxbans), INT_TYPE_VAR , VAR_READ_ONLY },
151 	{ "MAXBANSTIME",	offsetof(ChannelList, maxbanstime), INT_TYPE_VAR , VAR_READ_ONLY },
152 	{ "BANS",		offsetof(ChannelList, bans), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
153 	{ "EXEMPTBANS",		offsetof(ChannelList, exemptbans), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
154 	{ NULL,			0,				0, 0 }
155 };
156 
157 static LookupStruct user_struct[] = {
158 	{ "NICK",		offsetof(UserList, nick),	STR_TYPE_VAR , VAR_READ_WRITE },
159 	{ "HOST",		offsetof(UserList, host),	STR_TYPE_VAR , VAR_READ_WRITE },
160 	{ "COMMENT",		offsetof(UserList, comment),	STR_TYPE_VAR , VAR_READ_WRITE },
161 	{ "CHANNELS",		offsetof(UserList, channels),	STR_TYPE_VAR , VAR_READ_WRITE },
162 	{ "PASSWORD",		offsetof(UserList, password),	STR_TYPE_VAR , VAR_READ_WRITE },
163 	{ "FLAGS",		offsetof(UserList, flags),	INT_TYPE_VAR , VAR_READ_WRITE },
164 	{ "TIME",		offsetof(UserList, time),	INT_TYPE_VAR , VAR_READ_WRITE },
165 	{ NULL,			0,				0, 0 }
166 };
167 
168 static LookupStruct shit_struct[] = {
169 	{ "FILTER",		offsetof(ShitList, filter),	STR_TYPE_VAR , VAR_READ_WRITE },
170 	{ "LEVEL",		offsetof(ShitList, level),	INT_TYPE_VAR , VAR_READ_WRITE },
171 	{ "CHANNELS",		offsetof(ShitList, channels),	STR_TYPE_VAR , VAR_READ_WRITE },
172 	{ "REASON",		offsetof(ShitList, reason),	STR_TYPE_VAR , VAR_READ_WRITE },
173 	{ "TIME",		offsetof(ShitList, time),	INT_TYPE_VAR , VAR_READ_WRITE },
174 	{ NULL,			0,				0, 0 }
175 };
176 
177 static LookupStruct bans_struct[] = {
178 	{ "BAN",		offsetof(BanList, ban),	STR_TYPE_VAR, VAR_READ_ONLY },
179 	{ "SETBY",		offsetof(BanList, setby), STR_TYPE_VAR, VAR_READ_WRITE },
180 	{ "SENT_UNBAN",		offsetof(BanList, sent_unban),INT_TYPE_VAR, VAR_READ_WRITE },
181 	{ "SENT_UNBAN_TIME",	offsetof(BanList, sent_unban_time),INT_TYPE_VAR, VAR_READ_WRITE },
182 	{ "TIME",		offsetof(BanList, time), INT_TYPE_VAR, VAR_READ_ONLY },
183 	{ "COUNT",		offsetof(BanList, count), INT_TYPE_VAR, VAR_READ_ONLY },
184 	{ NULL,			0,				0, 0 }
185 };
186 
187 static LookupStruct dcc_struct[] = {
188 	{ "USER",		offsetof(DCC_int, user),	STR_TYPE_VAR , VAR_READ_WRITE },
189 	{ "USERHOST",		offsetof(DCC_int, userhost),	STR_TYPE_VAR , VAR_READ_WRITE },
190 	{ "SERVER",		offsetof(DCC_int, server),	INT_TYPE_VAR , VAR_READ_ONLY },
191 	{ "ENCRYPT",		offsetof(DCC_int, encrypt),	STR_TYPE_VAR , VAR_READ_ONLY },
192 	{ "FILENAME",		offsetof(DCC_int, filename),	STR_TYPE_VAR , VAR_READ_ONLY },
193 	{ "OTHERNAME",		offsetof(DCC_int, othername),	STR_TYPE_VAR , VAR_READ_ONLY },
194 	{ "BYTES_READ",		offsetof(DCC_int, bytes_read),	INT_TYPE_VAR , VAR_READ_ONLY },
195 	{ "BYTES_SENT",		offsetof(DCC_int, bytes_sent),	INT_TYPE_VAR , VAR_READ_ONLY },
196 	{ "START_OFFSET",	offsetof(DCC_int, transfer_orders.byteoffset), INT_TYPE_VAR , VAR_READ_ONLY },
197 	{ "FILESIZE",		offsetof(DCC_int, filesize),	INT_TYPE_VAR , VAR_READ_ONLY },
198 	{ "PACKETS",		offsetof(DCC_int, packets),	INT_TYPE_VAR , VAR_READ_ONLY },
199 	{ "BLOCKSIZE",		offsetof(DCC_int, blocksize),	INT_TYPE_VAR , VAR_READ_ONLY },
200 	{ "DCC_FAST",		offsetof(DCC_int, dcc_fast),	INT_TYPE_VAR , VAR_READ_ONLY },
201 	{ "REMPORT",		offsetof(DCC_int, remport),	INT_TYPE_VAR , VAR_READ_ONLY },
202 	{ "LOCALPORT",		offsetof(DCC_int, localport),	INT_TYPE_VAR , VAR_READ_ONLY },
203 	{ "DCCNUM",		offsetof(DCC_int, dccnum),	INT_TYPE_VAR , VAR_READ_ONLY },
204 	{ NULL,			0, 				0, 0}
205 };
206 
207 static LookupStruct win_struct[] = {
208 	{ "NAME",		offsetof(Window, name),		STR_TYPE_VAR , VAR_READ_ONLY },
209 	{ "REFNUM",		offsetof(Window, refnum),	INT_TYPE_VAR , VAR_READ_ONLY },
210 	{ "SERVER",		offsetof(Window, server),	INT_TYPE_VAR , VAR_READ_ONLY },
211 	{ "TOP",		offsetof(Window, top),		INT_TYPE_VAR , VAR_READ_ONLY },
212 	{ "BOTTOM",		offsetof(Window, bottom),	INT_TYPE_VAR , VAR_READ_ONLY },
213 	{ "CURSOR",		offsetof(Window, cursor),	INT_TYPE_VAR , VAR_READ_ONLY },
214 	{ "LINE_CNT",		offsetof(Window, line_cnt),	INT_TYPE_VAR , VAR_READ_ONLY },
215 	{ "SCROLL",		offsetof(Window, noscroll),	BOOL_TYPE_VAR , VAR_READ_WRITE },
216 	{ "SCRATCH",		offsetof(Window, scratch_line), BOOL_TYPE_VAR , VAR_READ_WRITE },
217 	{ "COLUMNS",		offsetof(Window, columns),	INT_TYPE_VAR , VAR_READ_ONLY },
218 	{ "NOTIFY_LEVEL",	offsetof(Window, notify_level), INT_TYPE_VAR , VAR_READ_WRITE },
219 	{ "WINDOW_LEVEL",	offsetof(Window, window_level), INT_TYPE_VAR , VAR_READ_WRITE },
220 	{ "CURRENT_CHANNEL",	offsetof(Window, current_channel),STR_TYPE_VAR , VAR_READ_ONLY },
221 	{ "WAITING_CHANNEL",	offsetof(Window, waiting_channel),STR_TYPE_VAR , VAR_READ_ONLY },
222 	{ "BIND_CHANNEL",	offsetof(Window, bind_channel), STR_TYPE_VAR , VAR_READ_ONLY },
223 	{ "QUERY_NICK",		offsetof(Window, query_nick),	STR_TYPE_VAR , VAR_READ_WRITE },
224 	{ "QUERY_HOST",		offsetof(Window, query_host),	STR_TYPE_VAR , VAR_READ_WRITE },
225 	{ "QUERY_CMD",		offsetof(Window, query_cmd),	STR_TYPE_VAR , VAR_READ_WRITE },
226 	{ "LOG",		offsetof(Window, log),		BOOL_TYPE_VAR , VAR_READ_WRITE },
227 	{ "LOGFILE",		offsetof(Window, logfile),	STR_TYPE_VAR , VAR_READ_WRITE },
228 	{ "LASTLOG_LEVEL",	offsetof(Window, lastlog_level),INT_TYPE_VAR , VAR_READ_WRITE },
229 	{ "LASTLOG_SIZE",	offsetof(Window, lastlog_size), INT_TYPE_VAR , VAR_READ_WRITE },
230 	{ "LASTLOG_MAX",	offsetof(Window, lastlog_max),	INT_TYPE_VAR , VAR_READ_WRITE },
231 	{ "HOLD_MODE",		offsetof(Window, hold_mode),	BOOL_TYPE_VAR , VAR_READ_WRITE },
232 	{ "MANGLER",		offsetof(Window, mangler),	BOOL_TYPE_VAR, VAR_READ_WRITE },
233 	{ "PROMPT",		offsetof(Window, prompt),	STR_TYPE_VAR, VAR_READ_WRITE },
234 	{ NULL,			0, 				0, 0}
235 };
236 
237 static LookupStruct nicklist_struct[] = {
238 	{ "NICK",		offsetof(NickList, nick),	STR_TYPE_VAR , VAR_READ_ONLY },
239 	{ "HOST",		offsetof(NickList, host),	STR_TYPE_VAR , VAR_READ_ONLY },
240 	{ "IP",			offsetof(NickList, ip),		STR_TYPE_VAR , VAR_READ_WRITE },
241 	{ "SERVER",		offsetof(NickList, server),	STR_TYPE_VAR , VAR_READ_ONLY },
242 	{ "IP_COUNT",		offsetof(NickList, ip_count),	INT_TYPE_VAR , VAR_READ_ONLY },
243 
244 	{ "USERLIST",		offsetof(NickList, userlist),	SPECIAL_TYPE_VAR , VAR_READ_ONLY },
245 	{ "SHITLIST",		offsetof(NickList, shitlist),	SPECIAL_TYPE_VAR , VAR_READ_ONLY },
246 
247 	{ "FLAGS",		offsetof(NickList, flags),	INT_TYPE_VAR , VAR_READ_ONLY },
248 
249 	{ "IDLE_TIME",		offsetof(NickList, idle_time),	INT_TYPE_VAR , VAR_READ_WRITE },
250 
251 	{ "FLOODCOUNT",		offsetof(NickList, floodcount),	INT_TYPE_VAR , VAR_READ_WRITE },
252 	{ "FLOODTIME",		offsetof(NickList, floodtime),	INT_TYPE_VAR , VAR_READ_WRITE },
253 
254 	{ "NICKCOUNT",		offsetof(NickList, nickcount),	INT_TYPE_VAR , VAR_READ_WRITE },
255 	{ "NICKTIME",		offsetof(NickList, nicktime),	INT_TYPE_VAR , VAR_READ_WRITE },
256 
257 	{ "KICKCOUNT",		offsetof(NickList, kickcount),	INT_TYPE_VAR , VAR_READ_WRITE },
258 	{ "KICKTIME",		offsetof(NickList, kicktime),	INT_TYPE_VAR , VAR_READ_WRITE },
259 
260 	{ "JOINCOUNT",		offsetof(NickList, joincount),	INT_TYPE_VAR , VAR_READ_WRITE },
261 	{ "JOINTIME",		offsetof(NickList, jointime),	INT_TYPE_VAR , VAR_READ_WRITE },
262 
263 
264 	{ "DOPCOUNT",		offsetof(NickList, dopcount),	INT_TYPE_VAR , VAR_READ_WRITE },
265 	{ "DOPTIME",		offsetof(NickList, doptime),	INT_TYPE_VAR , VAR_READ_WRITE },
266 
267 	{ "KICKCOUNT",		offsetof(NickList, bancount),	INT_TYPE_VAR , VAR_READ_WRITE },
268 	{ "KICKTIME",		offsetof(NickList, bantime),	INT_TYPE_VAR , VAR_READ_WRITE },
269 
270 	{ "CREATED",		offsetof(NickList, created),	INT_TYPE_VAR , VAR_READ_ONLY },
271 
272 
273 	{ "STAT_KICKS", 	offsetof(NickList, stat_kicks),INT_TYPE_VAR , VAR_READ_WRITE },
274 	{ "STAT_DOPS",		offsetof(NickList, stat_dops),	INT_TYPE_VAR , VAR_READ_WRITE },
275 	{ "STAT_OPS",		offsetof(NickList, stat_ops),	INT_TYPE_VAR , VAR_READ_WRITE },
276 	{ "STAT_HOPS",		offsetof(NickList, stat_hops),	INT_TYPE_VAR , VAR_READ_WRITE },
277 	{ "STAT_DHOPS",		offsetof(NickList, stat_dhops),INT_TYPE_VAR , VAR_READ_WRITE },
278 	{ "STAT_EBAN",		offsetof(NickList, stat_eban),	INT_TYPE_VAR , VAR_READ_WRITE },
279 	{ "STAT_UNEBAN",	offsetof(NickList, stat_uneban),INT_TYPE_VAR , VAR_READ_WRITE },
280 	{ "STAT_BANS",		offsetof(NickList, stat_bans),	INT_TYPE_VAR , VAR_READ_WRITE },
281 	{ "STAT_UNBANS",	offsetof(NickList, stat_unbans),INT_TYPE_VAR , VAR_READ_WRITE },
282 	{ "STAT_NICKS",		offsetof(NickList, stat_nicks),INT_TYPE_VAR , VAR_READ_WRITE },
283 	{ "STAT_PUB",		offsetof(NickList, stat_pub),	INT_TYPE_VAR , VAR_READ_WRITE },
284 	{ "STAT_TOPICS",	offsetof(NickList, stat_topics),INT_TYPE_VAR , VAR_READ_WRITE },
285 
286 	{ "SENT_REOP",		offsetof(NickList, sent_reop),	INT_TYPE_VAR , VAR_READ_WRITE },
287 	{ "SENT_REOP_TIME",	offsetof(NickList, sent_reop_time),INT_TYPE_VAR , VAR_READ_WRITE },
288 	{ "SENT_VOICE",		offsetof(NickList, sent_voice),	INT_TYPE_VAR , VAR_READ_WRITE },
289 	{ "SENT_VOICE_TIME",	offsetof(NickList, sent_voice_time),INT_TYPE_VAR , VAR_READ_WRITE },
290 	{ "SENT_DEOP",		offsetof(NickList, sent_deop),	INT_TYPE_VAR , VAR_READ_WRITE },
291 	{ "SENT_DEOP_TIME",	offsetof(NickList, sent_deop_time),INT_TYPE_VAR , VAR_READ_WRITE },
292 	{ "NEED_USERHOST",	offsetof(NickList, need_userhost), INT_TYPE_VAR , VAR_READ_ONLY },
293 	{ NULL,			0, 				0, 0}
294 };
295 
296 static LookupStruct cset_struct[] = {
297 	{ "AINV",		offsetof(CSetList, set_ainv), INT_TYPE_VAR, VAR_READ_WRITE },
298 	{ "ANNOY_KICK",		offsetof(CSetList, set_annoy_kick), BOOL_TYPE_VAR, VAR_READ_WRITE },
299 	{ "AOP",		offsetof(CSetList, set_aop), BOOL_TYPE_VAR, VAR_READ_WRITE },
300 	{ "AUTO_JOIN_ON_INVITE",offsetof(CSetList, set_auto_join_on_invite), BOOL_TYPE_VAR, VAR_READ_WRITE },
301 	{ "AUTO_LIMIT",		offsetof(CSetList, set_auto_limit), BOOL_TYPE_VAR, VAR_READ_WRITE },
302 	{ "AUTO_REJOIN",	offsetof(CSetList, set_auto_rejoin), INT_TYPE_VAR, VAR_READ_WRITE },
303 	{ "BANTIME",		offsetof(CSetList, set_bantime), INT_TYPE_VAR, VAR_READ_WRITE },
304 	{ "BITCH",		offsetof(CSetList, bitch_mode), BOOL_TYPE_VAR, VAR_READ_WRITE },
305 	{ "CHANMODE",		offsetof(CSetList, chanmode), STR_TYPE_VAR, VAR_READ_WRITE },
306 
307 	{ "CHANNEL_LOG",	offsetof(CSetList, channel_log), BOOL_TYPE_VAR, VAR_READ_WRITE },
308 	{ "CHANNEL_LOG_FILE",	offsetof(CSetList, channel_log_file), STR_TYPE_VAR, VAR_READ_WRITE },
309 	{ "CHANNEL_LOG_LEVEL",	offsetof(CSetList, log_level), INT_TYPE_VAR, VAR_READ_WRITE },
310 
311 	{ "COMPRESS_MODES",	offsetof(CSetList, compress_modes), BOOL_TYPE_VAR, VAR_READ_WRITE },
312 	{ "CTCP_FLOOD_BAN",	offsetof(CSetList, set_ctcp_flood_ban), BOOL_TYPE_VAR, VAR_READ_WRITE },
313 	{ "DEOPFLOOD",		offsetof(CSetList, set_deopflood), BOOL_TYPE_VAR, VAR_READ_WRITE },
314 	{ "DEOPFLOOD_TIME",	offsetof(CSetList, set_deopflood_time), INT_TYPE_VAR, VAR_READ_WRITE },
315 	{ "DEOP_ON_DEOPFLOOD",	offsetof(CSetList, set_deop_on_deopflood), INT_TYPE_VAR, VAR_READ_WRITE },
316 	{ "DEOP_ON_KICKFLOOD",	offsetof(CSetList, set_deop_on_kickflood), INT_TYPE_VAR, VAR_READ_WRITE },
317 	{ "HACKING",		offsetof(CSetList, set_hacking), INT_TYPE_VAR, VAR_READ_WRITE },
318 	{ "JOINFLOOD",		offsetof(CSetList, set_joinflood), BOOL_TYPE_VAR, VAR_READ_WRITE },
319 	{ "JOINFLOOD_TIME",	offsetof(CSetList, set_joinflood_time), INT_TYPE_VAR, VAR_READ_WRITE },
320 	{ "KICKFLOOD",		offsetof(CSetList, set_kickflood), BOOL_TYPE_VAR, VAR_READ_WRITE },
321 	{ "KICKFLOOD_TIME",	offsetof(CSetList, set_kickflood_time), INT_TYPE_VAR, VAR_READ_WRITE },
322 	{ "KICK_IF_BANNED",	offsetof(CSetList, set_kick_if_banned), BOOL_TYPE_VAR, VAR_READ_WRITE },
323 	{ "KICK_ON_DEOPFLOOD",	offsetof(CSetList, set_kick_on_deopflood), INT_TYPE_VAR, VAR_READ_WRITE },
324 	{ "KICK_ON_JOINFLOOD",	offsetof(CSetList, set_kick_on_joinflood), INT_TYPE_VAR, VAR_READ_WRITE },
325 	{ "KICK_ON_KICKFLOOD",	offsetof(CSetList, set_kick_on_kickflood), INT_TYPE_VAR, VAR_READ_WRITE },
326 	{ "KICK_ON_NICKFLOOD",	offsetof(CSetList, set_kick_on_nickflood), INT_TYPE_VAR, VAR_READ_WRITE },
327 	{ "KICK_ON_PUBFLOOD",	offsetof(CSetList, set_kick_on_pubflood), INT_TYPE_VAR, VAR_READ_WRITE },
328 	{ "KICK_OPS",		offsetof(CSetList, set_kick_ops), BOOL_TYPE_VAR, VAR_READ_WRITE },
329 	{ "LAMEIDENT",		offsetof(CSetList, set_lame_ident), BOOL_TYPE_VAR, VAR_READ_WRITE },
330 	{ "LAMELIST",		offsetof(CSetList, set_lamelist), BOOL_TYPE_VAR, VAR_READ_WRITE },
331 	{ "NICKFLOOD",		offsetof(CSetList, set_nickflood), BOOL_TYPE_VAR, VAR_READ_WRITE },
332 	{ "NICKFLOOD_TIME",	offsetof(CSetList, set_nickflood_time), INT_TYPE_VAR, VAR_READ_WRITE },
333 	{ "PUBFLOOD",		offsetof(CSetList, set_pubflood), BOOL_TYPE_VAR, VAR_READ_WRITE },
334 	{ "PUBFLOOD_IGNORE_TIME",offsetof(CSetList, set_pubflood_ignore), INT_TYPE_VAR, VAR_READ_WRITE },
335 	{ "PUBFLOOD_TIME",	offsetof(CSetList, set_pubflood_time), INT_TYPE_VAR, VAR_READ_WRITE },
336 	{ "SHITLIST",		offsetof(CSetList, set_shitlist), BOOL_TYPE_VAR, VAR_READ_WRITE },
337 	{ "USERLIST",		offsetof(CSetList, set_userlist), BOOL_TYPE_VAR, VAR_READ_WRITE },
338 	{ "CHANNEL",		offsetof(CSetList, channel), STR_TYPE_VAR, VAR_READ_ONLY },
339 	{ NULL,			0, 				0, 0}
340 };
341 
find_structure(char * name)342 int find_structure(char *name)
343 {
344 int i;
345 	for (i = 0; *struct_name[i]; i++)
346 		if (!my_stricmp(struct_name[i], name))
347 			return i;
348 	return -1;
349 }
350 
setup_structure(char * name,char * which,Window ** win,DCC_int ** dcc,ChannelList ** chan,NickList ** nick,int * server)351 int setup_structure(char *name, char *which, Window **win, DCC_int **dcc, ChannelList **chan, NickList **nick, int *server)
352 {
353 	int i;
354 	int serv = -1;
355 	i = find_structure(name);
356 	switch (i)
357 	{
358 		case WINDOW_LOOKUP:
359 		{
360 			*win = get_window_by_desc(which);
361 			if (!*win)
362 				*win = current_window;
363 			return WINDOW_LOOKUP;
364 		}
365 		case NICKLIST_LOOKUP:
366 		{
367 			char *ch = NULL;
368 			if (!*chan)
369 			{
370 				if (!(ch = get_current_channel_by_refnum(0)))
371 					return -1;
372 				if (!(*chan = lookup_channel(ch, current_window->server, 0)))
373 					return -1;
374 			}
375 			if (!ch && !*chan)
376 				return -1;
377 			*nick = find_nicklist_in_channellist(which, *chan, 0);
378 			return NICKLIST_LOOKUP;
379 		}
380 		case DCC_LOOKUP:
381 		{
382 			SocketList *s;
383 			DCC_int *n;
384 			int l = my_atol(which);
385 			s = get_socket(l);
386 			if (!s || !(n = (DCC_int *)s->info))
387 				break;
388 			*dcc = n;
389 			return DCC_LOOKUP;
390 		}
391 		case CHANNEL_LOOKUP:
392 		{
393 			char *ch = which;
394 			if (!*ch)
395 			{
396 				if (!(ch = get_current_channel_by_refnum(0)))
397 					return -1;
398 			}
399 			if (is_channel(ch))
400 				*chan = lookup_channel(ch, current_window->server, 0);
401 			else
402 			{
403 				if ((ch = make_channel(ch)))
404 					*chan = lookup_channel(ch, current_window->server, 0);
405 			}
406 			return CHANNEL_LOOKUP;
407 		}
408 		case SERVER_LOOKUP:
409 			if (*which && ((serv = my_atol(which)) != -1))
410 				*server = serv;
411 			return SERVER_LOOKUP;
412 		default:
413 			break;
414 	}
415 	return -1;
416 }
417 
418 
get_offset_int(void * tmp,int offset)419 static inline int get_offset_int(void *tmp, int offset)
420 {
421 	int val = *(int *)((char *)tmp + offset);
422 	return val;
423 }
424 
get_offset_str(void * tmp,int offset)425 static inline char *get_offset_str(void *tmp, int offset)
426 {
427 	char *s = *(char **)((char *)tmp + offset);
428 	return s;
429 }
430 
get_offset_char(void * tmp,int offset)431 static inline char *get_offset_char(void *tmp, int offset)
432 {
433 	char *s = (char *)((char *)tmp + offset);
434 	return s;
435 }
436 
set_offset_int(void * tmp,int offset,int val)437 static inline void set_offset_int(void *tmp, int offset, int val)
438 {
439 	int *ptr = (int *)((char *)tmp + offset);
440 	*ptr = val;
441 }
442 
set_offset_str(void * tmp,int offset,const char * val)443 static inline void set_offset_str(void *tmp, int offset, const char *val)
444 {
445 	char **ptr = (char **)((char *)tmp + offset);
446 	if (val && *val)
447 		malloc_strcpy(ptr, val);
448 	else
449 		new_free(ptr);
450 }
451 
set_offset_char(void * tmp,int offset,const char * val)452 static inline void set_offset_char(void *tmp, int offset, const char *val)
453 {
454 	char *ptr = (char *)((char *)tmp + offset);
455 	if (val && *val)
456 		strcpy(ptr, val);
457 	else
458 		*ptr = 0;
459 }
460 
lookup_code(LookupStruct * t,char * name)461 int lookup_code(LookupStruct *t, char *name)
462 {
463 	int i;
464 	for (i = 0; t[i].code; i++)
465 	{
466 		if (!my_stricmp(t[i].code, name))
467 			break;
468 	}
469 	if (!t[i].code)
470 		return -1;
471 	return i;
472 }
473 
return_structure(LookupStruct * name,void * user)474 char *return_structure(LookupStruct *name, void *user)
475 {
476 int j;
477 char *ret = NULL;
478 char *s;
479 	if (!user)
480 		return NULL;
481 	for (j = 0; name[j].code; j++)
482 	{
483 		if (name[j].type == INT_TYPE_VAR)
484 			m_s3cat(&ret, ",", ltoa(get_offset_int(user, name[j].offset)));
485 		else if (name[j].type == STR_TYPE_VAR)
486 		{
487 			s = get_offset_str(user, name[j].offset);
488 			m_s3cat(&ret, ",", s ? s : empty_string);
489 		}
490 		else if (name[j].type == BOOL_TYPE_VAR)
491 			m_s3cat(&ret, ",", on_off(get_offset_int(user, name[j].offset)));
492 		else if (name[j].type == CHAR_TYPE_VAR)
493 			m_s3cat(&ret, ",", get_offset_char(user, name[j].offset));
494 		else if (name[j].type == SPECIAL_TYPE_VAR)
495 		{
496 			s = LOCAL_COPY(name[j].code);
497 			lower(s);
498 			m_s3cat(&ret, ",", "<");
499 			malloc_strcat(&ret, s);
500 			malloc_strcat(&ret, ">");
501 		}
502 	}
503 	return ret;
504 }
505 
lookup_structure_item(int idx,LookupStruct * name,void * user,char * arg)506 char *lookup_structure_item(int idx, LookupStruct *name, void *user, char *arg)
507 {
508 	if (!user || (idx == -1))
509 		return NULL;
510 	switch (name[idx].type)
511 	{
512 		case STR_TYPE_VAR:
513 			if (arg && !name[idx].readwrite)
514 				set_offset_str(user, name[idx].offset, arg);
515 			return m_strdup(get_offset_str(user, name[idx].offset));
516 		case CHAR_TYPE_VAR:
517 			if (arg && !name[idx].readwrite)
518 				set_offset_char(user, name[idx].offset, arg);
519 			return m_strdup(get_offset_char(user, name[idx].offset));
520 		case INT_TYPE_VAR:
521 			if (arg && *arg && !name[idx].readwrite)
522 				set_offset_int(user, name[idx].offset, my_atol(arg));
523 			return m_strdup(ltoa(get_offset_int(user, name[idx].offset)));
524 		case BOOL_TYPE_VAR:
525 			if (arg && *arg && !name[idx].readwrite)
526 			{
527 				int val = 0;
528 				if (!my_stricmp(arg, "on"))
529 					val = 1;
530 				else if (!my_stricmp(arg, "off"))
531 					val = 0;
532 				else
533 					val = my_atol(arg);
534 				set_offset_int(user, name[idx].offset, val);
535 			}
536 			return m_strdup(on_off(get_offset_int(user, name[idx].offset)));
537 		default:
538 			break;
539 	}
540 	return NULL;
541 }
542 
lookup_structure_member(int type,char * name,char * rest,NickList * n,ChannelList * ch,Window * w,DCC_int * dcc,int serv)543 char *lookup_structure_member(int type, char *name, char *rest, NickList *n, ChannelList *ch, Window *w, DCC_int *dcc, int serv)
544 {
545 LookupStruct *tmp = NULL;
546 int i = -1;
547 char *ret = NULL;
548 void *user = NULL;
549 int code = -1;
550 	switch (type)
551 	{
552 		case WINDOW_LOOKUP:
553 			tmp = win_struct;
554 			user = w;
555 			break;
556 		case NICKLIST_LOOKUP:
557 			tmp = nicklist_struct;
558 			user = n;
559 			break;
560 		case DCC_LOOKUP:
561 			tmp = dcc_struct;
562 			user = dcc;
563 			break;
564 		case CHANNEL_LOOKUP:
565 			tmp = channel_struct;
566 			user = ch;
567 			break;
568 		case CSET_LOOKUP:
569 			tmp = cset_struct;
570 			if (ch)
571 				user = ch->csets;
572 			break;
573 		case SERVER_LOOKUP:
574 			tmp = server_struct;
575 			if (serv >= 0 && serv < server_list_size())
576 			{
577 				Server *slist = get_server_list();
578 
579 				user = &slist[serv];
580 				ch = slist[serv].chan_list;
581 			}
582 		default:
583 			break;
584 	}
585 	if (!tmp || !user)
586 		return NULL;
587 	if (!name || !*name)
588 		return return_structure(tmp, user);
589  	if ((i = lookup_code(tmp, name)) == -1)
590 		return NULL;
591  	switch(tmp[i].type)
592 	{
593 		case INT_TYPE_VAR:
594 		case STR_TYPE_VAR:
595 		case BOOL_TYPE_VAR:
596 		case CHAR_TYPE_VAR:
597 		{
598 			char *lparen;
599 			if (rest && !*rest)
600 				rest = NULL;
601 #if 0
602 			if ((lparen = strchr(rest+1, '[')))
603 			{
604 				if ((rparen = MatchingBracket(lparen+1, '[', ']')))
605 					*rparen++ = 0;
606 				*lparen++ = 0;
607 				if (!*lparen)
608 					lparen = NULL;
609 			} else if (*rest)
610 #endif
611 				lparen = rest;
612 			ret = lookup_structure_item(i, tmp, user, lparen);
613 			break;
614 		}
615 		case SPECIAL_TYPE_VAR:
616 		{
617 			code = find_structure(name);
618 			switch (code)
619 			{
620 				case NICKLIST_LOOKUP: /* this is a special case */
621 					tmp = nicklist_struct;
622 					n = sorted_nicklist(ch, NICKSORT_NONE);
623 					for (; n; n = n->next)
624 						if (!rest || !*rest)
625 							m_s3cat(&ret, ",", n->nick);
626 						else if (*rest == '>' &&  *(rest+1) && !my_stricmp(rest+1, n->nick))
627 							ret = return_structure(tmp, n);
628 					clear_sorted_nicklist(&n);
629 					return ret;
630 					break;
631 				case USERLIST_LOOKUP:
632 					tmp = user_struct;
633 					if (n)
634 						user = n->userlist;
635 					break;
636 				case SHITLIST_LOOKUP:
637 					tmp = shit_struct;
638 					if (n)
639 						user = n->shitlist;
640 					break;
641 				case CSET_LOOKUP:
642 					tmp = cset_struct;
643 					if (ch)
644 						user = ch->csets;
645 					break;
646 				case WINDOW_LOOKUP:
647 					tmp = win_struct;
648 					if (ch)
649 						user = ch->window;
650 					break;
651 				case EXEMPT_LOOKUP:
652 					tmp = bans_struct;
653 					if (ch)
654 						user = ch->exemptbans;
655 					break;
656 				case BANS_LOOKUP:
657 				{
658 					BanList *b;
659 					tmp = bans_struct;
660 					if (ch)
661 						user = ch->bans;
662 					for (b = ch->bans; b; b= b->next)
663 						if (!rest || !*rest)
664 							m_s3cat(&ret, ",", b->ban);
665 						else if (*rest == '>' &&  *(rest+1) && !my_stricmp(rest+1, b->ban))
666 							ret = return_structure(tmp, b);
667 					return ret;
668 					break;
669 				}
670 				case CHANNEL_LOOKUP:
671 					tmp = channel_struct;
672 					ch = ((Server *)user)->chan_list;
673 					for (; ch; ch = ch->next)
674 						if (!rest || !*rest)
675 							m_s3cat(&ret, ",", ch->channel);
676 						else if (*rest == '>' &&  *(rest+1) && !my_stricmp(rest+1, ch->channel))
677 							ret = return_structure(tmp, ch);
678 					return ret;
679 					break;
680 			}
681 			if (rest && *rest == '>' && *(rest + 1))
682 			{
683 				char *lparen, *rparen;
684 				if ((lparen = strchr(rest+1, '[')))
685 				{
686 					if ((rparen = MatchingBracket(lparen+1, '[', ']')))
687 						*rparen++ = 0;
688 					*lparen++ = 0;
689 				} else if (rest && !*rest)
690 					rest = NULL;
691 				i = lookup_code(tmp, rest+1);
692 				ret = lookup_structure_item(i, tmp, user, lparen);
693 			}
694 			else
695 				ret = return_structure(tmp, user);
696 		}
697 		default:
698 			break;
699 	}
700 	return ret;
701 }
702 
703 
call_structure_internal(char * name,char * args,char * rest,char * rest1)704 char *call_structure_internal(char *name, char *args, char *rest, char *rest1)
705 {
706 	Window		*win	= NULL;
707 	ChannelList	*chan	= NULL;
708 	DCC_int		*dcc	= NULL;
709 	NickList	*nick	= NULL;
710 	char		*ret	= NULL;
711 	int		type =  -1;
712 	int		server = -1;
713 	char		*lparen, *rparen;
714 	type = setup_structure(name, args, &win, &dcc, &chan, &nick, &server);
715 	if ((lparen = strchr(rest, '[')))
716 	{
717 		if ((rparen = MatchingBracket(lparen+1, '[', ']')))
718 			*rparen++ = 0;
719 		*lparen++ = 0;
720 		rest1 = lparen;
721 	}
722 	if (type != -1)
723 		ret = lookup_structure_member(type, rest, rest1, nick, chan, win ? win : current_window, dcc, server);
724 	return ret;
725 }
726