diff -ru work/src/common/ctcp.c work2/src/common/ctcp.c --- work/src/common/ctcp.c 2006-10-02 07:47:03.000000000 +0300 +++ work2/src/common/ctcp.c 2008-02-16 01:14:08.000000000 +0200 @@ -149,11 +149,11 @@ if (!chansess) chansess = sess; - EMIT_SIGNAL (XP_TE_CTCPSNDC, chansess, word[5], + EMIT_SIGNAL (XP_TE_CTCPSNDC, chansess, word[5], /* XXX unsafe_name? */ nick, to, NULL, 0); } else { - EMIT_SIGNAL (XP_TE_CTCPSND, sess->server->front_session, word[5], + EMIT_SIGNAL (XP_TE_CTCPSND, sess->server->front_session, word[5], /* XXX unsafe_name? */ nick, NULL, NULL, 0); } @@ -182,6 +182,7 @@ chansess = find_channel (sess->server, to); if (!chansess) chansess = sess; + /* FIXME it's a channel, but do we need to unsafe_name it? */ EMIT_SIGNAL (XP_TE_CTCPGENC, chansess, msg, nick, to, NULL, 0); } } diff -ru work/src/common/inbound.c work2/src/common/inbound.c --- work/src/common/inbound.c 2007-06-20 11:48:42.000000000 +0300 +++ work2/src/common/inbound.c 2008-02-16 01:14:08.000000000 +0200 @@ -541,6 +541,7 @@ inbound_ujoin (server *serv, char *chan, char *nick, char *ip) { session *sess; + char uchan[CHANLEN]; /* already joined? probably a bnc */ sess = find_channel (serv, chan); @@ -577,7 +578,8 @@ /* sends a MODE */ serv->p_join_info (sess->server, chan); - EMIT_SIGNAL (XP_TE_UJOIN, sess, nick, chan, ip, NULL, 0); + rfc_unsafe_chan (uchan, chan, CHANLEN); + EMIT_SIGNAL (XP_TE_UJOIN, sess, nick, uchan, ip, NULL, 0); if (prefs.userhost) { @@ -593,7 +595,9 @@ session *sess = find_channel (serv, chan); if (sess) { - EMIT_SIGNAL (XP_TE_UKICK, sess, serv->nick, chan, kicker, reason, 0); + char uchan[CHANLEN]; + rfc_unsafe_chan (uchan, chan, CHANLEN); + EMIT_SIGNAL (XP_TE_UKICK, sess, serv->nick, uchan, kicker, reason, 0); clear_channel (sess); if (prefs.autorejoin) { @@ -609,11 +613,13 @@ session *sess = find_channel (serv, chan); if (sess) { + char uchan[CHANLEN]; + rfc_unsafe_chan (uchan, chan, CHANLEN); if (*reason) - EMIT_SIGNAL (XP_TE_UPARTREASON, sess, serv->nick, ip, chan, reason, + EMIT_SIGNAL (XP_TE_UPARTREASON, sess, serv->nick, ip, uchan, reason, 0); else - EMIT_SIGNAL (XP_TE_UPART, sess, serv->nick, ip, chan, NULL, 0); + EMIT_SIGNAL (XP_TE_UPART, sess, serv->nick, ip, uchan, NULL, 0); clear_channel (sess); } } @@ -623,17 +629,19 @@ { session *sess; char name[NICKLEN]; + char uchan[CHANLEN]; int pos = 0; sess = find_channel (serv, chan); + rfc_unsafe_chan (uchan, chan, CHANLEN); if (!sess) { - EMIT_SIGNAL (XP_TE_USERSONCHAN, serv->server_session, chan, names, NULL, + EMIT_SIGNAL (XP_TE_USERSONCHAN, serv->server_session, uchan, names, NULL, NULL, 0); return; } if (!sess->ignore_names) - EMIT_SIGNAL (XP_TE_USERSONCHAN, sess, chan, names, NULL, NULL, 0); + EMIT_SIGNAL (XP_TE_USERSONCHAN, sess, uchan, names, NULL, NULL, 0); if (sess->end_of_names) { @@ -669,6 +677,7 @@ { session *sess = find_channel (serv, chan); char *new_topic; + char uchan[CHANLEN]; if (sess) { @@ -678,7 +687,8 @@ } else sess = serv->server_session; - EMIT_SIGNAL (XP_TE_TOPIC, sess, chan, topic_text, NULL, NULL, 0); + rfc_unsafe_chan (uchan, chan, CHANLEN); + EMIT_SIGNAL (XP_TE_TOPIC, sess, uchan, topic_text, NULL, NULL, 0); } void @@ -690,10 +700,12 @@ sess = find_channel (serv, chan); if (sess) { + char uchan[CHANLEN]; new_topic = strip_color (topic, -1, STRIP_ALL); set_topic (sess, new_topic); free (new_topic); - EMIT_SIGNAL (XP_TE_NEWTOPIC, sess, nick, topic, chan, NULL, 0); + rfc_unsafe_chan (uchan, chan, CHANLEN); + EMIT_SIGNAL (XP_TE_NEWTOPIC, sess, nick, topic, uchan, NULL, 0); } } @@ -704,7 +716,11 @@ if (sess) { if (!sess->hide_join_part) - EMIT_SIGNAL (XP_TE_JOIN, sess, user, chan, ip, NULL, 0); + { + char uchan[CHANLEN]; + rfc_unsafe_chan (uchan, chan, CHANLEN); + EMIT_SIGNAL (XP_TE_JOIN, sess, user, uchan, ip, NULL, 0); + } userlist_add (sess, user, ip); } } @@ -715,7 +731,9 @@ session *sess = find_channel (serv, chan); if (sess) { - EMIT_SIGNAL (XP_TE_KICK, sess, kicker, user, chan, reason, 0); + char uchan[CHANLEN]; + rfc_unsafe_chan (uchan, chan, CHANLEN); + EMIT_SIGNAL (XP_TE_KICK, sess, kicker, user, uchan, reason, 0); userlist_remove (sess, user); } } @@ -728,10 +746,12 @@ { if (!sess->hide_join_part) { + char uchan[CHANLEN]; + rfc_unsafe_chan (uchan, chan, CHANLEN); if (*reason) - EMIT_SIGNAL (XP_TE_PARTREASON, sess, user, ip, chan, reason, 0); + EMIT_SIGNAL (XP_TE_PARTREASON, sess, user, ip, uchan, reason, 0); else - EMIT_SIGNAL (XP_TE_PART, sess, user, ip, chan, NULL, 0); + EMIT_SIGNAL (XP_TE_PART, sess, user, ip, uchan, NULL, 0); } userlist_remove (sess, user); } @@ -741,13 +761,15 @@ inbound_topictime (server *serv, char *chan, char *nick, time_t stamp) { char *tim = ctime (&stamp); + char uchan[CHANLEN]; session *sess = find_channel (serv, chan); if (!sess) sess = serv->server_session; tim[24] = 0; /* get rid of the \n */ - EMIT_SIGNAL (XP_TE_TOPICDATE, sess, chan, nick, tim, NULL, 0); + rfc_unsafe_chan (uchan, chan, CHANLEN); + EMIT_SIGNAL (XP_TE_TOPICDATE, sess, uchan, nick, tim, NULL, 0); } void @@ -1247,12 +1269,14 @@ if (!fe_is_banwindow (sess)) { + char uchan[CHANLEN]; nowindow: /* let proto-irc.c do the 'goto def' for exemptions */ if (is_exemption) return FALSE; - EMIT_SIGNAL (XP_TE_BANLIST, sess, chan, mask, banner, time_str, 0); + rfc_unsafe_chan (uchan, chan, CHANLEN); + EMIT_SIGNAL (XP_TE_BANLIST, sess, uchan, mask, banner, time_str, 0); return TRUE; } Only in work2/src/common: inbound.c.orig diff -ru work/src/common/proto-irc.c work2/src/common/proto-irc.c --- work/src/common/proto-irc.c 2007-02-12 14:36:28.000000000 +0200 +++ work2/src/common/proto-irc.c 2008-02-16 01:14:08.000000000 +0200 @@ -307,9 +307,11 @@ channel_date (session *sess, char *chan, char *timestr) { time_t timestamp = (time_t) atol (timestr); + char uchan[CHANLEN]; char *tim = ctime (×tamp); tim[24] = 0; /* get rid of the \n */ - EMIT_SIGNAL (XP_TE_CHANDATE, sess, chan, tim, NULL, NULL, 0); + rfc_unsafe_chan (uchan, chan, CHANLEN); + EMIT_SIGNAL (XP_TE_CHANDATE, sess, uchan, tim, NULL, NULL, 0); } static void @@ -319,6 +321,7 @@ server *serv = sess->server; /* show whois is the server tab */ session *whois_sess = serv->server_session; + char uchan[CHANLEN]; /* unless this setting is on */ if (prefs.irc_whois_front) @@ -467,8 +470,10 @@ case 313: case 319: + /* FIXME: Is this really necessary? */ + rfc_unsafe_chan (uchan, word_eol[5] + 1, CHANLEN); EMIT_SIGNAL (XP_TE_WHOIS2, whois_sess, word[4], - word_eol[5] + 1, NULL, NULL, 0); + uchan, NULL, NULL, 0); break; case 307: /* dalnet version */ @@ -507,8 +512,11 @@ if (sess->ignore_mode) sess->ignore_mode = FALSE; else - EMIT_SIGNAL (XP_TE_CHANMODES, sess, word[4], word_eol[5], + { + rfc_unsafe_chan (uchan, word_eol[5], CHANLEN); + EMIT_SIGNAL (XP_TE_CHANMODES, sess, word[4], uchan, NULL, NULL, 0); + } fe_update_mode_buttons (sess, 't', '-'); fe_update_mode_buttons (sess, 'n', '-'); fe_update_mode_buttons (sess, 's', '-'); @@ -553,7 +561,8 @@ #endif case 341: /* INVITE ACK */ - EMIT_SIGNAL (XP_TE_UINVITE, sess, word[4], word[5], serv->servername, + rfc_unsafe_chan (uchan, word[5], CHANLEN); + EMIT_SIGNAL (XP_TE_UINVITE, sess, word[4], uchan, serv->servername, NULL, 0); break; @@ -695,19 +704,23 @@ break; case 471: - EMIT_SIGNAL (XP_TE_USERLIMIT, sess, word[4], NULL, NULL, NULL, 0); + rfc_unsafe_chan (uchan, word[4], CHANLEN); + EMIT_SIGNAL (XP_TE_USERLIMIT, sess, uchan, NULL, NULL, NULL, 0); break; case 473: - EMIT_SIGNAL (XP_TE_INVITE, sess, word[4], NULL, NULL, NULL, 0); + rfc_unsafe_chan (uchan, word[4], CHANLEN); + EMIT_SIGNAL (XP_TE_INVITE, sess, uchan, NULL, NULL, NULL, 0); break; case 474: - EMIT_SIGNAL (XP_TE_BANNED, sess, word[4], NULL, NULL, NULL, 0); + rfc_unsafe_chan (uchan, word[4], CHANLEN); + EMIT_SIGNAL (XP_TE_BANNED, sess, uchan, NULL, NULL, NULL, 0); break; case 475: - EMIT_SIGNAL (XP_TE_KEYWORD, sess, word[4], NULL, NULL, NULL, 0); + rfc_unsafe_chan (uchan, word[4], CHANLEN); + EMIT_SIGNAL (XP_TE_KEYWORD, sess, uchan, NULL, NULL, NULL, 0); break; case 601: @@ -856,6 +869,7 @@ else if (len >= 5) { guint32 t; + char uchan[CHANLEN]; t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); /* this should compile to a bunch of: CMP.L, JE ... nice & fast */ @@ -866,11 +880,16 @@ return; if (word[4][0] == ':') + { + rfc_unsafe_chan (uchan, word[4] + 1, CHANLEN); EMIT_SIGNAL (XP_TE_INVITED, sess, word[4] + 1, nick, serv->servername, NULL, 0); - else + } else + { + rfc_unsafe_chan (uchan, word[4], CHANLEN); EMIT_SIGNAL (XP_TE_INVITED, sess, word[4], nick, serv->servername, NULL, 0); + } return; Only in work2/src/common: proto-irc.c.orig diff -ru work/src/common/text.c work2/src/common/text.c --- work/src/common/text.c 2008-02-16 01:11:05.000000000 +0200 +++ work2/src/common/text.c 2008-02-16 01:14:08.000000000 +0200 @@ -349,10 +349,12 @@ static char * log_create_filename (char *channame) { + char unsafe[CHANLEN]; char *tmp, *ret; int mbl; - ret = tmp = strdup (channame); + rfc_unsafe_chan (unsafe, channame, CHANLEN); + ret = tmp = strdup (unsafe); while (*tmp) { mbl = g_utf8_skip[((unsigned char *)tmp)[0]]; diff -ru work/src/common/util.c work2/src/common/util.c --- work/src/common/util.c 2008-02-16 01:11:05.000000000 +0200 +++ work2/src/common/util.c 2008-02-16 01:14:08.000000000 +0200 @@ -1441,6 +1441,18 @@ 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };*/ +void +rfc_unsafe_chan (char *dst, char *src, int len) +{ + if (src[0] != '!' || strlen (src) < 7) + safe_strcpy (dst, src, len); + else + { + dst[0] = '!'; + safe_strcpy (dst + 1, src + 6, len - 6); + } +} + /*static int rename_utf8 (char *oldname, char *newname) { Only in work2/src/common: util.c.orig diff -ru work/src/common/util.h work2/src/common/util.h --- work/src/common/util.h 2008-02-16 01:11:05.000000000 +0200 +++ work2/src/common/util.h 2008-02-16 01:14:31.000000000 +0200 @@ -27,6 +27,7 @@ int rfc_casecmp (const char *, const char *); int rfc_ncasecmp (char *, char *, int); int hal_casecomp ( char *s1, char *s2); +void rfc_unsafe_chan (char *dst, char *src, int len); int buf_get_line (char *, char **, int *, int len); char *nocasestrstr (const char *text, const char *tofind); char *country (char *); Only in work2/src/common: util.h.orig Only in work2/src/common: util.h.rej diff -ru work/src/fe-gtk/banlist.c work2/src/fe-gtk/banlist.c --- work/src/fe-gtk/banlist.c 2007-07-01 07:13:20.000000000 +0300 +++ work2/src/fe-gtk/banlist.c 2008-02-16 01:14:08.000000000 +0200 @@ -40,6 +40,7 @@ #include "../common/fe.h" #include "../common/modes.h" #include "../common/outbound.h" +#include "../common/util.h" #include "../common/xchatc.h" #include "gtkutil.h" #include "maingui.h" @@ -125,11 +126,13 @@ if (sess->server->connected) { GtkListStore *store; + char uchan[CHANLEN]; gtk_widget_set_sensitive (sess->res->banlist_butRefresh, FALSE); + rfc_unsafe_chan (uchan, sess->channel, CHANLEN); snprintf (tbuf, sizeof tbuf, "XChat: Ban List (%s, %s)", - sess->channel, sess->server->servername); + uchan, sess->server->servername); mg_set_title (sess->res->banlist_window, tbuf); store = get_store (sess); @@ -272,10 +275,12 @@ banlist_clear (GtkWidget * wid, struct session *sess) { GtkWidget *dialog; + char uchan[CHANLEN]; + rfc_unsafe_chan (uchan, sess->channel, CHANLEN); dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, - _("Are you sure you want to remove all bans in %s?"), sess->channel); + _("Are you sure you want to remove all bans in %s?"), uchan); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (banlist_clear_cb), sess); gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE); diff -ru work/src/fe-gtk/maingui.c work2/src/fe-gtk/maingui.c --- work/src/fe-gtk/maingui.c 2007-06-23 18:54:15.000000000 +0300 +++ work2/src/fe-gtk/maingui.c 2008-02-16 01:14:08.000000000 +0200 @@ -55,6 +55,7 @@ #include "../common/plugin.h" #include "../common/modes.h" #include "../common/url.h" +#include "../common/util.h" #include "fe-gtk.h" #include "banlist.h" #include "gtkutil.h" @@ -483,6 +484,7 @@ fe_set_title (session *sess) { char tbuf[512]; + char uchan[CHANLEN]; int type; if (sess->gui->is_tab && sess != current_tab) @@ -504,17 +506,18 @@ sess->server->nick, server_get_network (sess->server, TRUE)); break; case SESS_CHANNEL: + rfc_unsafe_chan (uchan, sess->channel, CHANLEN); /* don't display keys in the titlebar */ if ((!(prefs.gui_tweaks & 16)) && has_key (sess->current_modes)) snprintf (tbuf, sizeof (tbuf), "XChat: %s @ %s / %s", sess->server->nick, server_get_network (sess->server, TRUE), - sess->channel); + uchan); else snprintf (tbuf, sizeof (tbuf), "XChat: %s @ %s / %s (%s)", sess->server->nick, server_get_network (sess->server, TRUE), - sess->channel, sess->current_modes ? sess->current_modes : ""); + uchan, sess->current_modes ? sess->current_modes : ""); if (prefs.gui_tweaks & 1) snprintf (tbuf + strlen (tbuf), 9, " (%d)", sess->total); break; @@ -784,7 +787,9 @@ case SESS_CHANNEL: if (sess->topic) { - text = g_strdup_printf (_("Topic for %s is: %s"), sess->channel, + char uchan[CHANLEN]; + rfc_unsafe_chan (uchan, sess->channel, CHANLEN); + text = g_strdup_printf (_("Topic for %s is: %s"), uchan, sess->topic); add_tip (sess->gui->topic_entry, text); g_free (text); @@ -1613,7 +1618,10 @@ if (tag == TAG_IRC) { - char *name = g_markup_escape_text (sess->channel[0] ? sess->channel : _(""), -1); + char uchan[CHANLEN]; + char *name; + rfc_unsafe_chan (uchan, sess->channel[0] ? sess->channel : _(""), CHANLEN); + name = g_markup_escape_text (uchan, -1); snprintf (buf, sizeof (buf), "%s", name); g_free (name); item = gtk_menu_item_new_with_label (""); @@ -1649,6 +1657,7 @@ mg_create_icon_item (_("_Detach Tab"), GTK_STOCK_REDO, menu, mg_detach_tab_cb, ch); + /* FIXME what is this menu? */ if (sess && tabmenu_list) menu_create (menu, tabmenu_list, sess->channel, FALSE); menu_add_plugin_items (menu, "\x4$TAB", sess->channel); @@ -2862,6 +2871,7 @@ } /* compare two tabs (for tab sorting function) */ +/* TODO: Thanks to rfc_unsafe_chan sorting is unnecessarily expensive */ static int mg_tabs_compare (session *a, session *b) @@ -2876,7 +2886,14 @@ if (a->type != SESS_CHANNEL && b->type == SESS_CHANNEL) return 1; - return strcasecmp (a->channel, b->channel); + if (a->type == SESS_CHANNEL) + { + char achan[CHANLEN], bchan[CHANLEN]; + rfc_unsafe_chan (achan, a->channel, CHANLEN); + rfc_unsafe_chan (bchan, b->channel, CHANLEN); + return strcasecmp (achan, bchan); + } else + return strcasecmp (a->channel, b->channel); } static void @@ -3185,16 +3202,16 @@ { if (sess->waitchannel[0]) { + tbuf[0] = '('; + rfc_unsafe_chan (tbuf + 1, sess->waitchannel, CHANLEN); if (prefs.truncchans > 2 && g_utf8_strlen (sess->waitchannel, -1) > prefs.truncchans) { /* truncate long channel names */ - tbuf[0] = '('; - strcpy (tbuf + 1, sess->waitchannel); g_utf8_offset_to_pointer(tbuf, prefs.truncchans)[0] = 0; strcat (tbuf, "..)"); } else { - sprintf (tbuf, "(%s)", sess->waitchannel); + strcat (tbuf, ")"); } } else @@ -3326,7 +3343,11 @@ fe_set_channel (session *sess) { if (sess->res->tab != NULL) - chan_rename (sess->res->tab, sess->channel, prefs.truncchans); + { + char uchan[CHANLEN]; + rfc_unsafe_chan (uchan, sess->channel, CHANLEN); + chan_rename (sess->res->tab, uchan, prefs.truncchans); + } } void Only in work2/src/fe-gtk: maingui.c.orig