Coverage Report

Created: 2025-11-09 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/irssi/src/fe-common/irc/fe-events-numeric.c
Line
Count
Source
1
/*
2
 fe-events-numeric.c : irssi
3
4
    Copyright (C) 1999-2000 Timo Sirainen
5
6
    This program is free software; you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation; either version 2 of the License, or
9
    (at your option) any later version.
10
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
16
    You should have received a copy of the GNU General Public License along
17
    with this program; if not, write to the Free Software Foundation, Inc.,
18
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
*/
20
21
#include "module.h"
22
#include <irssi/src/fe-common/irc/module-formats.h>
23
#include <irssi/src/core/signals.h>
24
#include <irssi/src/core/misc.h>
25
#include <irssi/src/core/settings.h>
26
#include <irssi/src/core/levels.h>
27
#include <irssi/src/core/recode.h>
28
29
#include <irssi/src/irc/core/irc-servers.h>
30
#include <irssi/src/irc/core/irc-channels.h>
31
#include <irssi/src/core/nicklist.h>
32
#include <irssi/src/irc/core/mode-lists.h>
33
34
#include <irssi/src/fe-common/core/module-formats.h>
35
#include <irssi/src/fe-common/core/printtext.h>
36
#include <irssi/src/fe-common/core/fe-channels.h>
37
#include <irssi/src/fe-common/irc/fe-irc-server.h>
38
#include <irssi/src/fe-common/irc/fe-irc-channels.h>
39
40
static void print_event_received(IRC_SERVER_REC *server, const char *data,
41
         const char *nick, int target_param);
42
43
static char *last_away_nick = NULL;
44
static char *last_away_msg = NULL;
45
46
static void event_user_mode(IRC_SERVER_REC *server, const char *data)
47
963
{
48
963
  char *params, *mode;
49
50
963
  g_return_if_fail(data != NULL);
51
963
  g_return_if_fail(server != NULL);
52
53
963
  params = event_get_params(data, 2, NULL, &mode);
54
963
        printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_USER_MODE,
55
963
                    g_strchomp(mode));
56
963
  g_free(params);
57
963
}
58
59
static void event_ison(IRC_SERVER_REC *server, const char *data)
60
433
{
61
433
  char *params, *online;
62
63
433
  g_return_if_fail(data != NULL);
64
433
  g_return_if_fail(server != NULL);
65
66
433
  params = event_get_params(data, 2, NULL, &online);
67
433
  printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_ONLINE, online);
68
433
  g_free(params);
69
433
}
70
71
static void event_names_list(IRC_SERVER_REC *server, const char *data)
72
21.8k
{
73
21.8k
  IRC_CHANNEL_REC *chanrec;
74
21.8k
  char *params, *channel, *names;
75
76
21.8k
  g_return_if_fail(data != NULL);
77
78
21.8k
  params = event_get_params(data, 4, NULL, NULL, &channel, &names);
79
80
21.8k
  chanrec = irc_channel_find(server, channel);
81
21.8k
  if (chanrec == NULL || chanrec->names_got) {
82
9.29k
    printformat_module("fe-common/core", server, channel,
83
9.29k
           MSGLEVEL_CRAP, TXT_NAMES,
84
9.29k
           channel, 0, 0, 0, 0, 0);
85
9.29k
                printtext(server, channel, MSGLEVEL_CRAP, "%s", names);
86
87
9.29k
  }
88
21.8k
  g_free(params);
89
21.8k
}
90
91
static void event_end_of_names(IRC_SERVER_REC *server, const char *data,
92
             const char *nick)
93
21.4k
{
94
21.4k
  IRC_CHANNEL_REC *chanrec;
95
21.4k
  char *params, *channel;
96
97
21.4k
  g_return_if_fail(data != NULL);
98
99
21.4k
  params = event_get_params(data, 2, NULL, &channel);
100
101
21.4k
  chanrec = irc_channel_find(server, channel);
102
21.4k
  if (chanrec == NULL || chanrec->names_got)
103
11.7k
    print_event_received(server, data, nick, FALSE);
104
21.4k
  g_free(params);
105
21.4k
}
106
107
static void event_who(IRC_SERVER_REC *server, const char *data)
108
23.0k
{
109
23.0k
  char *params, *nick, *channel, *user, *host, *stat, *realname, *hops;
110
23.0k
  char *serv, *recoded;
111
112
23.0k
  g_return_if_fail(data != NULL);
113
114
23.0k
  params = event_get_params(data, 8, NULL, &channel, &user,
115
23.0k
          &host, &serv, &nick, &stat, &realname);
116
117
  /* split hops/realname */
118
23.0k
  hops = realname;
119
147k
  while (*realname != '\0' && *realname != ' ') realname++;
120
23.0k
  if (*realname == ' ')
121
134
    *realname++ = '\0';
122
123
23.0k
  recoded = recode_in(SERVER(server), realname, nick);
124
23.0k
  printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHO,
125
23.0k
        channel, nick, stat, hops, user, host, recoded, serv);
126
127
23.0k
  g_free(params);
128
23.0k
  g_free(recoded);
129
23.0k
}
130
131
static void event_end_of_who(IRC_SERVER_REC *server, const char *data)
132
253
{
133
253
  char *params, *channel;
134
135
253
  g_return_if_fail(data != NULL);
136
137
253
  params = event_get_params(data, 2, NULL, &channel);
138
253
  printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_END_OF_WHO, channel);
139
253
  g_free(params);
140
253
}
141
142
static void event_ban_list(IRC_SERVER_REC *server, const char *data)
143
3.82k
{
144
3.82k
  IRC_CHANNEL_REC *chanrec;
145
3.82k
  BAN_REC *banrec;
146
3.82k
  const char *channel;
147
3.82k
  char *params, *ban, *setby, *tims, *timestr, *ago;
148
149
3.82k
  g_return_if_fail(data != NULL);
150
151
3.82k
  params = event_get_params(data, 5, NULL, &channel,
152
3.82k
          &ban, &setby, &tims);
153
3.82k
  timestr = my_asctime((time_t) atoll(tims));
154
3.82k
  ago = time_ago((time_t) atoll(tims));
155
156
3.82k
  chanrec = irc_channel_find(server, channel);
157
3.82k
  banrec = chanrec == NULL ? NULL : banlist_find(chanrec->banlist, ban);
158
159
3.82k
  channel = get_visible_target(server, channel);
160
3.82k
  printformat(server, channel, MSGLEVEL_CRAP,
161
3.82k
              *setby == '\0' ? IRCTXT_BANLIST : IRCTXT_BANLIST_LONG,
162
3.82k
              banrec == NULL ? 0 : g_slist_index(chanrec->banlist, banrec) + 1, channel, ban,
163
3.82k
              setby, ago, timestr);
164
165
3.82k
  g_free(timestr);
166
3.82k
  g_free(params);
167
3.82k
}
168
169
static void event_eban_list(IRC_SERVER_REC *server, const char *data)
170
1.05k
{
171
1.05k
  const char *channel;
172
1.05k
  char *params, *ban, *setby, *tims, *timestr, *ago;
173
174
1.05k
  g_return_if_fail(data != NULL);
175
176
1.05k
  params = event_get_params(data, 5, NULL, &channel,
177
1.05k
          &ban, &setby, &tims);
178
1.05k
  timestr = my_asctime((time_t) atoll(tims));
179
1.05k
  ago = time_ago((time_t) atoll(tims));
180
181
1.05k
  channel = get_visible_target(server, channel);
182
1.05k
  printformat(server, channel, MSGLEVEL_CRAP,
183
1.05k
              *setby == '\0' ? IRCTXT_EBANLIST : IRCTXT_EBANLIST_LONG, channel, ban, setby,
184
1.05k
              timestr, ago);
185
186
1.05k
  g_free(timestr);
187
1.05k
  g_free(params);
188
1.05k
}
189
190
static void do_quiet_list(IRC_SERVER_REC *server, const char *channel, char *ban, char *setby,
191
                          char *tims)
192
979
{
193
979
  char *timestr, *ago;
194
195
979
  timestr = my_asctime((time_t) atoll(tims));
196
979
  ago = time_ago((time_t) atoll(tims));
197
198
979
  channel = get_visible_target(server, channel);
199
979
  printformat(server, channel, MSGLEVEL_CRAP,
200
979
              *setby == '\0' ? IRCTXT_QUIETLIST : IRCTXT_QUIETLIST_LONG, channel, ban, setby,
201
979
              ago, timestr);
202
203
979
  g_free(timestr);
204
979
}
205
206
static void event_quiet_list(IRC_SERVER_REC *server, const char *data)
207
96
{
208
96
  const char *channel;
209
96
  char *params, *ban, *setby, *tims;
210
211
96
  g_return_if_fail(data != NULL);
212
213
96
  params = event_get_params(data, 6, NULL, &channel, NULL, &ban, &setby, &tims);
214
96
  do_quiet_list(server, channel, ban, setby, tims);
215
216
96
  g_free(params);
217
96
}
218
219
static void event_silence_list(IRC_SERVER_REC *server, const char *data)
220
272
{
221
272
  char *params, *nick, *mask;
222
223
272
  g_return_if_fail(data != NULL);
224
225
272
  params = event_get_params(data, 3, NULL, &nick, &mask);
226
272
  printformat(server, NULL, MSGLEVEL_CRAP,
227
272
        IRCTXT_SILENCE_LINE, nick, mask);
228
272
  g_free(params);
229
272
}
230
231
static void event_accept_list(IRC_SERVER_REC *server, const char *data)
232
478
{
233
478
  char *params, *accepted;
234
235
478
  g_return_if_fail(data != NULL);
236
478
  g_return_if_fail(server != NULL);
237
238
478
  params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
239
478
      NULL, &accepted);
240
478
  printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_ACCEPT_LIST, accepted);
241
478
  g_free(params);
242
478
}
243
244
static void event_invite_list(IRC_SERVER_REC *server, const char *data)
245
575
{
246
575
  const char *channel;
247
575
  char *params, *invite, *setby, *tims, *timestr, *ago;
248
249
575
  g_return_if_fail(data != NULL);
250
251
575
  params = event_get_params(data, 5, NULL, &channel, &invite,
252
575
      &setby, &tims);
253
575
  timestr = my_asctime((time_t) atoll(tims));
254
575
  ago = time_ago((time_t) atoll(tims));
255
256
575
  channel = get_visible_target(server, channel);
257
575
  printformat(server, channel, MSGLEVEL_CRAP,
258
575
              *setby == '\0' ? IRCTXT_INVITELIST : IRCTXT_INVITELIST_LONG, channel, invite,
259
575
              setby, timestr, ago);
260
261
575
  g_free(timestr);
262
575
  g_free(params);
263
575
}
264
265
static void event_nick_in_use(IRC_SERVER_REC *server, const char *data)
266
4.15k
{
267
4.15k
  char *params, *nick;
268
269
4.15k
  g_return_if_fail(data != NULL);
270
271
4.15k
  params = event_get_params(data, 2, NULL, &nick);
272
4.15k
  if (server->connected) {
273
622
    printformat(server, NULL, MSGLEVEL_CRAP,
274
622
          IRCTXT_NICK_IN_USE, nick);
275
622
  }
276
277
4.15k
  g_free(params);
278
4.15k
}
279
280
static void event_topic_get(IRC_SERVER_REC *server, const char *data)
281
1.96k
{
282
1.96k
  const char *channel;
283
1.96k
  char *params, *topic, *recoded;
284
285
1.96k
  g_return_if_fail(data != NULL);
286
287
1.96k
  params = event_get_params(data, 3, NULL, &channel, &topic);
288
1.96k
  recoded = recode_in(SERVER(server), topic, channel);
289
1.96k
  channel = get_visible_target(server, channel);
290
1.96k
  printformat(server, channel, MSGLEVEL_CRAP,
291
1.96k
        IRCTXT_TOPIC, channel, recoded);
292
1.96k
  g_free(params);
293
1.96k
  g_free(recoded);
294
1.96k
}
295
296
static void event_topic_info(IRC_SERVER_REC *server, const char *data)
297
3.20k
{
298
3.20k
  const char *channel;
299
3.20k
  char *params, *timestr, *bynick, *byhost, *topictime;
300
301
3.20k
  g_return_if_fail(data != NULL);
302
303
3.20k
  params = event_get_params(data, 4, NULL, &channel,
304
3.20k
          &bynick, &topictime);
305
306
3.20k
        timestr = my_asctime((time_t) atol(topictime));
307
308
3.20k
  byhost = strchr(bynick, '!');
309
3.20k
  if (byhost != NULL)
310
1.03k
    *byhost++ = '\0';
311
312
3.20k
  channel = get_visible_target(server, channel);
313
3.20k
  printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_TOPIC_INFO,
314
3.20k
        bynick, timestr, byhost == NULL ? "" : byhost);
315
3.20k
  g_free(timestr);
316
3.20k
  g_free(params);
317
3.20k
}
318
319
static void event_channel_mode(IRC_SERVER_REC *server, const char *data)
320
1.90k
{
321
1.90k
  const char *channel;
322
1.90k
  char *params, *mode;
323
324
1.90k
  g_return_if_fail(data != NULL);
325
326
1.90k
  params = event_get_params(data, 3 | PARAM_FLAG_GETREST,
327
1.90k
          NULL, &channel, &mode);
328
1.90k
  channel = get_visible_target(server, channel);
329
1.90k
  printformat(server, channel, MSGLEVEL_CRAP,
330
1.90k
        IRCTXT_CHANNEL_MODE, channel, g_strchomp(mode));
331
1.90k
  g_free(params);
332
1.90k
}
333
334
static void event_channel_created(IRC_SERVER_REC *server, const char *data)
335
1.11k
{
336
1.11k
  const char *channel;
337
1.11k
  char *params, *createtime, *timestr;
338
339
1.11k
  g_return_if_fail(data != NULL);
340
341
1.11k
  params = event_get_params(data, 3, NULL, &channel, &createtime);
342
343
1.11k
        timestr = my_asctime((time_t) atol(createtime));
344
1.11k
  channel = get_visible_target(server, channel);
345
1.11k
  printformat(server, channel, MSGLEVEL_CRAP,
346
1.11k
        IRCTXT_CHANNEL_CREATED, channel, timestr);
347
1.11k
  g_free(timestr);
348
1.11k
  g_free(params);
349
1.11k
}
350
351
static void event_nowaway(IRC_SERVER_REC *server, const char *data)
352
14.5k
{
353
14.5k
  printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_AWAY);
354
14.5k
}
355
356
static void event_unaway(IRC_SERVER_REC *server, const char *data)
357
12.3k
{
358
12.3k
  printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_UNAWAY);
359
12.3k
}
360
361
static void event_away(IRC_SERVER_REC *server, const char *data)
362
1.55k
{
363
1.55k
  char *params, *nick, *awaymsg, *recoded;
364
365
1.55k
  g_return_if_fail(data != NULL);
366
367
1.55k
  params = event_get_params(data, 3, NULL, &nick, &awaymsg);
368
1.55k
  recoded = recode_in(SERVER(server), awaymsg, nick);
369
1.55k
  if (!settings_get_bool("show_away_once") ||
370
1.55k
      last_away_nick == NULL ||
371
1.55k
      g_ascii_strcasecmp(last_away_nick, nick) != 0 ||
372
1.11k
      last_away_msg == NULL ||
373
1.11k
      g_ascii_strcasecmp(last_away_msg, awaymsg) != 0) {
374
    /* don't show the same away message
375
       from the same nick all the time */
376
715
    g_free_not_null(last_away_nick);
377
715
    g_free_not_null(last_away_msg);
378
715
    last_away_nick = g_strdup(nick);
379
715
    last_away_msg = g_strdup(awaymsg);
380
381
715
    printformat(server, nick, MSGLEVEL_CRAP,
382
715
          IRCTXT_NICK_AWAY, nick, recoded);
383
715
  }
384
1.55k
  g_free(params);
385
1.55k
  g_free(recoded);
386
1.55k
}
387
388
static void event_userhost(IRC_SERVER_REC *server, const char *data)
389
725
{
390
725
  char *params, *hosts;
391
392
725
  g_return_if_fail(data != NULL);
393
394
725
  params = event_get_params(data, 2, NULL, &hosts);
395
725
  printtext(server, NULL, MSGLEVEL_CRAP, "%s", hosts);
396
725
  g_free(params);
397
725
}
398
399
static void event_sent_invite(IRC_SERVER_REC *server, const char *data)
400
651
{
401
651
        char *params, *nick, *channel;
402
403
651
  g_return_if_fail(data != NULL);
404
405
651
  params = event_get_params(data, 3, NULL, &nick, &channel);
406
651
  printformat(server, nick, MSGLEVEL_CRAP,
407
651
        IRCTXT_INVITING, nick, channel);
408
651
  g_free(params);
409
651
}
410
411
static void event_chanserv_url(IRC_SERVER_REC *server, const char *data)
412
818
{
413
818
  const char *channel;
414
818
  char *params, *url;
415
416
818
  g_return_if_fail(data != NULL);
417
418
818
  params = event_get_params(data, 3, NULL, &channel, &url);
419
818
  channel = get_visible_target(server, channel);
420
818
  printformat(server, channel, MSGLEVEL_CRAP,
421
818
        IRCTXT_CHANNEL_URL, channel, url);
422
818
  g_free(params);
423
818
}
424
425
static void event_target_unavailable(IRC_SERVER_REC *server, const char *data,
426
             const char *nick, const char *addr)
427
9.44k
{
428
9.44k
  IRC_CHANNEL_REC *chanrec;
429
9.44k
  char *params, *target;
430
431
9.44k
  g_return_if_fail(data != NULL);
432
433
9.44k
  params = event_get_params(data, 2, NULL, &target);
434
9.44k
  if (!server_ischannel(SERVER(server), target)) {
435
    /* nick unavailable */
436
4.95k
    printformat(server, NULL, MSGLEVEL_CRAP,
437
4.95k
          IRCTXT_NICK_UNAVAILABLE, target);
438
4.95k
  } else {
439
4.48k
    chanrec = irc_channel_find(server, target);
440
4.48k
    if (chanrec != NULL && chanrec->joined) {
441
      /* dalnet - can't change nick while being banned */
442
2.11k
      print_event_received(server, data, nick, FALSE);
443
2.37k
    } else {
444
      /* channel is unavailable. */
445
2.37k
      printformat(server, NULL, MSGLEVEL_CRAP,
446
2.37k
            IRCTXT_JOINERROR_UNAVAIL, target);
447
2.37k
    }
448
4.48k
  }
449
450
9.44k
  g_free(params);
451
9.44k
}
452
453
static void event_no_such_nick(IRC_SERVER_REC *server, const char *data,
454
             const char *nick, const char *addr)
455
3.56k
{
456
3.56k
  char *params, *unick;
457
458
3.56k
  g_return_if_fail(data != NULL);
459
460
3.56k
  params = event_get_params(data, 2, NULL, &unick);
461
3.56k
  if (!g_strcmp0(unick, "*"))
462
    /* more information will be in the description,
463
     * e.g. * :Target left IRC. Failed to deliver: [hi] */
464
427
    print_event_received(server, data, nick, FALSE);
465
3.14k
  else
466
3.14k
    printformat(server, unick, MSGLEVEL_CRAP, IRCTXT_NO_SUCH_NICK, unick);
467
3.56k
  g_free(params);
468
3.56k
}
469
470
static void event_no_such_channel(IRC_SERVER_REC *server, const char *data)
471
3.56k
{
472
3.56k
  char *params, *channel;
473
474
3.56k
  g_return_if_fail(data != NULL);
475
476
3.56k
  params = event_get_params(data, 2, NULL, &channel);
477
3.56k
  printformat(server, channel, MSGLEVEL_CRAP,
478
3.56k
        IRCTXT_NO_SUCH_CHANNEL, channel);
479
3.56k
  g_free(params);
480
3.56k
}
481
482
static void cannot_join(IRC_SERVER_REC *server, const char *data, int format)
483
3.49k
{
484
3.49k
  char *params, *channel;
485
486
3.49k
  g_return_if_fail(data != NULL);
487
488
3.49k
  params = event_get_params(data, 2, NULL, &channel);
489
3.49k
  printformat(server, NULL, MSGLEVEL_CRAP, format, channel);
490
3.49k
  g_free(params);
491
3.49k
}
492
493
static void event_too_many_channels(IRC_SERVER_REC *server, const char *data)
494
421
{
495
421
  cannot_join(server, data, IRCTXT_JOINERROR_TOOMANY);
496
421
}
497
498
static void event_duplicate_channel(IRC_SERVER_REC *server, const char *data,
499
    const char *nick)
500
4.32k
{
501
4.32k
  char *params, *channel, *p;
502
503
4.32k
  g_return_if_fail(data != NULL);
504
505
  /* this new addition to ircd breaks completely with older
506
     "standards", "nick Duplicate ::!!channel ...." */
507
4.32k
  params = event_get_params(data, 3, NULL, NULL, &channel);
508
4.32k
  p = strchr(channel, ' ');
509
4.32k
  if (p != NULL) *p = '\0';
510
511
4.32k
  if (channel[0] == '!' && channel[1] == '!') {
512
645
    printformat(server, NULL, MSGLEVEL_CRAP,
513
645
          IRCTXT_JOINERROR_DUPLICATE, channel+1);
514
645
  } else
515
3.68k
    print_event_received(server, data, nick, FALSE);
516
517
4.32k
  g_free(params);
518
4.32k
}
519
520
static void event_channel_is_full(IRC_SERVER_REC *server, const char *data)
521
797
{
522
797
  cannot_join(server, data, IRCTXT_JOINERROR_FULL);
523
797
}
524
525
static void event_invite_only(IRC_SERVER_REC *server, const char *data)
526
834
{
527
834
  cannot_join(server, data, IRCTXT_JOINERROR_INVITE);
528
834
}
529
530
static void event_banned(IRC_SERVER_REC *server, const char *data)
531
202
{
532
202
  cannot_join(server, data, IRCTXT_JOINERROR_BANNED);
533
202
}
534
535
static void event_bad_channel_key(IRC_SERVER_REC *server, const char *data)
536
780
{
537
780
  cannot_join(server, data, IRCTXT_JOINERROR_BAD_KEY);
538
780
}
539
540
static void event_bad_channel_mask(IRC_SERVER_REC *server, const char *data)
541
461
{
542
461
  cannot_join(server, data, IRCTXT_JOINERROR_BAD_MASK);
543
461
}
544
545
static void event_477(IRC_SERVER_REC *server, const char *data, const char *nick)
546
5.58k
{
547
  /* Numeric 477 can mean many things:
548
   * modeless channel, cannot join/send to channel (+r/+R/+M).
549
   * If we tried to join this channel, display the error in the
550
   * status window. Otherwise display it in the channel window.
551
   */
552
5.58k
  IRC_CHANNEL_REC *chanrec;
553
5.58k
  char *params, *channel;
554
555
5.58k
  g_return_if_fail(data != NULL);
556
557
5.58k
  params = event_get_params(data, 2, NULL, &channel);
558
559
5.58k
  chanrec = irc_channel_find(server, channel);
560
5.58k
  print_event_received(server, data, nick, chanrec == NULL || chanrec->joined);
561
5.58k
  g_free(params);
562
5.58k
}
563
564
static void event_489(IRC_SERVER_REC *server, const char *data, const char *nick)
565
1.43k
{
566
  /* Numeric 489 can mean one of two things things:
567
   * cannot join to channel (secure only), or not chanop or voice.
568
   * If we tried to join this channel, display the joinerror.
569
   * Otherwise depending on the channel being joined or not
570
   * display the error in the channel or status window.
571
   */
572
1.43k
  IRC_CHANNEL_REC *chanrec;
573
1.43k
  char *params, *channel;
574
575
1.43k
  g_return_if_fail(data != NULL);
576
577
1.43k
  params = event_get_params(data, 2, NULL, &channel);
578
579
1.43k
  chanrec = irc_channel_find(server, channel);
580
1.43k
  if (chanrec != NULL && !chanrec->joined) {
581
0
    cannot_join(server, data, IRCTXT_JOINERROR_SECURE_ONLY);
582
1.43k
  } else {
583
1.43k
    print_event_received(server, data, nick, chanrec == NULL || chanrec->joined);
584
1.43k
  }
585
1.43k
  g_free(params);
586
1.43k
}
587
588
static void event_help(IRC_SERVER_REC *server, int formatnum, const char *data)
589
1.89k
{
590
  /* Common handling for umerics 704 (RPL_HELPSTART), 705 (RPL_HELPTXT),
591
   * and 706 (RPL_ENDOFHELP); sent as a reply to HELP or HELPOP command.
592
   */
593
1.89k
  char *params, *topic, *help_text;
594
595
1.89k
  g_return_if_fail(data != NULL);
596
597
1.89k
  params = event_get_params(data, 3, NULL, &topic, &help_text);
598
599
1.89k
  g_return_if_fail(help_text != NULL);
600
601
1.89k
  if (help_text[0] == '\0') {
602
    /* Empty lines can be used by servers for styling; and we need to replace
603
     * them with something non-empty or they would be dropped when displayed.
604
     */
605
1.20k
    help_text = " ";
606
1.20k
  }
607
608
1.89k
  printformat(server, NULL, MSGLEVEL_CRAP, formatnum, topic, help_text);
609
1.89k
  g_free(params);
610
1.89k
}
611
612
static void event_helpstart(IRC_SERVER_REC *server, const char *data, const char *nick)
613
1.19k
{
614
  /* Numeric 704 (RPL_HELPSTART) sent as a reply to HELP or HELPOP command.
615
   */
616
1.19k
  event_help(server, IRCTXT_SERVER_HELP_START, data);
617
1.19k
}
618
619
static void event_helptxt(IRC_SERVER_REC *server, const char *data, const char *nick)
620
375
{
621
  /* Numeric 705 (RPL_HELPTXT), sent as a reply to HELP or HELPOP command.
622
   */
623
375
  event_help(server, IRCTXT_SERVER_HELP_TXT, data);
624
375
}
625
626
static void event_endofhelp(IRC_SERVER_REC *server, const char *data, const char *nick)
627
318
{
628
  /* Numeric 706 (RPL_ENDOFHELP), sent as a reply to HELP or HELPOP command.
629
   */
630
318
  event_help(server, IRCTXT_SERVER_END_OF_HELP, data);
631
318
}
632
633
static void event_target_too_fast(IRC_SERVER_REC *server, const char *data,
634
          const char *nick)
635
1.20k
{
636
  /* Target change too fast, could be nick or channel.
637
   * If we tried to join this channel, display the error in the
638
   * status window. Otherwise display it in the channel window.
639
   */
640
1.20k
  IRC_CHANNEL_REC *chanrec;
641
1.20k
  char *params, *channel;
642
643
1.20k
  g_return_if_fail(data != NULL);
644
645
1.20k
  params = event_get_params(data, 2, NULL, &channel);
646
647
1.20k
  chanrec = irc_channel_find(server, channel);
648
1.20k
  print_event_received(server, data, nick, chanrec == NULL || chanrec->joined);
649
1.20k
  g_free(params);
650
1.20k
}
651
652
static void event_unknown_mode(IRC_SERVER_REC *server, const char *data)
653
663
{
654
663
  char *params, *mode;
655
656
663
  g_return_if_fail(data != NULL);
657
658
663
  params = event_get_params(data, 2, NULL, &mode);
659
663
  printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_UNKNOWN_MODE, mode);
660
663
  g_free(params);
661
663
}
662
663
static void event_numeric(IRC_SERVER_REC *server, const char *data,
664
        const char *nick)
665
158k
{
666
158k
  data = strchr(data, ' ');
667
158k
  if (data != NULL)
668
113k
                print_event_received(server, data+1, nick, FALSE);
669
158k
}
670
671
static void print_event_received(IRC_SERVER_REC *server, const char *data,
672
         const char *nick, int target_param)
673
217k
{
674
217k
  char *target, *args, *ptr, *ptr2, *recoded;
675
217k
  int format;
676
677
217k
  g_return_if_fail(data != NULL);
678
679
        /* first param is our nick, "*" or a channel */
680
217k
  ptr = strchr(data, ' ');
681
217k
  if (ptr == NULL)
682
83.5k
    return;
683
134k
  ptr++;
684
685
134k
  if (server_ischannel(SERVER(server), data)) /* directed at channel */
686
11.7k
    target = g_strndup(data, (int)(ptr - data - 1));
687
122k
  else if (!target_param || *ptr == ':' || (ptr2 = strchr(ptr, ' ')) == NULL)
688
118k
    target = NULL;
689
3.65k
  else {
690
                /* target parameter expected and present */
691
3.65k
                target = g_strndup(ptr, (int) (ptr2-ptr));
692
3.65k
  }
693
694
  /* param1 param2 ... :last parameter */
695
134k
  if (*ptr == ':') {
696
                /* only one parameter */
697
4.52k
    args = g_strdup(ptr+1);
698
129k
  } else {
699
129k
    args = g_strdup(ptr);
700
129k
    ptr = strstr(args, " :");
701
129k
    if (ptr != NULL)
702
7.99k
      memmove(ptr+1, ptr+2, strlen(ptr+1));
703
129k
  }
704
705
134k
  recoded = recode_in(SERVER(server), args, NULL);
706
134k
  format = nick == NULL || server->real_address == NULL ||
707
8.25k
    g_strcmp0(nick, server->real_address) == 0 ?
708
133k
    IRCTXT_DEFAULT_EVENT : IRCTXT_DEFAULT_EVENT_SERVER;
709
134k
  printformat(server, target, MSGLEVEL_CRAP, format,
710
134k
        nick, recoded, current_server_event);
711
712
134k
  g_free(recoded);
713
134k
  g_free(args);
714
134k
  g_free(target);
715
134k
}
716
717
static void event_received(IRC_SERVER_REC *server, const char *data,
718
         const char *nick)
719
70.4k
{
720
70.4k
        print_event_received(server, data, nick, FALSE);
721
70.4k
}
722
723
static void event_target_received(IRC_SERVER_REC *server, const char *data,
724
          const char *nick)
725
4.32k
{
726
4.32k
        print_event_received(server, data, nick, TRUE);
727
4.32k
}
728
729
static void event_hybrid_quiet_list(IRC_SERVER_REC *server, const char *data)
730
1.49k
{
731
1.49k
  const char *channel;
732
1.49k
  char *params, *ban, *setby, *tims;
733
734
1.49k
  g_return_if_fail(data != NULL);
735
736
1.49k
  params = event_get_params(data, 5, NULL, &channel, &ban, &setby, &tims);
737
738
1.49k
  if (*tims == '\0') {
739
    /* probably not a quiet list */
740
615
    event_target_received(server, data, NULL);
741
615
    return;
742
615
  }
743
744
883
  do_quiet_list(server, channel, ban, setby, tims);
745
746
883
  g_free(params);
747
883
}
748
749
static void event_motd(IRC_SERVER_REC *server, const char *data,
750
           const char *nick, const char *addr)
751
3.79k
{
752
  /* don't ignore motd anymore after 3 seconds of connection time -
753
     we might have called /MOTD */
754
3.79k
  if (settings_get_bool("skip_motd") && !server->motd_got)
755
0
    return;
756
757
3.79k
        print_event_received(server, data, nick, FALSE);
758
3.79k
}
759
760
static void sig_empty(void)
761
69
{
762
69
}
763
764
void fe_events_numeric_init(void)
765
2
{
766
2
  last_away_nick = NULL;
767
2
  last_away_msg = NULL;
768
769
  /* clang-format off */
770
2
  signal_add("event 221", (SIGNAL_FUNC) event_user_mode);
771
2
  signal_add("event 303", (SIGNAL_FUNC) event_ison);
772
2
  signal_add("event 353", (SIGNAL_FUNC) event_names_list);
773
2
  signal_add_first("event 366", (SIGNAL_FUNC) event_end_of_names);
774
2
  signal_add("event 352", (SIGNAL_FUNC) event_who);
775
2
  signal_add("event 315", (SIGNAL_FUNC) event_end_of_who);
776
2
  signal_add("event 271", (SIGNAL_FUNC) event_silence_list);
777
2
  signal_add("event 272", (SIGNAL_FUNC) sig_empty);
778
2
  signal_add("event 281", (SIGNAL_FUNC) event_accept_list);
779
2
  signal_add("event 367", (SIGNAL_FUNC) event_ban_list);
780
2
  signal_add("event 348", (SIGNAL_FUNC) event_eban_list);
781
2
  signal_add("event 728", (SIGNAL_FUNC) event_quiet_list);
782
2
  signal_add("event 344", (SIGNAL_FUNC) event_hybrid_quiet_list); /* used by ircd-hybrid */
783
2
  signal_add("event 346", (SIGNAL_FUNC) event_invite_list);
784
2
  signal_add("event 433", (SIGNAL_FUNC) event_nick_in_use);
785
2
  signal_add("event 332", (SIGNAL_FUNC) event_topic_get);
786
2
  signal_add("event 333", (SIGNAL_FUNC) event_topic_info);
787
2
  signal_add("event 324", (SIGNAL_FUNC) event_channel_mode);
788
2
  signal_add("event 329", (SIGNAL_FUNC) event_channel_created);
789
2
  signal_add("event 306", (SIGNAL_FUNC) event_nowaway);
790
2
  signal_add("event 305", (SIGNAL_FUNC) event_unaway);
791
2
  signal_add("event 301", (SIGNAL_FUNC) event_away);
792
2
  signal_add("event 328", (SIGNAL_FUNC) event_chanserv_url);
793
2
  signal_add("event 302", (SIGNAL_FUNC) event_userhost);
794
2
  signal_add("event 341", (SIGNAL_FUNC) event_sent_invite);
795
796
2
  signal_add("event 437", (SIGNAL_FUNC) event_target_unavailable);
797
2
  signal_add("event 401", (SIGNAL_FUNC) event_no_such_nick);
798
2
  signal_add("event 403", (SIGNAL_FUNC) event_no_such_channel);
799
2
  signal_add("event 405", (SIGNAL_FUNC) event_too_many_channels);
800
2
  signal_add("event 407", (SIGNAL_FUNC) event_duplicate_channel);
801
2
  signal_add("event 471", (SIGNAL_FUNC) event_channel_is_full);
802
2
  signal_add("event 472", (SIGNAL_FUNC) event_unknown_mode);
803
2
  signal_add("event 473", (SIGNAL_FUNC) event_invite_only);
804
2
  signal_add("event 474", (SIGNAL_FUNC) event_banned);
805
2
  signal_add("event 475", (SIGNAL_FUNC) event_bad_channel_key);
806
2
  signal_add("event 476", (SIGNAL_FUNC) event_bad_channel_mask);
807
2
  signal_add("event 477", (SIGNAL_FUNC) event_477);
808
2
  signal_add("event 489", (SIGNAL_FUNC) event_489); /* cannot join to channel (secure only), or not chanop or voice. */
809
2
  signal_add("event 375", (SIGNAL_FUNC) event_motd);
810
2
  signal_add("event 376", (SIGNAL_FUNC) event_motd);
811
2
  signal_add("event 372", (SIGNAL_FUNC) event_motd);
812
2
  signal_add("event 422", (SIGNAL_FUNC) event_motd);
813
2
  signal_add("event 439", (SIGNAL_FUNC) event_target_too_fast);
814
2
  signal_add("event 704", (SIGNAL_FUNC) event_helpstart);
815
2
  signal_add("event 705", (SIGNAL_FUNC) event_helptxt);
816
2
  signal_add("event 706", (SIGNAL_FUNC) event_endofhelp);
817
2
  signal_add("event 707", (SIGNAL_FUNC) event_target_too_fast);
818
819
2
        signal_add("default event numeric", (SIGNAL_FUNC) event_numeric);
820
  /* Because default event numeric only fires if there is no specific
821
   * event, add all numerics with a handler elsewhere in irssi that
822
   * should not be printed specially here.
823
   */
824
2
  signal_add("event 001", (SIGNAL_FUNC) event_received);
825
2
  signal_add("event 004", (SIGNAL_FUNC) event_received);
826
2
  signal_add("event 005", (SIGNAL_FUNC) event_received);
827
2
  signal_add("event 254", (SIGNAL_FUNC) event_received);
828
2
  signal_add("event 354", (SIGNAL_FUNC) event_received);
829
2
  signal_add("event 364", (SIGNAL_FUNC) event_received);
830
2
  signal_add("event 365", (SIGNAL_FUNC) event_received);
831
2
  signal_add("event 381", (SIGNAL_FUNC) event_received);
832
2
  signal_add("event 396", (SIGNAL_FUNC) event_received);
833
2
  signal_add("event 421", (SIGNAL_FUNC) event_received);
834
2
  signal_add("event 432", (SIGNAL_FUNC) event_received);
835
2
  signal_add("event 436", (SIGNAL_FUNC) event_received);
836
2
  signal_add("event 438", (SIGNAL_FUNC) event_received);
837
2
  signal_add("event 465", (SIGNAL_FUNC) event_received);
838
2
  signal_add("event 470", (SIGNAL_FUNC) event_received);
839
2
  signal_add("event 479", (SIGNAL_FUNC) event_received);
840
841
2
  signal_add("event 345", (SIGNAL_FUNC) event_target_received); /* end of reop list/hybrid quiet list */
842
2
  signal_add("event 347", (SIGNAL_FUNC) event_target_received); /* end of invite exception list */
843
2
  signal_add("event 349", (SIGNAL_FUNC) event_target_received); /* end of ban exception list */
844
2
  signal_add("event 368", (SIGNAL_FUNC) event_target_received); /* end of ban list */
845
2
  signal_add("event 386", (SIGNAL_FUNC) event_target_received); /* owner list; old rsa challenge (harmless) */
846
2
  signal_add("event 387", (SIGNAL_FUNC) event_target_received); /* end of owner list */
847
2
  signal_add("event 388", (SIGNAL_FUNC) event_target_received); /* protect list */
848
2
  signal_add("event 389", (SIGNAL_FUNC) event_target_received); /* end of protect list */
849
2
  signal_add("event 404", (SIGNAL_FUNC) event_target_received); /* cannot send to channel */
850
2
  signal_add("event 408", (SIGNAL_FUNC) event_target_received); /* cannot send (+c) */
851
2
  signal_add("event 442", (SIGNAL_FUNC) event_target_received); /* you're not on that channel */
852
2
  signal_add("event 478", (SIGNAL_FUNC) event_target_received); /* ban list is full */
853
2
  signal_add("event 482", (SIGNAL_FUNC) event_target_received); /* not chanop */
854
2
  signal_add("event 486", (SIGNAL_FUNC) event_target_received); /* cannot /msg (+R) */
855
2
  signal_add("event 494", (SIGNAL_FUNC) event_target_received); /* cannot /msg (own +R) */
856
2
  signal_add("event 506", (SIGNAL_FUNC) event_target_received); /* cannot send (+R) */
857
2
  signal_add("event 716", (SIGNAL_FUNC) event_target_received); /* cannot /msg (+g) */
858
2
  signal_add("event 717", (SIGNAL_FUNC) event_target_received); /* +g notified */
859
2
  signal_add("event 729", (SIGNAL_FUNC) event_target_received); /* end of quiet (or other) list */
860
  /* clang-format on */
861
2
}
862
863
void fe_events_numeric_deinit(void)
864
0
{
865
0
  g_free_not_null(last_away_nick);
866
0
  g_free_not_null(last_away_msg);
867
868
0
  signal_remove("event 221", (SIGNAL_FUNC) event_user_mode);
869
0
  signal_remove("event 303", (SIGNAL_FUNC) event_ison);
870
0
  signal_remove("event 353", (SIGNAL_FUNC) event_names_list);
871
0
  signal_remove("event 366", (SIGNAL_FUNC) event_end_of_names);
872
0
  signal_remove("event 352", (SIGNAL_FUNC) event_who);
873
0
  signal_remove("event 315", (SIGNAL_FUNC) event_end_of_who);
874
0
  signal_remove("event 271", (SIGNAL_FUNC) event_silence_list);
875
0
  signal_remove("event 272", (SIGNAL_FUNC) sig_empty);
876
0
  signal_remove("event 281", (SIGNAL_FUNC) event_accept_list);
877
0
  signal_remove("event 367", (SIGNAL_FUNC) event_ban_list);
878
0
  signal_remove("event 348", (SIGNAL_FUNC) event_eban_list);
879
0
  signal_remove("event 728", (SIGNAL_FUNC) event_quiet_list);
880
0
  signal_remove("event 344", (SIGNAL_FUNC) event_hybrid_quiet_list);
881
0
  signal_remove("event 346", (SIGNAL_FUNC) event_invite_list);
882
0
  signal_remove("event 433", (SIGNAL_FUNC) event_nick_in_use);
883
0
  signal_remove("event 332", (SIGNAL_FUNC) event_topic_get);
884
0
  signal_remove("event 333", (SIGNAL_FUNC) event_topic_info);
885
0
  signal_remove("event 324", (SIGNAL_FUNC) event_channel_mode);
886
0
  signal_remove("event 329", (SIGNAL_FUNC) event_channel_created);
887
0
  signal_remove("event 306", (SIGNAL_FUNC) event_nowaway);
888
0
  signal_remove("event 305", (SIGNAL_FUNC) event_unaway);
889
0
  signal_remove("event 301", (SIGNAL_FUNC) event_away);
890
0
  signal_remove("event 328", (SIGNAL_FUNC) event_chanserv_url);
891
0
  signal_remove("event 302", (SIGNAL_FUNC) event_userhost);
892
0
  signal_remove("event 341", (SIGNAL_FUNC) event_sent_invite);
893
894
0
  signal_remove("event 437", (SIGNAL_FUNC) event_target_unavailable);
895
0
  signal_remove("event 401", (SIGNAL_FUNC) event_no_such_nick);
896
0
  signal_remove("event 403", (SIGNAL_FUNC) event_no_such_channel);
897
0
  signal_remove("event 405", (SIGNAL_FUNC) event_too_many_channels);
898
0
  signal_remove("event 407", (SIGNAL_FUNC) event_duplicate_channel);
899
0
  signal_remove("event 471", (SIGNAL_FUNC) event_channel_is_full);
900
0
  signal_remove("event 472", (SIGNAL_FUNC) event_unknown_mode);
901
0
  signal_remove("event 473", (SIGNAL_FUNC) event_invite_only);
902
0
  signal_remove("event 474", (SIGNAL_FUNC) event_banned);
903
0
  signal_remove("event 475", (SIGNAL_FUNC) event_bad_channel_key);
904
0
  signal_remove("event 476", (SIGNAL_FUNC) event_bad_channel_mask);
905
0
  signal_remove("event 477", (SIGNAL_FUNC) event_477);
906
0
  signal_remove("event 489", (SIGNAL_FUNC) event_489);
907
0
  signal_remove("event 375", (SIGNAL_FUNC) event_motd);
908
0
  signal_remove("event 376", (SIGNAL_FUNC) event_motd);
909
0
  signal_remove("event 372", (SIGNAL_FUNC) event_motd);
910
0
  signal_remove("event 422", (SIGNAL_FUNC) event_motd);
911
0
  signal_remove("event 439", (SIGNAL_FUNC) event_target_too_fast);
912
0
  signal_remove("event 704", (SIGNAL_FUNC) event_helpstart);
913
0
  signal_remove("event 705", (SIGNAL_FUNC) event_helptxt);
914
0
  signal_remove("event 706", (SIGNAL_FUNC) event_endofhelp);
915
0
  signal_remove("event 707", (SIGNAL_FUNC) event_target_too_fast);
916
917
0
        signal_remove("default event numeric", (SIGNAL_FUNC) event_numeric);
918
0
  signal_remove("event 001", (SIGNAL_FUNC) event_received);
919
0
  signal_remove("event 004", (SIGNAL_FUNC) event_received);
920
0
  signal_remove("event 005", (SIGNAL_FUNC) event_received);
921
0
  signal_remove("event 254", (SIGNAL_FUNC) event_received);
922
0
  signal_remove("event 354", (SIGNAL_FUNC) event_received);
923
0
  signal_remove("event 364", (SIGNAL_FUNC) event_received);
924
0
  signal_remove("event 365", (SIGNAL_FUNC) event_received);
925
0
  signal_remove("event 381", (SIGNAL_FUNC) event_received);
926
0
  signal_remove("event 396", (SIGNAL_FUNC) event_received);
927
0
  signal_remove("event 421", (SIGNAL_FUNC) event_received);
928
0
  signal_remove("event 432", (SIGNAL_FUNC) event_received);
929
0
  signal_remove("event 436", (SIGNAL_FUNC) event_received);
930
0
  signal_remove("event 438", (SIGNAL_FUNC) event_received);
931
0
  signal_remove("event 465", (SIGNAL_FUNC) event_received);
932
0
  signal_remove("event 470", (SIGNAL_FUNC) event_received);
933
0
  signal_remove("event 479", (SIGNAL_FUNC) event_received);
934
935
0
  signal_remove("event 345", (SIGNAL_FUNC) event_target_received);
936
0
  signal_remove("event 347", (SIGNAL_FUNC) event_target_received);
937
0
  signal_remove("event 349", (SIGNAL_FUNC) event_target_received);
938
0
  signal_remove("event 368", (SIGNAL_FUNC) event_target_received);
939
0
  signal_remove("event 386", (SIGNAL_FUNC) event_target_received);
940
0
  signal_remove("event 387", (SIGNAL_FUNC) event_target_received);
941
0
  signal_remove("event 388", (SIGNAL_FUNC) event_target_received);
942
0
  signal_remove("event 389", (SIGNAL_FUNC) event_target_received);
943
0
  signal_remove("event 404", (SIGNAL_FUNC) event_target_received);
944
0
  signal_remove("event 408", (SIGNAL_FUNC) event_target_received);
945
0
  signal_remove("event 442", (SIGNAL_FUNC) event_target_received);
946
0
  signal_remove("event 478", (SIGNAL_FUNC) event_target_received);
947
0
  signal_remove("event 482", (SIGNAL_FUNC) event_target_received);
948
0
  signal_remove("event 486", (SIGNAL_FUNC) event_target_received);
949
0
  signal_remove("event 494", (SIGNAL_FUNC) event_target_received);
950
0
  signal_remove("event 506", (SIGNAL_FUNC) event_target_received);
951
0
  signal_remove("event 716", (SIGNAL_FUNC) event_target_received);
952
0
  signal_remove("event 717", (SIGNAL_FUNC) event_target_received);
953
  signal_remove("event 729", (SIGNAL_FUNC) event_target_received);
954
0
}