Mercurial > pidgin
diff src/protocols/irc/irc.c @ 5211:0241d6b6702d
[gaim-migrate @ 5581]
Wrote a new debugging API, and of course core/ui split it. Debug statements
can now have debug levels and categories, for future filtering of stuff,
and color highlighting. It's nifty, m'kay?
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Sat, 26 Apr 2003 06:46:08 +0000 |
parents | fefad67de2c7 |
children | abe4d103e300 |
line wrap: on
line diff
--- a/src/protocols/irc/irc.c Sat Apr 26 05:31:26 2003 +0000 +++ b/src/protocols/irc/irc.c Sat Apr 26 06:46:08 2003 +0000 @@ -1310,6 +1310,66 @@ write(xfer->fd, (char *)&pos, 4); } +/* NOTE: This was taken from irssi. Thanks irssi! */ + +static gboolean +is_numeric(const char *str, char end_char) +{ + g_return_val_if_fail(str != NULL, FALSE); + + if (*str == '\0' || *str == end_char) + return FALSE; + + while (*str != '\0' && *str != end_char) { + if (*str < '0' || *str > '9') + return FALSE; + + str++; + } + + return TRUE; +} + +#define get_params_match(params, pos) \ + (is_numeric(params[pos], '\0') && \ + is_numeric(params[(pos)+1], '\0') && atol(params[(pos)+1]) < 65536 && \ + is_numeric(params[(pos)+2], '\0')) + +/* Return number of parameters in `params' that belong to file name. + Normally it's paramcount-3, but I don't think anything forbids of + adding some extension where there could be more parameters after + file size. + + MIRC sends filenames with spaces quoted ("file name"), but I'd rather + not trust that entirely either. At least some clients that don't really + understand the problem with spaces in file names sends the file name + without any quotes. */ +static int +get_file_params_count(char **params, int paramcount) +{ + int pos, best; + + if (*params[0] == '"') { + /* quoted file name? */ + for (pos = 0; pos < paramcount - 3; pos++) { + if (params[pos][strlen(params[pos]) - 1] == '"' && + get_params_match(params, pos + 1)) { + + return pos + 1; + } + } + } + + best = paramcount - 3; + + for (pos = paramcount - 3; pos > 0; pos--) { + if (get_params_match(params, pos)) + best = pos; + } + + return best; +} + static void handle_ctcp(struct gaim_connection *gc, char *to, char *nick, char *msg, char *word[], char *word_eol[]) @@ -1325,19 +1385,19 @@ g_snprintf(out, sizeof(out), ">> CTCP VERSION requested from %s", nick); do_error_dialog(out, _("IRC CTCP info"), GAIM_INFO); } - if (!g_ascii_strncasecmp(msg, "CLIENTINFO", 10)) { + else if (!g_ascii_strncasecmp(msg, "CLIENTINFO", 10)) { g_snprintf(buf, sizeof(buf), "\001CLIENTINFO USERINFO CLIENTINFO VERSION\001"); irc_send_notice (gc, nick, buf); g_snprintf(out, sizeof(out), ">> CTCP CLIENTINFO requested from %s", nick); do_error_dialog(out, _("IRC CTCP info"), GAIM_INFO); } - if (!g_ascii_strncasecmp(msg, "USERINFO", 8)) { + else if (!g_ascii_strncasecmp(msg, "USERINFO", 8)) { g_snprintf(buf, sizeof(buf), "\001USERINFO Alias: %s\001", gc->account->alias); irc_send_notice (gc, nick, buf); g_snprintf(out, sizeof(out), ">> CTCP USERINFO requested from %s", nick); do_error_dialog(out, _("IRC CTCP info"), GAIM_INFO); } - if (!g_ascii_strncasecmp(msg, "ACTION", 6)) { + else if (!g_ascii_strncasecmp(msg, "ACTION", 6)) { char *po = strchr(msg + 6, 1); char *tmp; if (po) *po = 0; @@ -1345,13 +1405,13 @@ handle_privmsg(gc, to, nick, tmp); g_free(tmp); } - if (!g_ascii_strncasecmp(msg, "PING", 4)) { + else if (!g_ascii_strncasecmp(msg, "PING", 4)) { g_snprintf(buf, sizeof(buf), "\001%s\001", msg); irc_send_notice (gc, nick, buf); g_snprintf(out, sizeof(out), ">> CTCP PING requested from %s", nick); do_error_dialog(out, _("IRC CTCP info"), GAIM_INFO); } - if (!g_ascii_strncasecmp(msg, "DCC CHAT", 8)) { + else if (!g_ascii_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); @@ -1362,24 +1422,60 @@ g_snprintf(ask, sizeof(ask), _("%s would like to establish a DCC chat"), nick); do_ask_dialog(ask, _("This requires a direct connection to be established between the two computers. Messages sent will not pass through the IRC server"), dccchat, _("Connect"), dcc_chat_init, _("Cancel"), dcc_chat_cancel, my_protocol->handle, FALSE); } - - - if (!g_ascii_strncasecmp(msg, "DCC SEND", 8)) { + else if (!g_ascii_strncasecmp(msg, "DCC SEND", 8)) { struct gaim_xfer *xfer; char **send_args; char *ip, *filename; struct irc_xfer_data *xfer_data; size_t size; + int param_count, file_params, len; int port; - send_args = g_strsplit(msg, " ", 6); - send_args[5][strlen(send_args[5])-1] = 0; + /* Okay, this is ugly, but should get us past "DCC SEND" */ + msg = strstr(msg, "DCC SEND"); + msg = strchr(msg, ' ') + 1; + msg = strchr(msg, ' ') + 1; + + /* SEND <file name> <address> <port> <size> [...] */ + send_args = g_strsplit(msg, " ", -1); + + for (param_count = 0; send_args[param_count] != NULL; param_count++) + ; + + if (param_count < 4) { + char buf[IRC_BUF_LEN]; + + g_snprintf(buf, sizeof(buf), + _("Received an invalid file send request from %s."), + nick); + + do_error_dialog(buf, _("IRC Error"), GAIM_ERROR); + + return; + } + + file_params = get_file_params_count(send_args, param_count); + + /* send_args[paramcount - 1][strlen(send_args[5])-1] = 0; */ /* Give these better names. */ - ip = send_args[3]; - filename = send_args[2]; - size = atoi(send_args[5]); - port = atoi(send_args[4]); + ip = send_args[file_params]; + port = atoi(send_args[file_params + 1]); + size = atoi(send_args[file_params + 2]); + + send_args[file_params] = NULL; + + filename = g_strjoinv(" ", send_args); + + g_strfreev(send_args); + + len = strlen(filename); + + if (len > 1 && *filename == '"' && filename[len - 1] == '"') { + /* "file name" - MIRC sends filenames with spaces like this */ + filename[len - 1] = '\0'; + g_memmove(filename, filename + 1, len); + } /* Setup the IRC-specific transfer data. */ xfer_data = g_malloc0(sizeof(struct irc_xfer_data)); @@ -1410,8 +1506,6 @@ /* Now perform the request! */ gaim_xfer_request(xfer); } - - /*write_to_conv(c, out, WFLAG_SYSTEM, NULL, time(NULL), -1);*/ } static gboolean