static void cmd_info(irc_t *irc, char **cmd) { struct im_connection *ic; account_t *a; if (!cmd[2]) { irc_user_t *iu = irc_user_by_name(irc, cmd[1]); if (!iu || !iu->bu) { irc_rootmsg(irc, "Nick `%s' does not exist", cmd[1]); return; } ic = iu->bu->ic; cmd[2] = iu->bu->handle; } else if (!(a = account_get(irc->b, cmd[1]))) { irc_rootmsg(irc, "Invalid account"); return; } else if (!((ic = a->ic) && (a->ic->flags & OPT_LOGGED_IN))) { irc_rootmsg(irc, "That account is not on-line"); return; } if (!ic->acc->prpl->get_info) { irc_rootmsg(irc, "Command `%s' not supported by this protocol", cmd[0]); } else { ic->acc->prpl->get_info(ic, cmd[2]); } }
static void irc_cmd_whois( irc_t *irc, char **cmd ) { char *nick = cmd[1]; irc_user_t *iu = irc_user_by_name( irc, nick ); if( iu ) irc_send_whois( iu ); else irc_send_num( irc, 401, "%s :Nick does not exist", nick ); }
static void irc_cmd_ison( irc_t *irc, char **cmd ) { char buff[IRC_MAX_LINE]; int lenleft, i; buff[0] = '\0'; /* [SH] Leave room for : and \0 */ lenleft = IRC_MAX_LINE - 2; for( i = 1; cmd[i]; i ++ ) { char *this, *next; this = cmd[i]; while( *this ) { irc_user_t *iu; if( ( next = strchr( this, ' ' ) ) ) *next = 0; if( ( iu = irc_user_by_name( irc, this ) ) && iu->bu && iu->bu->flags & BEE_USER_ONLINE ) { lenleft -= strlen( iu->nick ) + 1; if( lenleft < 0 ) break; strcat( buff, iu->nick ); strcat( buff, " " ); } if( next ) { *next = ' '; this = next + 1; } else { break; } } /* *sigh* */ if( lenleft < 0 ) break; } if( strlen( buff ) > 0 ) buff[strlen(buff)-1] = '\0'; irc_send_num( irc, 303, ":%s", buff ); }
static void irc_cmd_privmsg( irc_t *irc, char **cmd ) { irc_channel_t *ic; irc_user_t *iu; if( !cmd[2] ) { irc_send_num( irc, 412, ":No text to send" ); return; } /* Don't treat CTCP actions as real CTCPs, just convert them right now. */ if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 ) { cmd[2] += 4; memcpy( cmd[2], "/me", 3 ); if( cmd[2][strlen(cmd[2])-1] == '\001' ) cmd[2][strlen(cmd[2])-1] = '\0'; } if( irc_channel_name_ok( cmd[1] ) && ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) { if( cmd[2][0] == '\001' ) { /* CTCPs to channels? Nah. Maybe later. */ } else if( ic->f->privmsg ) ic->f->privmsg( ic, cmd[2] ); } else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) ) { if( cmd[2][0] == '\001' ) { char **ctcp; if( iu->f->ctcp == NULL ) return; if( cmd[2][strlen(cmd[2])-1] == '\001' ) cmd[2][strlen(cmd[2])-1] = '\0'; ctcp = split_command_parts( cmd[2] + 1 ); iu->f->ctcp( iu, ctcp ); } else if( iu->f->privmsg ) { iu->last_channel = NULL; iu->f->privmsg( iu, cmd[2] ); } } else { irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] ); } }
static void cmd_rename(irc_t *irc, char **cmd) { irc_user_t *iu, *old; gboolean del = g_strcasecmp(cmd[1], "-del") == 0; iu = irc_user_by_name(irc, cmd[del ? 2 : 1]); if (iu == NULL) { irc_rootmsg(irc, "Nick `%s' does not exist", cmd[1]); } else if (del) { if (iu->bu) { bee_irc_user_nick_reset(iu); } irc_rootmsg(irc, "Nickname reset to `%s'", iu->nick); } else if (iu == irc->user) { irc_rootmsg(irc, "Use /nick to change your own nickname"); } else if (!nick_ok(irc, cmd[2])) { irc_rootmsg(irc, "Nick `%s' is invalid", cmd[2]); } else if ((old = irc_user_by_name(irc, cmd[2])) && old != iu) { irc_rootmsg(irc, "Nick `%s' already exists", cmd[2]); } else { if (!irc_user_set_nick(iu, cmd[2])) { irc_rootmsg(irc, "Error while changing nick"); return; } if (iu == irc->root) { /* If we're called internally (user did "set root_nick"), let's not go O(INF). :-) */ if (strcmp(cmd[0], "set_rename") != 0) { set_setstr(&irc->b->set, "root_nick", cmd[2]); } } else if (iu->bu) { nick_set(iu->bu, cmd[2]); } irc_rootmsg(irc, "Nick successfully changed"); } }
static void cmd_allow(irc_t *irc, char **cmd) { struct im_connection *ic; account_t *a; if (!cmd[2] && (a = account_get(irc->b, cmd[1])) && a->ic) { char *format; GSList *l; if (strchr(irc->umode, 'b') != NULL) { format = "%s\t%s"; } else { format = "%-32.32s %-16.16s"; } irc_rootmsg(irc, format, "Handle", "Nickname"); for (l = a->ic->permit; l; l = l->next) { bee_user_t *bu = bee_user_by_handle(irc->b, a->ic, l->data); irc_user_t *iu = bu ? bu->ui_data : NULL; irc_rootmsg(irc, format, l->data, iu ? iu->nick : "(none)"); } irc_rootmsg(irc, "End of list."); return; } else if (!cmd[2]) { irc_user_t *iu = irc_user_by_name(irc, cmd[1]); if (!iu || !iu->bu) { irc_rootmsg(irc, "Nick `%s' does not exist", cmd[1]); return; } ic = iu->bu->ic; cmd[2] = iu->bu->handle; } else if (!(a = account_get(irc->b, cmd[1]))) { irc_rootmsg(irc, "Invalid account"); return; } else if (!((ic = a->ic) && (a->ic->flags & OPT_LOGGED_IN))) { irc_rootmsg(irc, "That account is not on-line"); return; } if (!ic->acc->prpl->rem_deny || !ic->acc->prpl->add_permit) { irc_rootmsg(irc, "Command `%s' not supported by this protocol", cmd[0]); } else { imc_rem_block(ic, cmd[2]); imc_add_allow(ic, cmd[2]); irc_rootmsg(irc, "Buddy `%s' moved from block- to allow-list", cmd[2]); } }
static void irc_cmd_watch( irc_t *irc, char **cmd ) { int i; /* Obviously we could also mark a user structure as being watched, but what if the WATCH command is sent right after connecting? The user won't exist yet then... */ for( i = 1; cmd[i]; i ++ ) { char *nick; irc_user_t *iu; if( !cmd[i][0] || !cmd[i][1] ) break; nick = g_strdup( cmd[i] + 1 ); nick_lc( nick ); iu = irc_user_by_name( irc, nick ); if( cmd[i][0] == '+' ) { if( !g_hash_table_lookup( irc->watches, nick ) ) g_hash_table_insert( irc->watches, nick, nick ); if( iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE ) irc_send_num( irc, 604, "%s %s %s %d :%s", iu->nick, iu->user, iu->host, (int) time( NULL ), "is online" ); else irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" ); } else if( cmd[i][0] == '-' ) { gpointer okey, ovalue; if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) ) { g_hash_table_remove( irc->watches, okey ); g_free( okey ); irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" ); } } } }
static void irc_cmd_notice( irc_t *irc, char **cmd ) { irc_user_t *iu; if( !cmd[2] ) { irc_send_num( irc, 412, ":No text to send" ); return; } /* At least for now just echo. IIRC some IRC clients use self-notices for lag checks, so try to support that. */ if( nick_cmp( cmd[1], irc->user->nick ) == 0 ) irc_send_msg( irc->user, "NOTICE", irc->user->nick, cmd[2], NULL ); else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) ) iu->f->privmsg( iu, cmd[2] ); }
static void irc_cmd_userhost( irc_t *irc, char **cmd ) { int i; /* [TV] Usable USERHOST-implementation according to RFC1459. Without this, mIRC shows an error while connecting, and the used way of rejecting breaks standards. */ for( i = 1; cmd[i]; i ++ ) { irc_user_t *iu = irc_user_by_name( irc, cmd[i] ); if( iu ) irc_send_num( irc, 302, ":%s=%c%s@%s", iu->nick, irc_user_get_away( iu ) ? '-' : '+', iu->user, iu->host ); } }
static void irc_cmd_who( irc_t *irc, char **cmd ) { char *channel = cmd[1]; irc_channel_t *ic; irc_user_t *iu; if( !channel || *channel == '0' || *channel == '*' || !*channel ) irc_send_who( irc, irc->users, "**" ); else if( ( ic = irc_channel_by_name( irc, channel ) ) ) irc_send_who( irc, ic->users, channel ); else if( ( iu = irc_user_by_name( irc, channel ) ) ) { /* Tiny hack! */ GSList *l = g_slist_append( NULL, iu ); irc_send_who( irc, l, channel ); g_slist_free( l ); } else irc_send_num( irc, 403, "%s :No such channel", channel ); }
static void irc_cmd_invite( irc_t *irc, char **cmd ) { irc_channel_t *ic; irc_user_t *iu; if( ( iu = irc_user_by_name( irc, cmd[1] ) ) == NULL ) { irc_send_num( irc, 401, "%s :No such nick", cmd[1] ); return; } else if( ( ic = irc_channel_by_name( irc, cmd[2] ) ) == NULL ) { irc_send_num( irc, 403, "%s :No such channel", cmd[2] ); return; } if( !ic->f->invite ) irc_send_num( irc, 482, "%s :Can't invite people here", cmd[2] ); else if( ic->f->invite( ic, iu ) ) irc_send_num( irc, 341, "%s %s", iu->nick, ic->name ); }
static void irc_cmd_nick( irc_t *irc, char **cmd ) { irc_user_t *iu; if( ( iu = irc_user_by_name( irc, cmd[1] ) ) && iu != irc->user ) { irc_send_num( irc, 433, "%s :This nick is already in use", cmd[1] ); } else if( !nick_ok( cmd[1] ) ) { /* [SH] Invalid characters. */ irc_send_num( irc, 432, "%s :This nick contains invalid characters", cmd[1] ); } else if( irc->status & USTATUS_LOGGED_IN ) { /* WATCH OUT: iu from the first if reused here to check if the new nickname is the same (other than case, possibly). If it is, no need to reset identify-status. */ if( ( irc->status & USTATUS_IDENTIFIED ) && iu != irc->user ) { irc_setpass( irc, NULL ); irc->status &= ~USTATUS_IDENTIFIED; irc_umode_set( irc, "-R", 1 ); irc_rootmsg( irc, "Changing nicks resets your identify status. " "Re-identify or register a new account if you want " "your configuration to be saved. See \x02help " "nick_changes\x02." ); } if( strcmp( cmd[1], irc->user->nick ) != 0 ) irc_user_set_nick( irc->user, cmd[1] ); } else { g_free( irc->user->nick ); irc->user->nick = g_strdup( cmd[1] ); irc_check_login( irc ); } }
static void cmd_remove(irc_t *irc, char **cmd) { irc_user_t *iu; bee_user_t *bu; char *s; if (!(iu = irc_user_by_name(irc, cmd[1])) || !(bu = iu->bu)) { irc_rootmsg(irc, "Buddy `%s' not found", cmd[1]); return; } s = g_strdup(bu->handle); bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL); nick_del(bu); if (g_slist_find(irc->users, iu)) { bee_user_free(irc->b, bu); } irc_rootmsg(irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1]); g_free(s); return; }
static void irc_cmd_nick( irc_t *irc, char **cmd ) { irc_user_t *iu; if( ( iu = irc_user_by_name( irc, cmd[1] ) ) && iu != irc->user ) { irc_send_num( irc, 433, "%s :This nick is already in use", cmd[1] ); } else if( !nick_ok( cmd[1] ) ) { /* [SH] Invalid characters. */ irc_send_num( irc, 432, "%s :This nick contains invalid characters", cmd[1] ); } else if( irc->status & USTATUS_LOGGED_IN ) { if( irc->status & USTATUS_IDENTIFIED ) { irc_setpass( irc, NULL ); irc->status &= ~USTATUS_IDENTIFIED; irc_umode_set( irc, "-R", 1 ); irc_usermsg( irc, "Changing nicks resets your identify status. " "Re-identify or register a new account if you want " "your configuration to be saved. See \x02help " "nick_changes\x02." ); } irc_user_set_nick( irc->user, cmd[1] ); } else { g_free( irc->user->nick ); irc->user->nick = g_strdup( cmd[1] ); irc_check_login( irc ); } }
static void cmd_add(irc_t *irc, char **cmd) { account_t *a; int add_on_server = 1; char *handle = NULL, *s; if (g_strcasecmp(cmd[1], "-tmp") == 0) { MIN_ARGS(3); add_on_server = 0; cmd++; } if (!(a = account_get(irc->b, cmd[1]))) { irc_rootmsg(irc, "Invalid account"); return; } else if (!(a->ic && (a->ic->flags & OPT_LOGGED_IN))) { irc_rootmsg(irc, "That account is not on-line"); return; } if (cmd[3]) { if (!nick_ok(irc, cmd[3])) { irc_rootmsg(irc, "The requested nick `%s' is invalid", cmd[3]); return; } else if (irc_user_by_name(irc, cmd[3])) { irc_rootmsg(irc, "The requested nick `%s' already exists", cmd[3]); return; } else { nick_set_raw(a, cmd[2], cmd[3]); } } if ((a->flags & ACC_FLAG_HANDLE_DOMAINS) && cmd[2][0] != '_' && (!(s = strchr(cmd[2], '@')) || s[1] == '\0')) { /* If there's no @ or it's the last char, append the user's domain name now. Exclude handles starting with a _ so adding _xmlconsole will keep working. */ if (s) { *s = '\0'; } if ((s = strchr(a->user, '@'))) { cmd[2] = handle = g_strconcat(cmd[2], s, NULL); } } if (add_on_server) { irc_channel_t *ic; char *s, *group = NULL;; if ((ic = irc->root->last_channel) && (s = set_getstr(&ic->set, "fill_by")) && strcmp(s, "group") == 0 && (group = set_getstr(&ic->set, "group"))) { irc_rootmsg(irc, "Adding `%s' to contact list (group %s)", cmd[2], group); } else { irc_rootmsg(irc, "Adding `%s' to contact list", cmd[2]); } a->prpl->add_buddy(a->ic, cmd[2], group); } else { bee_user_t *bu; irc_user_t *iu; /* Only for add -tmp. For regular adds, this callback will be called once the IM server confirms. */ if ((bu = bee_user_new(irc->b, a->ic, cmd[2], BEE_USER_LOCAL)) && (iu = bu->ui_data)) { irc_rootmsg(irc, "Temporarily assigned nickname `%s' " "to contact `%s'", iu->nick, cmd[2]); } } g_free(handle); }
static void cmd_chat(irc_t *irc, char **cmd) { account_t *acc; if (g_strcasecmp(cmd[1], "add") == 0) { char *channel, *s; struct irc_channel *ic; MIN_ARGS(3); if (!(acc = account_get(irc->b, cmd[2]))) { irc_rootmsg(irc, "Invalid account"); return; } else if (!acc->prpl->chat_join) { irc_rootmsg(irc, "Named chatrooms not supported on that account."); return; } if (cmd[4] == NULL) { channel = g_strdup(cmd[3]); if ((s = strchr(channel, '@'))) { *s = 0; } } else { channel = g_strdup(cmd[4]); } if (strchr(CTYPES, channel[0]) == NULL) { s = g_strdup_printf("#%s", channel); g_free(channel); channel = s; irc_channel_name_strip(channel); } if ((ic = irc_channel_new(irc, channel)) && set_setstr(&ic->set, "type", "chat") && set_setstr(&ic->set, "chat_type", "room") && set_setstr(&ic->set, "account", cmd[2]) && set_setstr(&ic->set, "room", cmd[3])) { irc_rootmsg(irc, "Chatroom successfully added."); } else { if (ic) { irc_channel_free(ic); } irc_rootmsg(irc, "Could not add chatroom."); } g_free(channel); } else if (g_strcasecmp(cmd[1], "with") == 0) { irc_user_t *iu; MIN_ARGS(2); if ((iu = irc_user_by_name(irc, cmd[2])) && iu->bu && iu->bu->ic->acc->prpl->chat_with) { if (!iu->bu->ic->acc->prpl->chat_with(iu->bu->ic, iu->bu->handle)) { irc_rootmsg(irc, "(Possible) failure while trying to open " "a groupchat with %s.", iu->nick); } } else { irc_rootmsg(irc, "Can't open a groupchat with %s.", cmd[2]); } } else if (g_strcasecmp(cmd[1], "list") == 0 || g_strcasecmp(cmd[1], "set") == 0 || g_strcasecmp(cmd[1], "del") == 0) { irc_rootmsg(irc, "Warning: The \002chat\002 command was mostly replaced with the \002channel\002 command."); cmd_channel(irc, cmd); } else { irc_rootmsg(irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "chat", cmd[1]); } }