# HG changeset patch # User Sean Egan # Date 1030468588 0 # Node ID 12202a328adf8967be5261d1452b5385c313514b # Parent 02738ff4c21983d8d8414c8efd106618a010050e [gaim-migrate @ 3497] FROM JONAS BIRME: * IRC: /W implemented the WHO * command * IRC: /VERSION implemented * IRC: Display all error messages received from server. * IRC: Handle channel mode and added support for changing mode, /MODE * IRC: Implements /QUIT [] 4.1.6 in the RFC. Quits the entire application. * IRC: Use gc->user->alias as real name. Also includes yesterdays patch: * Add nickname to buddy list by right clicking on nickname in chat room. * IRC: Parsed the idle and signon time on WHOIS-answer. committer: Tailor Script diff -r 02738ff4c219 -r 12202a328adf ChangeLog --- a/ChangeLog Tue Aug 27 16:41:30 2002 +0000 +++ b/ChangeLog Tue Aug 27 17:16:28 2002 +0000 @@ -28,6 +28,7 @@ - GtkIMHtml, sorta (Ari Pollak, Christian Hammond) - Buddy Icons - IM Images + - Alert Dialogs * Notify.c plugin rewritten; check its configure dialog (Thanks, Etan Reisner) * TOC no longer compiles statically by default--use OSCAR @@ -38,6 +39,10 @@ * 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é) + * Add / Remove buddy menu item added to the chat users list + (Thanks Jonas Birmé) version 0.59 (06/24/2002): * Hungarian translation added (Thanks, Sutto Zoltan) diff -r 02738ff4c219 -r 12202a328adf src/protocols/irc/irc.c --- a/src/protocols/irc/irc.c Tue Aug 27 16:41:30 2002 +0000 +++ b/src/protocols/irc/irc.c Tue Aug 27 17:16:28 2002 +0000 @@ -605,6 +605,19 @@ return FALSE; } +static void irc_chan_mode(struct gaim_connection *gc, char *room, char sign, char mode, char *argstr, char *who) +{ + struct conversation *c = irc_find_chat(gc, room); + 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_free(nick); + write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL), -1); +} + static void irc_user_mode(struct gaim_connection *gc, char *room, char sign, char mode, char *nick) { struct conversation *c = irc_find_chat(gc, room); @@ -664,6 +677,7 @@ char sign = *modes++; int arg = 1; char *argstr; + char *who = word[1]; if (!c) return; @@ -686,11 +700,50 @@ argstr = ""; if (strchr(id->nickmodes, *modes)) irc_user_mode(gc, chan, sign, *modes, argstr); + else if (strchr(who, '!')) + irc_chan_mode(gc, chan, sign, *modes, argstr, who); } modes++; } } +static void handle_version(struct gaim_connection *gc, char *word[], char *word_eol[], int num) +{ + struct irc_data *id = gc->proto_data; + char buf[IRC_BUF_LEN]; + GString *str; + + id->liststr = g_string_new(""); + + id->liststr = g_string_append(id->liststr, "Version: "); + id->liststr = g_string_append(id->liststr, word_eol[4]); + + str = decode_html(id->liststr->str); + g_show_info_text(gc, NULL, 2, str->str, NULL); + g_string_free(str, TRUE); + g_string_free(id->liststr, TRUE); + id->liststr = NULL; +} + +static void handle_who(struct gaim_connection *gc, char *word[], char *word_eol[], int num) +{ + struct irc_data *id = gc->proto_data; + char buf[IRC_BUF_LEN]; + + if (!id->in_whois) { + id->in_whois = TRUE; + id->liststr = g_string_new(""); + } + + switch (num) { + case 352: + g_snprintf(buf, sizeof(buf), "%s (%s@%s): %s
", + word[8], word[5], word[6], word_eol[11]); + id->liststr = g_string_append(id->liststr, buf); + break; + } +} + /* Handle our whois stuff here. You know what, I have a sore throat. You know * what I think about that? I'm not too pleased with it. Perhaps I should take * some medicine, or perhaps I should go to bed? Blah!! */ @@ -730,9 +783,18 @@ default: break; } - + if (word_eol[5][0] == ':') id->liststr = g_string_append(id->liststr, word_eol[5] + 1); + /* Nicer idle time output, by jonas@birme.se */ + else if (isdigit(word_eol[5][0])) { + time_t idle = atol(word_eol[5]); + time_t signon = atol(strchr(word_eol[5], ' ')); + + g_snprintf(tmp, sizeof(tmp), + "%ld seconds [signon: %s]", (idle / 1000), ctime(&signon)); + id->liststr = g_string_append(id->liststr, tmp); + } else id->liststr = g_string_append(id->liststr, word_eol[5]); } @@ -791,14 +853,16 @@ case 312: case 313: case 317: - case 319: + case 319: handle_whois(gc, word, word_eol, n); break; case 322: handle_roomlist(gc, word, word_eol); break; + /* End of replies */ case 323: case 318: + case 315: 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); @@ -815,6 +879,12 @@ case 332: handle_topic(gc, text); break; + case 351: + handle_version(gc, word, word_eol, n); + break; + case 352: + handle_who(gc, word, word_eol, n); + break; case 353: handle_names(gc, word[5], word_eol[6]); break; @@ -829,6 +899,15 @@ case 431: do_error_dialog(_("No IRC nickname given"), NULL, GAIM_ERROR); break; + default: + if (n > 400 && n < 502) { + char errmsg[IRC_BUF_LEN]; + char *errmsg1 = strrchr(text, ':'); + g_snprintf(errmsg, sizeof(errmsg), "IRC Error %d", n); + if (errmsg) + do_error_dialog(errmsg, errmsg1+1, GAIM_ERROR); + } + break; } } @@ -990,7 +1069,7 @@ char *cmd; /* Check for errors */ - + if (*buf != ':') { if (!strncmp(buf, "NOTICE ", 7)) buf += 7; @@ -1182,7 +1261,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); @@ -1229,8 +1308,10 @@ hostname[sizeof(hostname) - 1] = 0; if (!*hostname) g_snprintf(hostname, sizeof(hostname), "localhost"); - g_snprintf(buf, sizeof(buf), "USER %s %s %s :Gaim (%s)\r\n", - g_get_user_name(), hostname, gc->user->proto_opt[USEROPT_SERV], WEBSITE); + g_snprintf(buf, sizeof(buf), "USER %s %s %s :%s [Gaim (%s)]\r\n", + g_get_user_name(), hostname, + gc->user->proto_opt[USEROPT_SERV], + gc->user->alias, WEBSITE); if (irc_write(idata->fd, buf, strlen(buf)) < 0) { hide_login_progress(gc, "Write error"); signoff(gc); @@ -1260,7 +1341,7 @@ set_login_progress(gc, 2, buf); idata->chantypes = g_strdup("#&!+"); - idata->chanmodes = g_strdup("beI,k,l"); + idata->chanmodes = g_strdup("beI,k,lnt"); idata->nickmodes = g_strdup("ohv"); idata->str = g_string_new(""); @@ -1280,7 +1361,12 @@ struct irc_data *idata = (struct irc_data *)gc->proto_data; gchar buf[IRC_BUF_LEN]; - g_snprintf(buf, sizeof(buf), "QUIT :Download Gaim [%s]\r\n", WEBSITE); + if (idata->str->len > 0) { + g_snprintf(buf, sizeof(buf), "QUIT :%s\r\n", idata->str->str); + } else { + g_snprintf(buf, sizeof(buf), + "QUIT :Download Gaim [%s]\r\n", WEBSITE); + } irc_write(idata->fd, buf, strlen(buf)); if (idata->rxqueue) @@ -1437,6 +1523,17 @@ } } +static void set_chan_mode(struct gaim_connection *gc, char *chan, char *mode_str) +{ + struct irc_data *id = gc->proto_data; + char buf[IRC_BUF_LEN]; + + if ((mode_str[0] == '-') || (mode_str[0] == '+')) { + g_snprintf(buf, sizeof(buf), "MODE %s %s\r\n", chan, mode_str); + irc_write(id->fd, buf, strlen(buf)); + } +} + static int handle_command(struct gaim_connection *gc, char *who, char *what) { char buf[IRC_BUF_LEN]; @@ -1516,6 +1613,9 @@ set_mode(gc, who, '+', 'v', word); } else if (!g_strcasecmp(pdibuf, "DEVOICE")) { set_mode(gc, who, '-', 'v', word); + } else if (!g_strcasecmp(pdibuf, "MODE")) { + char *chan = who; + set_chan_mode(gc, chan, word_eol[2]); } else if (!g_strcasecmp(pdibuf, "QUOTE")) { if (!*word_eol[2]) { g_free(what); @@ -1587,6 +1687,16 @@ } else if (!g_strcasecmp(pdibuf, "LIST")) { g_snprintf(buf, sizeof(buf), "LIST\r\n"); irc_write(id->fd, buf, strlen(buf)); + } else if (!g_strcasecmp(pdibuf, "QUIT")) { + char *reason = word_eol[2]; + id->str = g_string_insert(id->str, 0, reason); + do_quit(); + } else if (!g_strcasecmp(pdibuf, "VERSION")) { + g_snprintf(buf, sizeof(buf), "VERSION\r\n"); + irc_write(id->fd, buf, strlen(buf)); + } 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, "HELP")) { struct conversation *c = NULL; if (is_channel(gc, who)) { @@ -1602,7 +1712,8 @@ "WHOIS INVITE NICK LIST
" "JOIN PART TOPIC KICK
" "OP DEOP VOICE DEVOICE
" - "ME MSG QUOTE SAY", + "ME MSG QUOTE SAY QUIT
" + "MODE VERSION W", WFLAG_NOLOG, NULL, time(NULL), -1); } else { struct conversation *c = NULL;