/* Copyright (C) 2002 secret_penguinjp This is free software distributed under the terms of the GNU Public License. See the file COPYING for details. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lopster.h" #include "global.h" #include "support.h" #include "handler.h" #include "connection.h" #include "log.h" #include "chat.h" #include "server.h" #include "irc.h" #include "utils.h" #include "irc_handler.h" // should be removed later #include "napster_handler.h" #ifdef HAVE_LIBLCONV_H #include #endif static const char* irc_command_id[COMMAND_SIZE] = { NULL, // 0 unused NULL, // login // unused NULL, // share file NULL, // unshare file NULL, // unshare all files NULL, // 5 search "NS", // download request IRC_PRIVMSG, // private message IRC_NOTICE, // notice (never is replied) NULL, // hotlist add NULL, // 10 hotlist add (at server login) "NS", // browse users files NULL, // download start notification NULL, // download end notification NULL, // upload start notification NULL, // 15 upload end notification "NS", // request server stats (short) NULL, // hotlist remove IRC_JOIN, // join channel IRC_PART, // part channel IRC_PRIVMSG, // 20 send public message IRC_TOPIC, // get channel topic IRC_TOPIC, // set channel topic IRC_MODE, // get channel ban list IRC_MODE, // ban user from channel IRC_MODE, // 25 unban user from channel "NS", // request firewalled download NULL, // get user speed "NS", // list muzzle in channel "NS", // whois user "NS", // 30 set user level "NS", // accept upload IRC_KILL, // kill (disconnect) user "NS", // nuke (delete, unregister) user "NS", // ban user "NS", // 35 change user's upload port "NS", // unban user "NS", // get global ban list "NS", // upload rejected (limit) IRC_MOTD, // get MOTD "NS", // 40 muzzle user "NS", // unmuzzle user "NS", // change user's linespeed "NS", // message to all ops "NS", // message to all users "NS", // 45 request direct browse "NS", // accept direct browse request "NS", // cloak "NS", // change linespeed IRC_PASS, // change password "NS", // 50 change email "NS", // change data port IRC_PING, // ping server "NS", // ping user IRC_PONG, // pong user/server "NS", // 55 change user's password IRC_VERSION, // get server version "NS", // clear channel NULL, // get channel level NULL, // set channel level "NS", // 60 unnuke user "NS", // reload server config "NS", // get server vars "NS", // get server var "NS", // set server var "NS", // 65 redirect user "NS", // cycle user "ACTION", // emote message NULL, // get channel limit IRC_MODE, // set channel limit IRC_LIST, // 70 get channel list IRC_KICK, // kick user from channel IRC_NAMES, // get channel user list "NS", // get global user list "NS", // link server "NS", // 75 delink server "NS", // remove server "NS", // shutdown server "NS", // get server links "NS", // get server stats (long) "NS", // 80 get client version stats IRC_WHO, // locate user "NS", // whowas user "NS", // masskill ip "NS", // server incoming command histogram "NS", // 85 server outgoing command histogram "NS", // register user IRC_MODE, // get user mode IRC_MODE, // set user mode IRC_MODE, // op user in channel IRC_MODE, // 90 deop user in channel "NS", // channel wallop message IRC_MODE, // get channel mode IRC_MODE, // set channel mode "NS", // invite user to channel "NS", // 95 give user voice in channel "NS", // remove voice from user "NS", // muzzle user in channel "NS", // unmuzzle user in channel "NS", // class add "NS", //100 class remove "NS", // class list "NS", // dline add "NS", // dline remove "NS", // dline list "NS", //105 iline add "NS", // iline remove "NS", // iline list "NS", // eline add "NS", // eline remove "NS", //110 eline list NULL, // share generic media file "NS", // reset server var to default "NS", // list ops in channel "NS", // list voice in channel IRC_NICK, //115 change nick "DUMMY", // raw command // dummy command string "ACTION", // private emote }; static const char* command_supported_irc(int id) { if (id >= COMMAND_SIZE || id < 0) return 0; return irc_command_id[id]; } static void protocol_message_irc(net_t* net, int direction, char* text) { char *prefix; chat_page_t *page; page = chat_page_search(net, "Protocol", P_OTHER, 3); if (!page) page = create_other_page(net, "Protocol", "Protocol"); if (!page) return; chat_print_time_stamp(page, M_PUBLIC); if (!direction) prefix = cparse("%K>%r>%R> "); else prefix = cparse("%C<%c<%K< "); chat_print_colored(page, M_PUBLIC, "error", prefix); chat_print_colored(page, M_PUBLIC, "text", text); chat_print_text(page, M_PUBLIC, "text", "\n"); } static char* int2chmode_irc(int set, int clear) { set &= CMODE_MASK_IRC; clear &= CMODE_MASK_IRC; // dont allow both +s+p if (set & CMODE_SECRET) { clear |= CMODE_PRIVATE; set &= ~CMODE_PRIVATE; } if (set & CMODE_PRIVATE) { clear |= CMODE_SECRET; } return int2chmode_lop(set, clear); } static void command_pack_irc(net_t* net, gint16 type, va_list ap) { char* str1; char* str2; char* str3; char* pos; int added; int int1; int int2; buffer_t* buffer; const char* command; command = command_supported_irc(type); if (!command) return; buffer = net->out_buffer; // FIXME: we assume that we dont need more space than 1024 bytes if (buffer->datamax - buffer->datasize < 1024) buffer_resize(buffer, 2048); pos = buffer->data + buffer->datasize; switch (type) { case CMD_PUBLIC_EMOTE: str1 = va_arg(ap, char*); str2 = va_arg(ap, char*); added = sprintf(pos, "%s %s :\001%s %s\001", IRC_PRIVMSG, str1, command, str2); // we need to print the message, cause IRC doesnt send it back to us public_emote(net, str1, net->user.username, str2); break; case CMD_PRIVATE_EMOTE: str1 = va_arg(ap, char*); str2 = va_arg(ap, char*); added = sprintf(pos, "%s %s :\001%s %s\001", IRC_PRIVMSG, str1, command, str2); break; case CMD_RAW: str1 = va_arg(ap, char*); added = sprintf(pos, "%s", str1); break; case CMD_GET_USER_MODE: added = sprintf(pos, "%s %s", command, net->user.username); break; case CMD_KILL: str1 = va_arg(ap, char*); // user str2 = va_arg(ap, char*); // reason added = sprintf(pos, "%s %s :%s", command, str1, str2?str2:""); break; case CMD_SET_USER_MODE: str1 = va_arg(ap, char*); // mode added = sprintf(pos, "%s %s :%s", command, net->user.username, str1); break; case CMD_FULL_CHANNEL_LIST: added = sprintf(pos, "%s", command); break; case CMD_SERVER_VERSION: case CMD_MOTD: str1 = va_arg(ap, char*); // server if (str1) added = sprintf(pos, "%s %s", command, str1); else added = sprintf(pos, "%s", command); break; case CMD_JOIN: case CMD_PONG: case CMD_CHANGE_NICK: case CMD_CHANGE_PASS: case CMD_GET_CHAN_MODE: case CMD_GET_TOPIC: case CMD_NAMES_LIST: case CMD_PING_SERVER: case CMD_WHICH_SERVER: str1 = va_arg(ap, char*); added = sprintf(pos, "%s %s", command, str1); break; case CMD_PART: str1 = va_arg(ap, char*); // channel str2 = va_arg(ap, char*); // reason if (str2) added = sprintf(pos, "%s %s :%s", command, str1, str2); else added = sprintf(pos, "%s %s", command, str1); break; case CMD_PUBLIC: str1 = va_arg(ap, char*); // channel str2 = va_arg(ap, char*); // text added = sprintf(pos, "%s %s :%s", command, str1, str2); // we need to print the message, cause IRC doesnt send it back to us public_message(net, str1, net->user.username, str2); break; case CMD_DEOP: str1 = va_arg(ap, char*); // channel str2 = va_arg(ap, char*); // nick added = sprintf(pos, "%s %s -o %s", command, str1, str2); break; case CMD_OP: str1 = va_arg(ap, char*); // channel str2 = va_arg(ap, char*); // nick added = sprintf(pos, "%s %s +o %s", command, str1, str2); break; case CMD_PRIVMSG: case CMD_NOTICE: case CMD_SET_TOPIC: str1 = va_arg(ap, char*); // nick/channel str2 = va_arg(ap, char*); // text/topic added = sprintf(pos, "%s %s :%s", command, str1, str2); break; case CMD_SET_CHAN_MODE: str1 = va_arg(ap, char*); // channel int1 = va_arg(ap, int); // set int2 = va_arg(ap, int); // clear str2 = int2chmode_irc(int1, int2); if (!str2) return; added = sprintf(pos, "%s %s %s", command, str1, str2); break; case CMD_KICK: str1 = va_arg(ap, char*); // channel str2 = va_arg(ap, char*); // nick str3 = va_arg(ap, char*); // reason if (str3) added = sprintf(pos, "%s %s %s :%s", command, str1, str2, str3); else added = sprintf(pos, "%s %s %s", command, str1, str2); break; case CMD_CHANNEL_BAN_LIST: str1 = va_arg(ap, char*); // channel added = sprintf(pos, "%s %s b", command, str1); break; case CMD_CHAN_BAN: str1 = va_arg(ap, char*); // channel str2 = va_arg(ap, char*); // nick added = sprintf(pos, "%s %s +b %s", command, str1, str2); break; case CMD_CHAN_UNBAN: str1 = va_arg(ap, char*); // channel str2 = va_arg(ap, char*); // nick added = sprintf(pos, "%s %s -b %s", command, str1, str2); break; case CMD_SET_CHAN_LIMIT: str1 = va_arg(ap, char*); // channel int1 = va_arg(ap, int); // limit if (int1 == 0) added = sprintf(pos, "%s %s -l", command, str1); else added = sprintf(pos, "%s %s +l %d", command, str1, int1); break; default: printf("*** [IRC] command [%d] not implemented\n", type); return; } if (!added) return; #ifdef PROTOCOL_DEBUG l_log(net, "protocol", LOG_PROTOCOL, "S: %s\n", pos); #endif if ((global.options.no_piping & NOPIPE_PROTOCOL2) == 0) { protocol_message_irc(net, 1, pos); } added += sprintf(pos+added, "\r\n"); buffer->datasize += added; } int irc_get_command_code(char* command) { int num; if (!command) return 0; num = atoi(command); if (num) return num; if (!strcmp(command, IRC_NOTICE)) { return CIRC_NOTICE; } else if (!strcmp(command, IRC_JOIN)) { return CIRC_JOIN; } else if (!strcmp(command, IRC_PING)) { return CIRC_PING; } else if (!strcmp(command, IRC_ERROR)) { return CIRC_ERROR; } else if (!strcmp(command, IRC_NICK)) { return CIRC_NICK; } else if (!strcmp(command, IRC_PRIVMSG)) { return CIRC_PRIVMSG; } else if (!strcmp(command, IRC_PART)) { return CIRC_PART; } else if (!strcmp(command, IRC_TOPIC)) { return CIRC_TOPIC_SET; } else if (!strcmp(command, IRC_MODE)) { return CIRC_MODE; } else if (!strcmp(command, IRC_PONG)) { return CIRC_PONG; } else if (!strcmp(command, IRC_QUIT)) { return CIRC_QUIT; } else if (!strcmp(command, IRC_KICK)) { return CIRC_KICK; } return 0; } static int consume_command_irc(net_t* net) { char* result; char* last; char* data; char* first; char* from; char* command; char* args; int i; buffer_t* buffer = net->in_buffer; if (!buffer) return 0; do { if (buffer->datasize < buffer->consumed+1) return 0; first = buffer->data + buffer->consumed; data = first; last = first; for (i = buffer->consumed; i < buffer->datasize; i++, last++) { if (*last == '\r') continue; else if (*last == '\n') break; else if (*last == '\0') printf("*** 0 char\n"); else if (last != data) *data++ = *last; else data++; } if (i == buffer->datasize) return 0; *data = 0; last++; #ifdef PROTOCOL_DEBUG l_log(net, "protocol", LOG_PROTOCOL, "R: %s\n", first); #endif if ((global.options.no_piping & NOPIPE_PROTOCOL1) == 0) { protocol_message_irc(net, 0, first); } buffer_consume_virt(buffer, (last-first)); // printf("[c_type = irc_get_command_code(command); if (from) result = g_strdup_printf("%s %s", from, args); else result = g_strdup(args); net->c_length = strlen(result); net->c_message = result; return 1; } /* char *irc_irc2nap(net_t* net, char *data) { char* result; char* pos1; char* pos2; int n; irc_flag_notice = 0; if (*data != ':') { if (!strncmp (data, "NOTICE ", 7)) { net->c_type = CIRC_PRIVATE_NOTICE; result = g_strdup(data+7); } else if (!strncmp (data, "PING ", 5)) { net->c_type = CIRC_PING; result = g_strdup(data+5); } else if (!strncmp (data, "ERROR ", 6)) { net->c_type = CIRC_ERROR; result = g_strdup(data+6); } else { net->c_type = 20000; result = g_strdup(data); } return result; } data++; pos1 = arg(data, 0); pos1 = arg(NULL, 0); pos2 = arg(NULL, 1); if (!pos2) return NULL; n = atoi(pos1); if (n) { return process_numeric(net, n, data, pos2); } else { return process_command(net, data, pos1, pos2); } } */ /* char *irc_rpl_n(net_t* net, irc_t *irc, char *last) { char *data; char *wk; chat_page_t *page; if (irc->command_num == 1) { net->c_type = NAP_EMAIL; data = g_strdup_printf("admin@lopster.irc"); irc_handle_command(net, data); } if (irc->command_num > 001 && irc->command_num < 100) { // 000 - 099 net->c_type = NAP_ANNOUNCE; // strtok_r(NULL," ", &last); if (last[0] == ':') last++; return g_strdup_printf("SRV %s", last); } switch (irc->command_num) { case RPL_LUSERME: // 255 net->c_type = NAP_STATS; strtok_r(NULL," ", &last); strtok_r(NULL," ", &last); strtok_r(NULL," ", &last); return g_strdup_printf("%s 0 0", strtok_r(NULL," ", &last)); case RPL_LUSEROP: // 252 case RPL_LUSERCLIENT: // 251 case RPL_LUSERUNKNOWN: // 253 case RPL_LUSERCHANNELS: // 254 net->c_type = NAP_ANNOUNCE; strtok_r(NULL," ", &last); if (last[0] == ':') last++; return g_strdup_printf("%s %s", IRC_SRV_MSG, last); case RPL_ISON: // 303 if (last[0] == ':') last++; irc->params = last; if (irc->params[0]) { net->c_type = MODE_ERROR; data = g_strdup_printf("Nickname is already in use: %s", last); } else { net->c_type = CMD_SERVER_ANNOUNCE; // [SrvMsg] Nickname can be used. data = g_strdup_printf("%s Nickname can be used.", IRC_SRV_MSG); } return data; case ERR_NOMOTD: // 422 net->c_type = NAP_MOTD; strtok_r(NULL," ", &last); if (last[0] == ':') last++; return g_strdup_printf("%s", last); case RPL_CHANNELMODEIS: // 324 // " " net->c_type = NAP_PUBLIC; // 403 irc->msgtarget = strtok_r(NULL," ", &last); irc->channel = strtok_r(NULL," ", &last); return g_strdup_printf("%s --- %s sets channel mode to %s", irc->channel, irc->msgtarget, last); case ERR_NICKNAMEINUSE: // 433 // " :Nickname is already in use" // ex. // NICK test // :server 433 * test :Nickname is already in use. net->c_type = NAP_REGISTER; last = strchr(last, '*') + 2; irc->nickname = strtok_r(NULL," :", &last); break; case ERR_NOTONCHANNEL: // 442 net->c_type = NAP_PART; // 401 strtok_r(NULL," ", &last); irc->channel = strtok_r(NULL," ", &last); return g_strdup(irc->channel); // WHOIS case RPL_WHOISUSER: // 311 case RPL_WHOISCHANNELS: // 319 case RPL_WHOISSERVER: // 312 case RPL_WHOISIDLE: // 317 case RPL_ENDOFWHOIS: // 318 net->c_type = NAP_ANNOUNCE; strtok_r(NULL," ", &last); irc->nickname = strtok_r(NULL," :", &last); return g_strdup_printf("WhoIs [%s] %s", irc->nickname, last); // WHOWAS case RPL_WHOWASUSER: // 314 case RPL_ENDOFWHOWAS: // 369 net->c_type = NAP_ANNOUNCE; strtok_r(NULL," ", &last); irc->nickname = strtok_r(NULL," :", &last); return g_strdup_printf("WhoWas [%s] %s", irc->nickname, last); // WHO case RPL_WHOREPLY: // 352 net->c_type = NAP_ANNOUNCE; return g_strdup_printf("Who %s", last); case RPL_ENDOFWHO: // 315 net->c_type = NAP_ANNOUNCE; strtok_r(NULL," ", &last); irc->nickname = strtok_r(NULL," :", &last); return g_strdup_printf("Who [%s] %s", irc->nickname, last); case RPL_INVITING: // 341 net->c_type = NAP_ANNOUNCE; strtok_r(NULL," ", &last); irc->nickname = strtok_r(NULL," :", &last); return g_strdup_printf("--- You're inviting %s to %s", irc->nickname, last); case ERR_CHANOPRIVSNEEDED: // 482 page = chat_page_search(net, irc->channel, P_PUBLIC, 1); net->user.level = L_USER; chat_page_set_op(page, FALSE); page->opped = FALSE; net->c_type = NAP_ANNOUNCE; strtok_r(NULL," ", &last); irc->channel = strtok_r(NULL," :", &last); return g_strdup_printf("--- %s :You're not channel operator", irc->channel); default: irc->msgtarget = strtok_r(NULL," ", &last); break; } if (last[0] == ':') last++; irc->params = last; if (irc->command_num == RPL_ISON) { // 303 if (irc->params[0]) { net->c_type = NAP_ERROR; return g_strdup_printf("Nickname is already in use: %s", last); } else net->c_type = NAP_ANNOUNCE; return g_strdup_printf("Nickname is OK."); } if (irc->command_num >= 400 && irc->command_num < 600) { // 400 - 599 net->c_type = NAP_ANNOUNCE; return g_strdup_printf("SRV %s", last); } net->c_type = NAP_ANNOUNCE; return g_strdup_printf("SRV %s", last); return NULL; } */ /* char *irc_rpl_a(net_t* net, irc_t *irc, char *last) { char *data; // 3.3.1 Private messages // 3.3.2 Notice if (!strcasecmp(irc->command, IRC_PRIVMSG) || !strcasecmp(irc->command, IRC_NOTICE)) { irc->msgtarget = strtok_r(NULL," ", &last); if (is_channel(irc->msgtarget)) net->c_type = NAP_PUBLIC; // 403 else net->c_type = NAP_PRIVMSG; // 205 if (last[0] == ':') last++; // CTCP if (is_ctcp(last)) return irc_ctcp_old(net, irc, last); if (net->c_type == NAP_PUBLIC) { // return g_strdup_printf("%s %s %s", irc->msgtarget, irc->nickname, last); } else { // return g_strdup_printf("%s %s", irc->nickname, last); } } // Misc.... irc->nickname = strtok_r(NULL," ", &last); if (last[0] == ':') last++; irc->params = last; // FIXME net->c_type = NAP_ANNOUNCE; return g_strdup(last); return NULL; } */ /* ************************************************************************* */ /* * CTCP * */ /* ************************************************************************* */ /* char *irc_ctcp_old(net_t* net, irc_t *irc, char *data) { int i, j, k, len, rc_type = 0; int ctr, ctr_send; char *msg, *ctcp_msg, *rc = NULL; int sw_ctcp; len = strlen(data); msg = malloc((size_t)len); ctcp_msg = malloc((size_t)len); sw_ctcp = ctr_send = ctr = j = k = 0; // Initialize for (i=0; ic_type; ctr_send++; } sw_ctcp = k = 0; } else { sw_ctcp = 1; if (ctr != ctr_send) { #warning FIXME! // command_send(rc_type, rc, net); ctr_send++; } ctr++; } i++; // data[i] = 0x01, next pointer, next step. } // Found 0x01 Process end. if (sw_ctcp) { ctcp_msg[k++] = data[i]; } else { msg[j++] = data[i]; } } // end-for // if (sw_ctcp) printf("CTCP: ERRMSG SEND.\n"); if (j > 1) { msg[j] = 0; // printf("MSG:[%d][%s]\n", j, msg); } net->c_type = rc_type; return rc; } int is_ctcp(const char *data) { int i; int rc; rc = 0; for (i=0; data[i]; i++) { if (data[i] == 0x01) { // CTCP BIT. rc = 1; break; } } return rc; } */ /* char *ctcp_time() { struct tm *tm; char *out = NULL; size_t out_len = 0; time_t when; when = time(NULL); tm = localtime(&when); out_len = 200; out = (char *) malloc(out_len); setlocale (LC_TIME, "C"); strftime (out, out_len, "%a %b %_d %H:%M:%S %Y %Z", tm); setlocale (LC_TIME, ""); return out; } */ /* char *irc_ctcp_send_command(net_t* net, irc_t* irc, char *ctcp_msg) { char *data, *wk; char *ctcp_cmd, *last; last = ctcp_msg; ctcp_cmd = strtok_r(ctcp_msg," ",&last); if (!strcasecmp(ctcp_cmd, IRC_CTCP_VERSION)) { net->c_type = CMD_NOTICE; data = g_strdup_printf("%s %c%s Lopster %s%c", irc->nickname, ASCII_CTCP, IRC_CTCP_VERSION, VERSION, ASCII_CTCP); #warning FIXME! // send_command(net->c_type, data, net); net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_VERSION); } if (!strcasecmp(ctcp_cmd, IRC_CTCP_USERINFO)) { net->c_type = CMD_NOTICE; data = g_strdup_printf("%s %c%s :%s%c", irc->nickname, ASCII_CTCP, IRC_CTCP_USERINFO, net->user.username, ASCII_CTCP); // send_command(net->c_type, data, net); net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_USERINFO); } if (!strcasecmp(ctcp_cmd, IRC_CTCP_CLIENTINFO)) { net->c_type = CMD_NOTICE; data = g_strdup_printf("%s %c%s :%s %s %s %s %s %s %s%c", irc->nickname, ASCII_CTCP, IRC_CTCP_CLIENTINFO, // Support function list IRC_CTCP_VERSION, // VERSION IRC_CTCP_USERINFO, // USERINFO IRC_CTCP_CLIENTINFO, // CLIENTINFO IRC_CTCP_PING, // PING IRC_CTCP_TIME, // TIME IRC_CTCP_SOURCE, // SOURCE IRC_CTCP_X_NAP, // X-NAP ASCII_CTCP ); // send_command(net->c_type, data, net); net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_CLIENTINFO); } if (!strcasecmp(ctcp_cmd, IRC_CTCP_PING)) { net->c_type = CMD_NOTICE; data = g_strdup_printf("%s %c%s %s%c", irc->nickname, ASCII_CTCP, ctcp_cmd, last, ASCII_CTCP); // send_command(net->c_type, data, net); net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_PING); } if (!strcasecmp(ctcp_cmd, IRC_CTCP_TIME)) { net->c_type = CMD_NOTICE; wk = ctcp_time(); data = g_strdup_printf("%s %c%s :%s%c", irc->nickname, ASCII_CTCP, IRC_CTCP_TIME, wk, ASCII_CTCP ); // send_command(net->c_type, data, net); g_free(wk); net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_TIME); } if (!strcasecmp(ctcp_cmd, IRC_CTCP_SOURCE)) { net->c_type = CMD_NOTICE; wk = ctcp_time(); data = g_strdup_printf("%s %c%s :The latest version of Lopster can be obtained from %s%c", irc->nickname, ASCII_CTCP, IRC_CTCP_SOURCE, IRC_CTCP_SOURCE_URL, ASCII_CTCP ); // send_command(net->c_type, data, net); g_free(wk); net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_TIME); } if (!strcasecmp(ctcp_cmd, IRC_CTCP_FINGER)) { net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_FINGER); } if (!strcasecmp(ctcp_cmd, IRC_CTCP_XDCC_LIST)) { net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_XDCC_LIST); } if (!strcasecmp(ctcp_cmd, IRC_CTCP_CDCC_LIST)) { net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_CDCC_LIST); } // Lopster.... Only if (!strcasecmp(ctcp_cmd, IRC_CTCP_X_NAP_BROWSE_DIRECT)) { net->c_type = CMD_BROWSE_DIRECT_OK; // 641 data = g_strdup_printf("%s", last); // irc_handle_command(net, data); net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_X_NAP_BROWSE_DIRECT); } if (!strcasecmp(ctcp_cmd, IRC_CTCP_X_NAP_BROWSE)) { // net->c_type = CMD_SERVER_BROWSE_RESPONSE; // 212 net->c_type = CMD_BROWSE_DIRECT_OK; // 641 FIXME::::: data = g_strdup_printf("%s", last); // irc_handle_command(net, data); net->c_type = CMD_ANNOUNCE; return g_strdup_printf("%s CTCP %s", irc->nickname, IRC_CTCP_X_NAP_BROWSE); } return g_strdup_printf("%s", irc->nickname); } */ /* ************************************************************************* */ /* * irc_handle_command * */ /* ************************************************************************* */ /* void irc_handle_command(net_t* net, char* data) { net->c_length = strlen(data); handle_command(net, data); g_free(data); } */ // // NAP -> IRC Conversion function // /* char *irc_nap2irc(net_command_t * command, net_t* net) { unsigned char *msg; char *data, *last, *channel; char *lconv_buf; #ifdef HAVE_LIBLCONV_H if (!global.options.use_iconv) { #endif lconv_buf = g_strdup(command->data); #ifdef HAVE_LIBLCONV_H } else { lconv_buf = lconv_strdup_conv(LCONV_SPEC, net->codeset, local_codeset, command->data); } #endif switch (command->type) { case CMD_ADD_HOTLIST_SEQ: // 208 // 301 (0x12d) hotlist ack [SERVER] // Format: net->queue = g_list_remove(net->queue, command); // net->c_type = NAP_HOTLIST_ACK; // data = g_strdup(command->data); // irc_handle_command(net, data); return NULL; case CMD_DOWNLOAD_START: // 218 case CMD_UPLOAD_START: // 220 case NAP_IGNORE_USER: // 322 net->queue = g_list_remove(net->queue, command); return NULL; case CMD_LOGIN: // server.c server_login() msg = g_strdup_printf( "%s %s\r\n%s %s\r\n%s %s %s %s :%s\r\n", IRC_PASS, net->user.password, // PASS IRC_NICK, net->user.username, // NICK IRC_USER, net->user.username, "8", "*", net->user.username); // USER break; case CMD_JOIN: msg = g_strdup_printf("%s %s\r\n", IRC_JOIN, lconv_buf); break; // PRIVMSG case CMD_ANNOUNCE: // 628 FIXME // 4.7 Operwall message msg = g_strdup_printf("%s %s\r\n", IRC_WALLOPS, lconv_buf); break; case CMD_PRIVMSG: // 205 last = lconv_buf; data = strtok_r(lconv_buf," ", &last); msg = g_strdup_printf("%s %s :%s\r\n", IRC_PRIVMSG, data, last); break; case CMD_NOTICE: last = lconv_buf; data = strtok_r(lconv_buf," ", &last); msg = g_strdup_printf("%s %s :%s\r\n", IRC_NOTICE, data, last); break; case CMD_EMOTE: // 824 FIXME "" last = lconv_buf; channel = strtok_r(lconv_buf," ", &last); last++; last[strlen(last)-1] = 0; msg = g_strdup_printf("%s %s :\001ACTION %s\001\r\n", IRC_PRIVMSG, channel, last); net->c_type = CIRC_CTCP; data = g_strdup_printf("%s %s ACTION :%s", net->user.username, channel, last); irc_handle_command(net, data); break; case CMD_CHAN_WALLOP: // 10208 FIXME case CMD_PUBLIC: // 402 last = lconv_buf; channel = strtok_r(lconv_buf," ", &last); msg = g_strdup_printf("%s %s :%s\r\n", IRC_PRIVMSG, channel, last); net->c_type = CIRC_PUBLIC; // 403 c n t last = command->data; channel = strtok_r(command->data," ", &last); data = g_strdup_printf("%s %s %s", channel, net->user.username, last); irc_handle_command(net, data); break; case CMD_SERVER_DISCONNECT: msg = g_strdup_printf("%s Bye\r\n", IRC_QUIT); case CMD_FULL_CHANNEL_LIST: msg = g_strdup_printf("%s\r\n", IRC_LIST); break; case CMD_NAMES_LIST: msg = g_strdup_printf("%s %s\r\n", IRC_NAMES, lconv_buf); break; case CMD_SET_CHAN_MODE: // 10209 case CMD_SET_CHAN_LIMIT: // 826 if ((msg = irc_mode_nap(command->type, lconv_buf)) == NULL) { g_free(lconv_buf); return NULL; } break; case CMD_SET_CHAN_LEVEL: // 823 net->queue = g_list_remove(net->queue, command); return 0; case CMD_PART: // 401 // PART data = g_strdup(lconv_buf); msg = g_strdup_printf("%s %s :See you.\r\n", IRC_PART, lconv_buf); break; case CMD_PONG: msg = g_strdup_printf("%s %s\r\n", IRC_PONG, lconv_buf); break; case CMD_CHAN_INVITE: // 10210 last = lconv_buf; data = strtok_r(lconv_buf," ", &last); msg = g_strdup_printf("%s %s %s\r\n", IRC_INVITE, last, data); break; case CMD_KICK: // 829 msg = g_strdup_printf("%s %s\r\n", IRC_KICK, lconv_buf); break; case CMD_KILL: // 610 msg = g_strdup_printf("%s %s\r\n", IRC_KILL, lconv_buf); break; case CMD_SET_TOPIC: // 410 // 410 // TOPIC [ ] last = lconv_buf; data = strtok_r(lconv_buf," ", &last); if (*last) msg = g_strdup_printf("%s %s :%s\r\n", IRC_TOPIC, data, last); else msg = g_strdup_printf("%s %s\r\n", IRC_TOPIC, data); break; case CMD_WHOIS: // 603 msg = g_strdup_printf("%s %s\r\n", IRC_WHOIS, lconv_buf); break; case CMD_WHICH_SERVER: // 10119 msg = g_strdup_printf("%s %s\r\n", IRC_WHO, lconv_buf); break; // BAN case CMD_CHAN_BAN: // 422 last = lconv_buf; channel = strtok_r(lconv_buf," ", &last); msg = g_strdup_printf("MODE %s +b %s\r\n", channel, last); break; case CMD_CHAN_UNBAN: // 423 last = lconv_buf; channel = strtok_r(lconv_buf," ", &last); msg = g_strdup_printf("MODE %s -b %s\r\n", channel, last); break; // OP case CMD_OP: // 10204 last = lconv_buf; channel = strtok_r(lconv_buf," ", &last); msg = g_strdup_printf("MODE %s +o %s\r\n", channel, last); break; case CMD_DEOP: // 10205 last = lconv_buf; channel = strtok_r(lconv_buf," ", &last); msg = g_strdup_printf("MODE %s -o %s\r\n", channel, last); break; // Lopster Only. CTCP X-NAP-BROWSE case CMD_BROWSE: // 211 msg = g_strdup_printf("%s %s :%c%s %s%c", IRC_PRIVMSG, lconv_buf, // ASCII_CTCP, IRC_CTCP_X_NAP_BROWSE, net->user.username, // nick ASCII_CTCP); break; // Lopster Only, CTCP X-NAP-BROWSE-DIRECT case CMD_BROWSE_DIRECT: // 640 // Server: msg = g_strdup_printf("%s %s :%c%s %s %u %hu%c", IRC_PRIVMSG, lconv_buf, // ASCII_CTCP, IRC_CTCP_X_NAP_BROWSE_DIRECT, net->user.username, // nick BSWAP32( irc_myip() ), // ip global.network.port, // %hu : data port ASCII_CTCP); break; default: net->queue = g_list_remove(net->queue, command); g_free(lconv_buf); return NULL; } g_free(lconv_buf); return msg; } */ /* unsigned int irc_myip() { struct hostent *hp; if( (hp = gethostbyname( irc_My_Host )) == NULL ){ return 0; } return (unsigned int)hp->h_addr_list[0]; } */ static int server_login_irc(gpointer data, gint source ATTR_UNUSED, GdkInputCondition condition) { socket_t *socket = data; net_t *net = socket->data; char text[2084]; gint16 size; if (condition != GDK_INPUT_WRITE) { // net->active_server->ip = INADDR_NONE; // printf("could not login %d\n", condition); server_disconnect(net->active_server, "Could not login (write error)", 1); return 1; } gdk_input_remove(socket->output); socket->output = -1; server_set_status(net->active_server, SERVER_CONNECTING, "Logging in..."); // logging in and registering with mode '4' (receive wallops) size = sprintf(text, "%s %s\r\n%s %s\r\n%s %s %s %s :%s\r\n", IRC_PASS, net->user.password, // PASS IRC_NICK, net->user.username, // NICK IRC_USER, net->user.username, "4", "*", net->user.username); if (send_safe(socket->fd, text, size, size) < 0) { server_disconnect(net->active_server, "Could not login (command send error)", 1); return 1; } socket->input = gdk_input_add(socket->fd, GDK_INPUT_READ, GTK_SIGNAL_FUNC(server_get_input), socket); return 0; } static void channel_setup_irc(chat_page_t* page) { GtkWidget* wid; if (page->main) { wid = gtk_object_get_data(GTK_OBJECT(page->main), CModeNames[1]); gtk_widget_hide(wid); wid = gtk_object_get_data(GTK_OBJECT(page->main), CModeNames[7]); gtk_widget_hide(wid); wid = gtk_object_get_data(GTK_OBJECT(page->main), CModeNames[8]); gtk_widget_hide(wid); wid = gtk_object_get_data(GTK_OBJECT(page->main), CModeNames[9]); gtk_widget_hide(wid); wid = gtk_object_get_data(GTK_OBJECT(page->main), "level"); gtk_widget_hide(wid); } if (page->online) { gtk_clist_set_column_visibility(GTK_CLIST(page->online), 1, 0); gtk_clist_set_column_visibility(GTK_CLIST(page->online), 2, 0); } } static int network_success_irc(net_t* net) { net->subtype = N_IRC; net->major = 0; net->minor = 0; net->micro = 0; net->max_searches = 0; net->max_searches_pm = 0; update_status_line(0); return 1; } static void login_irc(socket_t* socket) { socket->output = gdk_input_add(socket->fd, GDK_INPUT_WRITE, GTK_SIGNAL_FUNC(server_login_irc), socket); } HANDLER_ENTRY* search_handler_irc(int command); static void handle_command_irc(net_t* net) { HANDLER_ENTRY* handler; if (!net->c_message) g_warning("no message"); handler = search_handler_irc(net->c_type); if (!handler) { not_implemented(net, net->c_message); } else if (handler->handler) { handler->handler(net, net->c_message); } } void setup_functions_irc(net_t* net) { net->success = network_success_irc; net->consume_command = consume_command_irc; net->login = login_irc; net->command_pack = command_pack_irc; net->channel_setup = channel_setup_irc; net->handle_command = handle_command_irc; }