# HG changeset patch # User Luke Schierer # Date 1034712134 0 # Node ID c1254110070a4062db6c0ea5af20bbc8e9bd0c55 # Parent 8cd8deb4234d0ce152f8abdffd923d32c08155ba [gaim-migrate @ 3840] yeah!!!!! more irc enhancements from birme :-) committer: Tailor Script diff -r 8cd8deb4234d -r c1254110070a ChangeLog --- a/ChangeLog Tue Oct 15 06:46:27 2002 +0000 +++ b/ChangeLog Tue Oct 15 20:02:14 2002 +0000 @@ -45,8 +45,8 @@ * Read proxy environment variables. (Thanks, Christian Hammond) * Fixed security vulnerability with manual browser option (Thanks, Robert McQueen) - * Added more IRC slash commands -- /W, /VERSION, /MODE -- and - other cool IRC enhancments (Thanks, Jonas Birmé) + * Added more IRC slash commands -- /W, /VERSION, /MODE, /CTCP stuff, + -- and other cool IRC enhancments (Thanks, Jonas Birmé) * Add / Remove buddy menu item added to the chat users list (Thanks Jonas Birmé) * Parse URL messages and Contact Sending in ICQ (Thanks Mark diff -r 8cd8deb4234d -r c1254110070a src/protocols/irc/irc.c --- a/src/protocols/irc/irc.c Tue Oct 15 06:46:27 2002 +0000 +++ b/src/protocols/irc/irc.c Tue Oct 15 20:02:14 2002 +0000 @@ -60,6 +60,11 @@ G_MODULE_IMPORT GSList *connections; +static void irc_start_chat(struct gaim_connection *gc, char *who); +static void irc_ctcp_clientinfo(struct gaim_connection *gc, char *who); +static void irc_ctcp_userinfo(struct gaim_connection *gc, char *who); +static void irc_ctcp_version(struct gaim_connection *gc, char *who); + struct dcc_chat { struct gaim_connection *gc; @@ -458,20 +463,18 @@ #else n = recv (chat->fd, buffer, IRC_BUF_LEN, 0); #endif - if (n > 0) - { - - /* Strip the terminating \n */ - l = 0; - while (buffer[l] && buffer[l] != '\n' && l <= n) - l++; - buffer[l] = '\000'; - - /* Convert to HTML */ - debug_printf ("DCC Message from: %s\n", chat->nick); - irc_got_im(chat->gc, chat->nick, buffer, 0, time(NULL)); - } - + if (n > 0) { + + buffer[n] = 0; + g_strstrip(buffer); + + /* Convert to HTML */ + if (strlen(buffer)) { + debug_printf ("DCC Message from: %s\n", chat->nick); + irc_got_im(chat->gc, chat->nick, buffer, 0, + time(NULL)); + } + } else { g_snprintf (buf, sizeof buf, _("DCC Chat with %s closed"), chat->nick); @@ -632,6 +635,16 @@ g_strfreev(buf); } +static void handle_notopic(struct gaim_connection *gc, char *text) +{ + struct conversation *c; + if ((c = irc_find_chat(gc, text))) { + char buf[IRC_BUF_LEN]; + g_snprintf(buf, sizeof(buf), _("No topic is set")); + chat_set_topic(c, NULL, buf); + } +} + static void handle_topic(struct gaim_connection *gc, char *text) { struct conversation *c; @@ -688,9 +701,9 @@ char buf[IRC_BUF_LEN]; char *nick = g_strndup(who, strchr(who, '!') - who); - g_snprintf(buf, sizeof(buf), "%s sets mode %c%c %s on %s", - nick, sign, mode, strlen(argstr) ? argstr : "", - room); + g_snprintf(buf, sizeof(buf), "-:- mode/%s [%c%c %s] by %s", + room, sign, mode, strlen(argstr) ? argstr : "", + nick); g_free(nick); write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL), -1); } @@ -839,25 +852,30 @@ } switch (num) { - case 311: - id->liststr = g_string_append(id->liststr, "User: "); - break; - case 312: - id->liststr = g_string_append(id->liststr, "Server: "); - break; - case 313: - g_snprintf(tmp, sizeof(tmp), "IRC Operator: %s ", word[4]); - id->liststr = g_string_append(id->liststr, tmp); - break; - - case 317: - id->liststr = g_string_append(id->liststr, "Idle Time: "); - break; - case 319: - id->liststr = g_string_append(id->liststr, "Channels: "); - break; - default: - break; + case 311: + id->liststr = g_string_append(id->liststr, "User: "); + break; + case 312: + id->liststr = g_string_append(id->liststr, "Server: "); + break; + case 313: + g_snprintf(tmp, sizeof(tmp), "IRC Operator: %s ", word[4]); + id->liststr = g_string_append(id->liststr, tmp); + break; + case 314: + id->liststr = g_string_append(id->liststr, "User: "); + g_snprintf(tmp, sizeof(tmp), "%s (%s@%s) %s", + word[4], word[5], word[6], word_eol[8]); + id->liststr = g_string_append(id->liststr, tmp); + return; + case 317: + id->liststr = g_string_append(id->liststr, "Idle Time: "); + break; + case 319: + id->liststr = g_string_append(id->liststr, "Channels: "); + break; + default: + break; } if (word_eol[5][0] == ':') @@ -909,6 +927,7 @@ if (*text == ':') text++; + /* RPL_ and ERR_ */ switch (n) { case 4: if (!strncmp(word[5], "u2.10", 5)) @@ -919,7 +938,7 @@ case 5: handle_005(gc, word, word_eol); break; - case 301: + case 301: /* RPL_AWAY */ if (id->in_whois) { id->liststr = g_string_append(id->liststr, "
Away: "); @@ -930,23 +949,24 @@ } else irc_got_im(gc, word[4], word_eol[5], IM_FLAG_AWAY, time(NULL)); break; - case 303: + case 303: /* RPL_ISON */ handle_list(gc, &word_eol[4][1]); break; - case 311: - case 312: - case 313: - case 317: - case 319: + case 311: /* RPL_WHOISUSER */ + case 312: /* RPL_WHOISSERVER */ + case 313: /* RPL_WHOISOPERATOR */ + case 314: /* RPL_WHOWASUSER */ + case 317: /* RPL_WHOISIDLE */ + case 319: /* RPL_WHOISCHANNELS */ handle_whois(gc, word, word_eol, n); break; - case 322: + case 322: /* RPL_LIST */ handle_roomlist(gc, word, word_eol); break; - /* End of replies */ - case 323: - case 318: - case 315: + case 315: /* RPL_ENDOFWHO */ + case 318: /* RPL_ENDOFWHOIS */ + case 323: /* RPL_LISTEND */ + case 369: /* RPL_ENDOFWHOWAS */ if ((id->in_whois || id->in_list) && id->liststr) { GString *str = decode_html(id->liststr->str); g_show_info_text(gc, NULL, 2, str->str, NULL); @@ -957,36 +977,46 @@ id->in_list = FALSE; } break; - case 324: + case 324: /* RPL_CHANNELMODEIS */ handle_mode(gc, word, word_eol, TRUE); break; - case 332: + case 331: /* RPL_NOTOPIC */ + handle_notopic(gc, text); + break; + case 332: /* RPL_TOPIC */ handle_topic(gc, text); break; - case 351: + case 351: /* RPL_VERSION */ handle_version(gc, word, word_eol, n); break; - case 352: - handle_who(gc, word, word_eol, n); - break; - case 353: + case 352: /* RPL_WHOREPLY */ + handle_who(gc, word, word_eol, n); + break; + case 353: /* RPL_NAMREPLY */ handle_names(gc, word[5], word_eol[6]); break; - case 376: + case 376: /* RPL_ENDOFMOTD */ irc_request_buddy_update(gc); break; - case 401: - do_error_dialog(_("There is no such nick or channel on this IRC channel."), NULL, GAIM_ERROR); + case 382: /* RPL_REHASHING */ + do_error_dialog(_("Rehashing server"), _("IRC Operator"), GAIM_ERROR); + break; + case 401: /* ERR_NOSUCHNICK */ + do_error_dialog(_("No such nick/channel"), _("IRC Error"), GAIM_ERROR); break; - case 402: - do_error_dialog(_("There is no such IRC Server"), NULL, GAIM_ERROR); - case 431: - do_error_dialog(_("No IRC nickname given"), NULL, GAIM_ERROR); + case 402: /* ERR_NOSUCHSERVER */ + do_error_dialog(_("No such server"), _("IRC Error"), GAIM_ERROR); + case 431: /* ERR_NONICKNAMEGIVEN */ + do_error_dialog(_("No nickname given"), _("IRC Error"), GAIM_ERROR); break; + case 481: /* ERR_NOPRIVILEGES */ + do_error_dialog(_("You're not an IRC operator!"), _("IRC Error"), GAIM_ERROR); + break; case 433: do_prompt_dialog(_("That nick is already in use. Please enter a new nick"), gc->displayname, gc, irc_change_nick, NULL); break; default: + /* Other error messages */ if (n > 400 && n < 502) { char errmsg[IRC_BUF_LEN]; char *errmsg1 = strrchr(text, ':'); @@ -1125,6 +1155,14 @@ "Multi-protocol Messaging Client: " WEBSITE "\001\r\n", nick); irc_write(id->fd, buf, strlen(buf)); } + if (!g_strncasecmp(msg, "CLIENTINFO", 10)) { + g_snprintf(buf, sizeof(buf), "NOTICE %s :\001CLIENTINFO USERINFO CLIENTINFO VERSION\001\r\n", nick); + irc_write(id->fd, buf, strlen(buf)); + } + if (!g_strncasecmp(msg, "USERINFO", 8)) { + g_snprintf(buf, sizeof(buf), "NOTICE %s :\001USERINFO Alias: %s\001\r\n", nick, gc->user->alias); + irc_write(id->fd, buf, strlen(buf)); + } if (!g_strncasecmp(msg, "ACTION", 6)) { char *po = strchr(msg + 6, 1); char *tmp; @@ -1136,7 +1174,7 @@ if (!g_strncasecmp(msg, "DCC CHAT", 8)) { char **chat_args = g_strsplit(msg, " ", 5); char ask[1024]; - struct dcc_chat * dccchat = g_new0(struct dcc_chat, 1); + struct dcc_chat *dccchat = g_new0(struct dcc_chat, 1); dccchat->gc = gc; g_snprintf(dccchat->ip_address, sizeof(dccchat->ip_address), chat_args[3]); printf("DCC CHAT DEBUG CRAP: %s\n", dccchat->ip_address); @@ -1258,9 +1296,14 @@ return FALSE; gc->buddy_chats = g_slist_remove(gc->buddy_chats, c); c->gc = NULL; + /* g_snprintf(outbuf, sizeof(outbuf), _("You have been kicked from %s by %s:"), word[3], nick); do_error_dialog(outbuf, *word_eol[5] == ':' ? word_eol[5] + 1 : word_eol[5], GAIM_INFO); + */ + g_snprintf(outbuf, sizeof(outbuf), _("You have been kicked from %s: %s"), + word[3], *word_eol[5] == ':' ? word_eol[5] + 1 : word_eol[5]); + do_error_dialog(outbuf, _("IRC Error"), GAIM_ERROR); } else { char *reason = *word_eol[5] == ':' ? word_eol[5] + 1 : word_eol[5]; char *msg = g_strdup_printf(_("Kicked by %s: %s"), nick, reason); @@ -1276,9 +1319,31 @@ g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", new); irc_change_name(gc, nick, new); } else if (!strcmp(cmd, "NOTICE")) { - if (*word_eol[4] == ':') word_eol[4]++; - if (ex) - irc_got_im(gc, nick, word_eol[4], 0, time(NULL)); + char buf[IRC_BUF_LEN]; + if (!g_strcasecmp(word[4], ":\001CLIENTINFO")) { + char *p = strrchr(word_eol[5], '\001'); + *p = 0; + g_snprintf(buf, sizeof(buf), "CTCP Answer: %s", + word_eol[5]); + do_error_dialog(buf, _("CTCP ClientInfo"), GAIM_INFO); + } else if (!g_strcasecmp(word[4], ":\001USERINFO")) { + char *p = strrchr(word_eol[5], '\001'); + *p = 0; + g_snprintf(buf, sizeof(buf), "CTCP Answer: %s", + word_eol[5]); + do_error_dialog(buf, _("CTCP UserInfo"), GAIM_INFO); + } else if (!g_strcasecmp(word[4], ":\001VERSION")) { + char *p = strrchr(word_eol[5], '\001'); + *p = 0; + g_snprintf(buf, sizeof(buf), "CTCP Answer: %s", + word_eol[5]); + do_error_dialog(buf, _("CTCP Version"), GAIM_INFO); + } else { + if (*word_eol[4] == ':') word_eol[4]++; + if (ex) + irc_got_im(gc, nick, word_eol[4], 0, + time(NULL)); + } } else if (!strcmp(cmd, "PART")) { char *chan = cmd + 5; struct conversation *c; @@ -1335,7 +1400,10 @@ nick, topic); write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); } - } else if (!strcmp(cmd, "WALLOPS")) { /* */ + } else if (!strcmp(cmd, "WALLOPS")) { /* Don't know if a dialog box is the right way? */ + char *msg = strrchr(word_eol[0], ':'); + if (msg) + do_error_dialog(msg+1, _("IRC Operator"), GAIM_ERROR); } return FALSE; @@ -1376,7 +1444,7 @@ d = g_strndup(idata->rxqueue, len); g_strchomp(d); debug_printf("IRC S: %s\n", d); - + idata->rxlen -= len; if (idata->rxlen) { char *tmp = g_strdup(e + 1); @@ -1802,11 +1870,14 @@ gc->buddy_chats = g_slist_remove(gc->buddy_chats, c); c->gc = NULL; g_snprintf(buf, sizeof(buf), _("You have left %s"), chan); - do_error_dialog(buf, NULL, GAIM_INFO); + do_error_dialog(buf, _("IRC Part"), GAIM_INFO); } } else if (!g_strcasecmp(pdibuf, "WHOIS")) { g_snprintf(buf, sizeof(buf), "WHOIS %s\r\n", word_eol[2]); irc_write(id->fd, buf, strlen(buf)); + } else if (!g_strcasecmp(pdibuf, "WHOWAS")) { + g_snprintf(buf, sizeof(buf), "WHOWAS %s\r\n", word_eol[2]); + irc_write(id->fd, buf, strlen(buf)); } else if (!g_strcasecmp(pdibuf, "LIST")) { g_snprintf(buf, sizeof(buf), "LIST\r\n"); irc_write(id->fd, buf, strlen(buf)); @@ -1820,6 +1891,40 @@ } else if (!g_strcasecmp(pdibuf, "W")) { g_snprintf(buf, sizeof(buf), "WHO *\r\n"); irc_write(id->fd, buf, strlen(buf)); + } else if (!g_strcasecmp(pdibuf, "REHASH")) { + g_snprintf(buf, sizeof(buf), "REHASH\r\n"); + irc_write(id->fd, buf, strlen(buf)); + } else if (!g_strcasecmp(pdibuf, "RESTART")) { + g_snprintf(buf, sizeof(buf), "RESTART\r\n"); + irc_write(id->fd, buf, strlen(buf)); + } else if (!g_strcasecmp(pdibuf, "CTCP")) { + if (!g_strcasecmp(word[2], "CLIENTINFO")) { + if (word[3]) + irc_ctcp_clientinfo(gc, word[3]); + } else if (!g_strcasecmp(word[2], "USERINFO")) { + if (word[3]) + irc_ctcp_userinfo(gc, word[3]); + } else if (!g_strcasecmp(word[2], "VERSION")) { + if (word[3]) + irc_ctcp_version(gc, word[3]); + } + } else if (!g_strcasecmp(pdibuf, "DCC")) { + struct conversation *c = NULL; + if (!g_strcasecmp(word[2], "CHAT")) { + if (word[3]) + irc_start_chat(gc, word[3]); + + if (is_channel(gc, who)) { + c = irc_find_chat(gc, who); + } else { + c = find_conversation(who); + } + if (c) { + write_to_conv(c, "Requesting DCC CHAT", + WFLAG_SYSTEM, NULL, + time(NULL), -1); + } + } } else if (!g_strcasecmp(pdibuf, "HELP")) { struct conversation *c = NULL; if (is_channel(gc, who)) { @@ -1831,13 +1936,32 @@ g_free(what); return -EINVAL; } - write_to_conv(c, "Currently supported commands:
" - "WHOIS INVITE NICK LIST
" - "JOIN PART TOPIC KICK
" - "OP DEOP VOICE DEVOICE
" - "ME MSG QUOTE SAY QUIT
" - "MODE VERSION W
", - WFLAG_NOLOG, NULL, time(NULL), -1); + if (!g_strcasecmp(word[2], "OPER")) { + write_to_conv(c, "Operator commands:
" + "REHASH RESTART
", + WFLAG_NOLOG, NULL, time(NULL), -1); + } else if (!g_strcasecmp(word[2], "CTCP")) { + write_to_conv(c, "CTCP commands:
" + "CLIENTINFO
" + "USERINFO
" + "VERSION
", + WFLAG_NOLOG, NULL, time(NULL), -1); + } else if (!g_strcasecmp(word[2], "DCC")) { + write_to_conv(c, "DCC commands:
" + "CHAT
", + WFLAG_NOLOG, NULL, time(NULL), -1); + } else { + write_to_conv(c, "Currently supported commands:
" + "WHOIS INVITE NICK LIST
" + "JOIN PART TOPIC KICK
" + "OP DEOP VOICE DEVOICE
" + "ME MSG QUOTE SAY QUIT
" + "MODE VERSION W WHOWAS

" + "Type /HELP OPER for operator commands
" + "Type /HELP CTCP for CTCP commands
" + "Type /HELP DCC for DCC commands", + WFLAG_NOLOG, NULL, time(NULL), -1); + } } else { struct conversation *c = NULL; if (is_channel(gc, who)) { @@ -2010,16 +2134,15 @@ addr.sin_port = htons (chat->port); addr.sin_addr.s_addr = INADDR_ANY; chat->fd = accept (chat->fd, (struct sockaddr *) (&addr), &addrlen); - if (!chat->fd) - { - dcc_chat_cancel (NULL,chat); - convo = new_conversation (chat->nick); - g_snprintf (buf, sizeof buf, _("DCC Chat with %s closed"), - chat->nick); - write_to_conv (convo, buf, WFLAG_SYSTEM, NULL, - time ((time_t) NULL), -1); - return; - } + if (!chat->fd) { + dcc_chat_cancel (NULL,chat); + convo = new_conversation (chat->nick); + g_snprintf (buf, sizeof buf, _("DCC Chat with %s closed"), + chat->nick); + write_to_conv (convo, buf, WFLAG_SYSTEM, NULL, + time ((time_t) NULL), -1); + return; + } chat->inpa = gaim_input_add (chat->fd, GAIM_INPUT_READ, dcc_chat_in, chat); convo = new_conversation (chat->nick); @@ -2155,6 +2278,27 @@ proxy_connect(ift->ip, ift->port, dcc_recv_callback, ift); } +static void irc_ctcp_clientinfo(struct gaim_connection *gc, char *who) +{ + char buf[200]; + snprintf (buf, sizeof buf, "\001CLIENTINFO\001\n"); + irc_send_im (gc, who, buf, -1, 0); +} + +static void irc_ctcp_userinfo(struct gaim_connection *gc, char *who) +{ + char buf[200]; + snprintf (buf, sizeof buf, "\001USERINFO\001\n"); + irc_send_im (gc, who, buf, -1, 0); +} + +static void irc_ctcp_version(struct gaim_connection *gc, char *who) +{ + char buf[200]; + snprintf (buf, sizeof buf, "\001VERSION\001\n"); + irc_send_im (gc, who, buf, -1, 0); +} + static void irc_start_chat(struct gaim_connection *gc, char *who) { struct dcc_chat *chat; int len; @@ -2224,6 +2368,25 @@ pbm->gc = gc; m = g_list_append(m, pbm); */ + + pbm = g_new0(struct proto_buddy_menu, 1); + pbm->label = _("CTCP ClientInfo"); + pbm->callback = irc_ctcp_clientinfo; + pbm->gc = gc; + m = g_list_append(m, pbm); + + pbm = g_new0(struct proto_buddy_menu, 1); + pbm->label = _("CTCP UserInfo"); + pbm->callback = irc_ctcp_userinfo; + pbm->gc = gc; + m = g_list_append(m, pbm); + + pbm = g_new0(struct proto_buddy_menu, 1); + pbm->label = _("CTCP Version"); + pbm->callback = irc_ctcp_version; + pbm->gc = gc; + m = g_list_append(m, pbm); + return m; }