static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client) { GSList *tmp, *nicks; GString *str; int first; proxy_outserver(client, "JOIN %s", channel->name); str = g_string_new(NULL); create_names_start(str, channel, client); first = TRUE; nicks = nicklist_getnicks(CHANNEL(channel)); for (tmp = nicks; tmp != NULL; tmp = tmp->next) { NICK_REC *nick = tmp->data; if (str->len >= 500) { g_string_append_c(str, '\n'); proxy_outdata(client, "%s", str->str); create_names_start(str, channel, client); first = TRUE; } if (first) first = FALSE; else g_string_append_c(str, ' '); if (nick->other) g_string_append_c(str, nick->other); else if (nick->op) g_string_append_c(str, '@'); else if (nick->halfop) g_string_append_c(str, '%'); else if (nick->voice) g_string_append_c(str, '+'); g_string_append(str, nick->nick); } g_slist_free(nicks); g_string_append_c(str, '\n'); proxy_outdata(client, "%s", str->str); g_string_free(str, TRUE); proxy_outdata(client, ":%s 366 %s %s :End of /NAMES list.\n", client->proxy_address, client->nick, channel->name); /* this is needed because the topic may be encoded into other charsets internaly */ if (channel->topic != NULL) { proxy_outdata(client, ":%s 332 %s %s :%s\n", client->proxy_address, client->nick, channel->name, recode_out(channel->topic, channel->name)); } }
static void sig_dump(CLIENT_REC *client, const char *data) { g_return_if_fail(client != NULL); g_return_if_fail(data != NULL); proxy_outdata(client, data); }
void proxy_outserver_all_except(CLIENT_REC *client, const char *data, ...) { va_list args; GSList *tmp; char *str; g_return_if_fail(client != NULL); g_return_if_fail(data != NULL); va_start(args, data); str = g_strdup_vprintf(data, args); for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; if (rec->connected && rec != client && rec->server == client->server) { proxy_outdata(rec, ":%s!%s@proxy %s\n", rec->nick, settings_get_str("user_name"), str); } } g_free(str); va_end(args); }
void proxy_client_reset_nick(CLIENT_REC *client) { if (client->server == NULL || strcmp(client->nick, client->server->nick) == 0) return; proxy_outdata(client, ":%s!proxy NICK :%s\n", client->nick, client->server->nick); g_free(client->nick); client->nick = g_strdup(client->server->nick); }
static void proxy_server_disconnected(CLIENT_REC *client, IRC_SERVER_REC *server) { GSList *tmp; proxy_outdata(client, ":%s NOTICE %s :Connection lost to server %s\r\n", client->proxy_address, client->nick, server->connrec->address); for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { IRC_CHANNEL_REC *rec = tmp->data; proxy_outserver(client, "PART %s :Connection lost to server", rec->name); } }
void proxy_outserver(CLIENT_REC *client, const char *data, ...) { va_list args; char *str; g_return_if_fail(client != NULL); g_return_if_fail(data != NULL); va_start(args, data); str = g_strdup_vprintf(data, args); proxy_outdata(client, ":%s!%s@proxy %s\n", client->nick, settings_get_str("user_name"), str); g_free(str); va_end(args); }
static void event_connected(IRC_SERVER_REC *server) { GSList *tmp; const char *chatnet; if (!IS_IRC_SERVER(server)) return; chatnet = server->connrec->chatnet; for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; if (rec->connected && rec->server == NULL && (g_strcmp0(rec->listen->ircnet, "*") == 0 || (chatnet != NULL && g_ascii_strcasecmp(chatnet, rec->listen->ircnet) == 0))) { proxy_outdata(rec, ":%s NOTICE %s :Connected to server\r\n", rec->proxy_address, rec->nick); rec->server = server; proxy_client_reset_nick(rec); } } }
static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, const char *data) { GSList *tmp; if (!client->connected) { handle_client_connect_cmd(client, cmd, args); return; } if (g_strcmp0(cmd, "QUIT") == 0) { remove_client(client); return; } if (g_strcmp0(cmd, "PING") == 0) { /* Reply to PING, if the target parameter is either proxy_adress, our own nick or empty. */ char *params, *origin, *target; params = event_get_params(args, 2, &origin, &target); if (*target == '\0' || g_ascii_strcasecmp(target, client->proxy_address) == 0 || g_ascii_strcasecmp(target, client->nick) == 0) { proxy_outdata(client, ":%s PONG %s :%s\r\n", client->proxy_address, client->proxy_address, origin); g_free(params); return; } g_free(params); } if (g_strcmp0(cmd, "PROXY") == 0) { if (g_ascii_strcasecmp(args, "CTCP ON") == 0) { /* client wants all ctcps */ client->want_ctcp = 1; for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; if ((g_ascii_strcasecmp(client->listen->ircnet,rec->listen->ircnet) == 0) && /* kludgy way to check if the clients aren't the same */ (client->recv_tag != rec->recv_tag)) { if (rec->want_ctcp == 1) proxy_outdata(rec, ":%s NOTICE %s :Another client is now receiving CTCPs sent to %s\r\n", rec->proxy_address, rec->nick, rec->listen->ircnet); rec->want_ctcp = 0; } } proxy_outdata(client, ":%s NOTICE %s :You're now receiving CTCPs sent to %s\r\n", client->proxy_address, client->nick,client->listen->ircnet); } else if (g_ascii_strcasecmp(args, "CTCP OFF") == 0) { /* client wants proxy to handle all ctcps */ client->want_ctcp = 0; proxy_outdata(client, ":%s NOTICE %s :Proxy is now handling itself CTCPs sent to %s\r\n", client->proxy_address, client->nick, client->listen->ircnet); } else { signal_emit("proxy client command", 3, client, args, data); } return; } if (client->server == NULL || !client->server->connected) { proxy_outdata(client, ":%s NOTICE %s :Not connected to server\r\n", client->proxy_address, client->nick); return; } /* check if the command could be redirected */ if (g_strcmp0(cmd, "WHO") == 0) grab_who(client, args); else if (g_strcmp0(cmd, "WHOWAS") == 0) proxy_redirect_event(client, "whowas", 1, args, -1); else if (g_strcmp0(cmd, "WHOIS") == 0) { char *p; /* convert dots to spaces */ for (p = args; *p != '\0'; p++) if (*p == ',') *p = ' '; proxy_redirect_event(client, "whois", 1, args, TRUE); } else if (g_strcmp0(cmd, "ISON") == 0) proxy_redirect_event(client, "ison", 1, args, -1); else if (g_strcmp0(cmd, "USERHOST") == 0) proxy_redirect_event(client, "userhost", 1, args, -1); else if (g_strcmp0(cmd, "MODE") == 0) { /* convert dots to spaces */ char *slist, *str, mode, *p; int argc; p = strchr(args, ' '); if (p != NULL) *p++ = '\0'; mode = p == NULL ? '\0' : *p; slist = g_strdup(args); argc = 1; for (p = slist; *p != '\0'; p++) { if (*p == ',') { *p = ' '; argc++; } } /* get channel mode / bans / exception / invite list */ str = g_strdup_printf("%s %s", args, slist); switch (mode) { case '\0': proxy_redirect_event(client, "mode channel", argc, str, -1); break; case 'b': proxy_redirect_event(client, "mode b", argc, str, -1); break; case 'e': proxy_redirect_event(client, "mode e", argc, str, -1); break; case 'I': proxy_redirect_event(client, "mode I", argc, str, -1); break; } g_free(str); g_free(slist); } else if (g_strcmp0(cmd, "PRIVMSG") == 0) { /* send the message to other clients as well */ char *params, *target, *msg; params = event_get_params(args, 2 | PARAM_FLAG_GETREST, &target, &msg); proxy_outserver_all_except(client, "PRIVMSG %s", args); ignore_next = TRUE; if (*msg != '\001' || msg[strlen(msg)-1] != '\001') { signal_emit(ischannel(*target) ? "message own_public" : "message own_private", 4, client->server, msg, target, target); } else if (strncmp(msg+1, "ACTION ", 7) == 0) { /* action */ msg[strlen(msg)-1] = '\0'; signal_emit("message irc own_action", 3, client->server, msg+8, target); } else { /* CTCP */ char *p; msg[strlen(msg)-1] = '\0'; p = strchr(msg, ' '); if (p != NULL) *p++ = '\0'; else p = ""; signal_emit("message irc own_ctcp", 4, client->server, msg+1, p, target); } ignore_next = FALSE; g_free(params); } else if (g_strcmp0(cmd, "PING") == 0) { proxy_redirect_event(client, "ping", 1, NULL, TRUE); } else if (g_strcmp0(cmd, "AWAY") == 0) { /* set the away reason */ if (args != NULL) { g_free(client->server->away_reason); client->server->away_reason = g_strdup(args); } } irc_send_cmd(client->server, data); }
void proxy_dump_data(CLIENT_REC *client) { GString *isupport_out, *paramstr; char **paramlist, **tmp; int count; proxy_client_reset_nick(client); /* welcome info */ proxy_outdata(client, ":%s 001 %s :Welcome to the Internet Relay Network\n", client->proxy_address, client->nick); proxy_outdata(client, ":%s 002 %s :Your host is irssi-proxy, running version %s\n", client->proxy_address, client->nick, IRSSI_VERSION); proxy_outdata(client, ":%s 003 %s :This server was created ...\n", client->proxy_address, client->nick); if (client->server == NULL || !client->server->emode_known) proxy_outdata(client, ":%s 004 %s %s %s oirw abiklmnopqstv\n", client->proxy_address, client->nick, client->proxy_address, IRSSI_VERSION); else proxy_outdata(client, ":%s 004 %s %s %s oirw abeIiklmnopqstv\n", client->proxy_address, client->nick, client->proxy_address, IRSSI_VERSION); if (client->server != NULL && client->server->isupport_sent) { isupport_out = g_string_new(NULL); g_hash_table_foreach(client->server->isupport, proxy_dump_data_005, isupport_out); if (isupport_out->len > 0) g_string_truncate(isupport_out, isupport_out->len-1); proxy_outdata(client, ":%s 005 %s ", client->proxy_address, client->nick); paramstr = g_string_new(NULL); paramlist = g_strsplit(isupport_out->str, " ", -1); count = 0; tmp = paramlist; for (;; tmp++) { if (*tmp != NULL) { g_string_sprintfa(paramstr, "%s ", *tmp); if (++count < 15) continue; } count = 0; if (paramstr->len > 0) g_string_truncate(paramstr, paramstr->len-1); g_string_sprintfa(paramstr, " :are supported by this server\n"); proxy_outdata(client, "%s", paramstr->str); g_string_truncate(paramstr, 0); g_string_sprintf(paramstr, ":%s 005 %s ", client->proxy_address, client->nick); if (*tmp == NULL || tmp[1] == NULL) break; } g_string_free(isupport_out, TRUE); g_string_free(paramstr, TRUE); g_strfreev(paramlist); } proxy_outdata(client, ":%s 251 %s :There are 0 users and 0 invisible on 1 servers\n", client->proxy_address, client->nick); proxy_outdata(client, ":%s 255 %s :I have 0 clients, 0 services and 0 servers\n", client->proxy_address, client->nick); proxy_outdata(client, ":%s 422 %s :MOTD File is missing\n", client->proxy_address, client->nick); /* user mode / away status */ if (client->server != NULL) { if (client->server->usermode != NULL) { proxy_outserver(client, "MODE %s :+%s", client->server->nick, client->server->usermode); } if (client->server->usermode_away) { proxy_outdata(client, ":%s 306 %s :You have been marked as being away\n", client->proxy_address, client->nick); } /* Send channel joins */ g_slist_foreach(client->server->channels, (GFunc) dump_join, client); } }