1 /*
2 * funny.c: Well, I put some stuff here and called it funny. So sue me.
3 *
4 * written by michael sandrof
5 *
6 * copyright(c) 1990
7 *
8 * see the copyright file, or do a help ircii copyright
9 */
10
11
12 #include "irc.h"
13 static char cvsrevision[] = "$Id: funny.c 515 2014-10-29 14:07:05Z keaston $";
14 CVS_REVISION(funny_c)
15 #include "struct.h"
16
17 #include "ircaux.h"
18 #include "hook.h"
19 #include "vars.h"
20 #include "funny.h"
21 #include "names.h"
22 #include "server.h"
23 #include "lastlog.h"
24 #include "ircterm.h"
25 #include "output.h"
26 #include "numbers.h"
27 #include "parse.h"
28 #include "status.h"
29 #include "misc.h"
30 #include "screen.h"
31 #define MAIN_SOURCE
32 #include "modval.h"
33
34 static char *match_str = NULL;
35
36 static int funny_min;
37 static int funny_max;
38 static int funny_flags;
39
funny_match(char * stuff)40 void funny_match(char *stuff)
41 {
42 malloc_strcpy(&match_str, stuff);
43 }
44
set_funny_flags(int min,int max,int flags)45 void set_funny_flags(int min, int max, int flags)
46 {
47 funny_min = min;
48 funny_max = max;
49 funny_flags = flags;
50 }
51
52 struct WideListInfoStru
53 {
54 char *channel;
55 int users;
56 };
57
58 typedef struct WideListInfoStru WideList;
59
60 static WideList **wide_list = NULL;
61 static int wl_size = 0;
62 static int wl_elements = 0;
63
64 static int funny_widelist_users (WideList **, WideList **);
65 static int funny_widelist_names (WideList **, WideList **);
66
funny_widelist_users(WideList ** left,WideList ** right)67 static int funny_widelist_users(WideList **left, WideList **right)
68 {
69 if ((**left).users > (**right).users)
70 return -1;
71 else if ((**right).users > (**left).users)
72 return 1;
73 else
74 return my_stricmp((**left).channel, (**right).channel);
75 }
76
funny_widelist_names(WideList ** left,WideList ** right)77 static int funny_widelist_names(WideList **left, WideList **right)
78 {
79 int comp;
80
81 if (!(comp = my_stricmp((**left).channel, (**right).channel)))
82 return comp;
83 else if ((**left).users > (**right).users)
84 return -1;
85 else if ((**right).users > (**left).users)
86 return 1;
87 else
88 return 0;
89 }
90
91
funny_print_widelist(void)92 void funny_print_widelist(void)
93 {
94 int i;
95 char buffer1[BIG_BUFFER_SIZE];
96 char buffer2[BIG_BUFFER_SIZE];
97 char *ptr;
98
99 if (!wide_list)
100 return;
101
102 if (funny_flags & FUNNY_NAME)
103 qsort((void *) wide_list, wl_elements, sizeof(WideList *),
104 (int (*) (const void *, const void *)) funny_widelist_names);
105 else if (funny_flags & FUNNY_USERS)
106 qsort((void *) wide_list, wl_elements, sizeof(WideList *),
107 (int (*) (const void *, const void *)) funny_widelist_users);
108
109 set_display_target(NULL, LOG_CRAP);
110 *buffer1 = '\0';
111 for (i = 1; i < wl_elements; i++)
112 {
113 snprintf(buffer2, sizeof buffer2, "%s(%d) ", wide_list[i]->channel,
114 wide_list[i]->users);
115 ptr = strchr(buffer1, '\0');
116 if (strlen(buffer1) + strlen(buffer2) > current_term->TI_cols - 5)
117 {
118 if (do_hook(WIDELIST_LIST, "%s", buffer1))
119 put_it("%s", convert_output_format(fget_string_var(FORMAT_WIDELIST_FSET), "%s %s", update_clock(GET_TIME), buffer1));
120 *buffer1 = 0;
121 strcat(buffer1, buffer2);
122 }
123 else
124 strcpy(ptr, buffer2);
125 }
126 if (*buffer1 && do_hook(WIDELIST_LIST, "%s", buffer1))
127 put_it("%s", convert_output_format(fget_string_var(FORMAT_WIDELIST_FSET), "%s %s", update_clock(GET_TIME), buffer1));
128
129 reset_display_target();
130 for (i = 0; i < wl_elements; i++)
131 {
132 new_free(&wide_list[i]->channel);
133 new_free((char **)&wide_list[i]);
134 }
135 new_free((char **)&wide_list);
136 wl_elements = wl_size = 0;
137 }
138
funny_list(char * from,char ** ArgList)139 void funny_list(char *from, char **ArgList)
140 {
141 char *channel,
142 *user_cnt,
143 *line;
144 WideList **new_list;
145 int cnt;
146 static char format[30];
147 static int last_width = -1;
148
149 if (last_width != get_int_var(CHANNEL_NAME_WIDTH_VAR))
150 {
151 if ((last_width = get_int_var(CHANNEL_NAME_WIDTH_VAR)) != 0)
152 snprintf(format, sizeof format, "%%s %%-%u.%us %%-5s %%s", /*thing_ansi,*/
153 (unsigned char) last_width,
154 (unsigned char) last_width);
155 else
156 snprintf(format, sizeof format, "%%s %%s %%-5s %%s"/*, thing_ansi*/);
157 }
158 channel = ArgList[0];
159 user_cnt = ArgList[1];
160 line = PasteArgs(ArgList, 2);
161 if (funny_flags & FUNNY_TOPIC && !(line && *line))
162 return;
163 cnt = my_atol(user_cnt);
164 if (funny_min && (cnt < funny_min))
165 return;
166 if (funny_max && (cnt > funny_max))
167 return;
168 if ((funny_flags & FUNNY_PRIVATE) && (*channel != '*'))
169 return;
170 if ((funny_flags & FUNNY_PUBLIC) && ((*channel == '*') || (*channel == '@')))
171 return;
172 if (match_str)
173 {
174 if (wild_match(match_str, channel) == 0)
175 return;
176 }
177 if (funny_flags & FUNNY_WIDE)
178 {
179 if (wl_elements >= wl_size)
180 {
181 new_list = (WideList **) new_malloc(sizeof(WideList *) *
182 (wl_size + 50));
183 memset(new_list, 0, sizeof(WideList *) * (wl_size + 50));
184 if (wl_size)
185 memcpy(new_list, wide_list, sizeof(WideList *) * wl_size);
186 wl_size += 50;
187 new_free((char **)&wide_list);
188 wide_list = new_list;
189 }
190 wide_list[wl_elements] = (WideList *)
191 new_malloc(sizeof(WideList));
192 wide_list[wl_elements]->channel = NULL;
193 wide_list[wl_elements]->users = cnt;
194 malloc_strcpy(&wide_list[wl_elements]->channel,
195 (*channel != '*') ? channel : "Prv");
196 wl_elements++;
197 return;
198 }
199 set_display_target(channel, LOG_CRAP);
200 if (do_hook(current_numeric, "%s %s %s %s", from, channel, user_cnt,
201 line) && do_hook(LIST_LIST, "%s %s %s", channel, user_cnt, line))
202 {
203 if (channel && user_cnt)
204 put_it("%s", convert_output_format(fget_string_var(FORMAT_LIST_FSET),"%s %s %s %s", update_clock(GET_TIME), *channel == '*'?"Prv":channel, user_cnt, line));
205 }
206 reset_display_target();
207 }
208
209 /* print_funny_names
210 *
211 * This handles presenting the output of a NAMES reply. It is a cut-down
212 * version of the /SCAN output formatting.
213 */
print_funny_names(char * line)214 void print_funny_names(char *line)
215 {
216 char *t;
217 int count = 0;
218 char buffer[BIG_BUFFER_SIZE];
219 int cols = get_int_var(NAMES_COLUMNS_VAR);
220
221 if (!cols)
222 cols = 1;
223
224 if (line && *line)
225 {
226 *buffer = 0;
227
228 while ((t = next_arg(line, &line))) {
229 char *nick;
230 char *nick_format;
231 char nick_buffer[BIG_BUFFER_SIZE];
232
233 if (!count && fget_string_var(FORMAT_NAMES_BANNER_FSET))
234 strlcat(buffer, convert_output_format(
235 fget_string_var(FORMAT_NAMES_BANNER_FSET), NULL, NULL),
236 sizeof buffer);
237
238 /* Seperate the nick and the possible status presets that might
239 * preceede it. */
240 nick = t + strspn(t, "@%+~-");
241 nick_format = fget_string_var(isme(nick) ?
242 FORMAT_NAMES_NICK_ME_FSET : FORMAT_NAMES_NICK_FSET);
243 strlcpy(nick_buffer,
244 convert_output_format(nick_format, "%s", nick),
245 sizeof nick_buffer);
246
247 if (nick != t)
248 {
249 char special = *t;
250
251 if (special == '+')
252 strlcat(buffer,
253 convert_output_format(
254 fget_string_var(FORMAT_NAMES_USER_VOICE_FSET),
255 "%c %s", special, nick_buffer), sizeof buffer);
256 else
257 strlcat(buffer,
258 convert_output_format(
259 fget_string_var(FORMAT_NAMES_USER_CHANOP_FSET),
260 "%c %s", special, nick_buffer), sizeof buffer);
261 }
262 else
263 strlcat(buffer,
264 convert_output_format(
265 fget_string_var(FORMAT_NAMES_USER_FSET), ". %s",
266 nick_buffer), sizeof buffer);
267
268 strlcat(buffer, space, sizeof buffer);
269
270 if (++count >= cols)
271 {
272 put_it("%s", buffer);
273 *buffer = 0;
274 count = 0;
275 }
276 }
277
278 if (count)
279 put_it("%s", buffer);
280 }
281 }
282
funny_namreply(char * from,char ** Args)283 void funny_namreply(char *from, char **Args)
284 {
285 char *type,
286 *channel;
287 static char format[40];
288 static int last_width = -1;
289 register char *ptr;
290 register char *line;
291 int user_count = 0;
292
293 PasteArgs(Args, 2);
294 type = Args[0];
295 channel = Args[1];
296 line = Args[2];
297
298 /* protocol violation by server */
299 if (!channel || !line)
300 return;
301
302 ptr = line;
303 while (*ptr)
304 {
305 while (*ptr && (*ptr != ' '))
306 ptr++;
307 user_count++;
308 while (*ptr && (*ptr == ' '))
309 ptr++;
310 }
311
312 if (in_join_list(channel, from_server))
313 {
314 set_display_target(channel, LOG_CRAP);
315 if (do_hook(current_numeric, "%s %s %s %s", from, type, channel,line)
316 && do_hook(NAMES_LIST, "%s %s", channel, line)
317 && get_int_var(SHOW_CHANNEL_NAMES_VAR))
318 {
319 put_it("%s", convert_output_format(fget_string_var(FORMAT_NAMES_FSET), "%s %s %d %d",update_clock(GET_TIME), channel, user_count, user_count));
320 print_funny_names(line);
321 }
322 if ((user_count == 1) && (*line == '@'))
323 got_info(channel, from_server, GOTNAMES | GOTNEW);
324 else
325 got_info(channel, from_server, GOTNAMES);
326 reset_display_target();
327 return;
328 }
329 if (last_width != get_int_var(CHANNEL_NAME_WIDTH_VAR))
330 {
331 if ((last_width = get_int_var(CHANNEL_NAME_WIDTH_VAR)) != 0)
332 snprintf(format, sizeof format, "%%s: %%-%u.%us %%s",
333 (unsigned char) last_width,
334 (unsigned char) last_width);
335 else
336 strcpy(format, "%s: %s\t%s");
337 }
338 if (funny_min && (user_count < funny_min))
339 return;
340 else if (funny_max && (user_count > funny_max))
341 return;
342 if ((funny_flags & FUNNY_PRIVATE) && (*type == '='))
343 return;
344 if ((funny_flags & FUNNY_PUBLIC) && ((*type == '*') || (*type == '@')))
345 return;
346 if (type && channel)
347 {
348 if (match_str)
349 {
350 if (wild_match(match_str, channel) == 0)
351 return;
352 }
353 if (do_hook(current_numeric, "%s %s %s %s", from, type, channel, line) && do_hook(NAMES_LIST, "%s %s", channel, line))
354 {
355 set_display_target(channel, LOG_CRAP);
356 if (fget_string_var(FORMAT_NAMES_FSET))
357 {
358 put_it("%s", convert_output_format(fget_string_var(FORMAT_NAMES_FSET), "%s %s %d %d", update_clock(GET_TIME), channel, user_count, user_count));
359 print_funny_names(line);
360 }
361 else
362 {
363 switch (*type)
364 {
365 case '=':
366 if (last_width &&(strlen(channel) > last_width))
367 {
368 channel[last_width-1] = '>';
369 channel[last_width] = (char) 0;
370 }
371 put_it(format, "Pub", channel, line);
372 break;
373 case '*':
374 put_it(format, "Prv", channel, line);
375 break;
376 case '@':
377 put_it(format, "Sec", channel, line);
378 break;
379 }
380 }
381 reset_display_target();
382 }
383 }
384 }
385
funny_mode(char * from,char ** ArgList)386 void funny_mode(char *from, char **ArgList)
387 {
388 char *mode, *channel;
389 ChannelList *chan = NULL;
390
391 if (!ArgList[0]) return;
392
393 channel = ArgList[0];
394 mode = ArgList[1];
395 PasteArgs(ArgList, 1);
396
397 if (in_join_list(channel, from_server))
398 {
399 update_channel_mode(from, channel, from_server, mode, chan);
400 update_all_status(current_window, NULL, 0);
401 got_info(channel, from_server, GOTMODE);
402 }
403 else
404 {
405 set_display_target(channel, LOG_CRAP);
406 if (do_hook(current_numeric, "%s %s %s", from, channel, mode))
407 put_it("%s", convert_output_format(fget_string_var(FORMAT_MODE_CHANNEL_FSET), "%s %s %s %s %s", update_clock(GET_TIME), from, *FromUserHost ? FromUserHost:"�", channel, mode));
408 reset_display_target();
409 }
410 }
411
update_user_mode(char * modes)412 void update_user_mode(char *modes)
413 {
414 int onoff = 1;
415 char *p_umodes = get_possible_umodes(from_server);
416
417 for (; *modes; modes++)
418 {
419 if (*modes == '-')
420 onoff = 0;
421 else if (*modes == '+')
422 onoff = 1;
423
424 else if ((*modes >= 'a' && *modes <= 'z')
425 || (*modes >= 'A' && *modes <= 'Z'))
426 {
427 size_t idx;
428 int c = *modes;
429
430 idx = ccspan(p_umodes, c);
431 if (p_umodes[idx] == 0)
432 ircpanic("Invalid user mode referenced");
433 set_server_flag(from_server, idx, onoff);
434
435 if (c == 'o' || c == 'O')
436 set_server_operator(from_server, onoff);
437 #if 0
438 char c = tolower(*modes);
439 size_t idx = (size_t) (strchr(umodes, c) - umodes);
440
441 set_server_flag(from_server, USER_MODE << idx, onoff);
442
443 if (c == 'o' || c == 'O')
444 set_server_operator(from_server, onoff);
445 #endif
446 }
447 }
448 }
449
reinstate_user_modes(void)450 void reinstate_user_modes (void)
451 {
452 char *modes = get_umode(from_server);
453 if (modes && *modes)
454 send_to_server("MODE %s +%s", get_server_nickname(from_server), modes);
455 }
456