Changeset 5ebff60 for irc_commands.c
- Timestamp:
- 2015-02-20T22:50:54Z (9 years ago)
- Branches:
- master
- Children:
- 0b9daac, 3d45471, 7733b8c
- Parents:
- af359b4
- git-author:
- Indent <please@…> (19-02-15 05:47:20)
- git-committer:
- dequis <dx@…> (20-02-15 22:50:54)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
irc_commands.c
raf359b4 r5ebff60 1 1 /********************************************************************\ 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * … … 29 29 #include "ipc.h" 30 30 31 static void irc_cmd_pass( irc_t *irc, char **cmd ) 32 { 33 if( irc->status & USTATUS_LOGGED_IN ) 34 { 31 static void irc_cmd_pass(irc_t *irc, char **cmd) 32 { 33 if (irc->status & USTATUS_LOGGED_IN) { 35 34 char *send_cmd[] = { "identify", cmd[1], NULL }; 36 35 37 36 /* We're already logged in, this client seems to send the PASS 38 37 command last. (Possibly it won't send it at all if it turns 39 38 out we don't require it, which will break this feature.) 40 39 Try to identify using the given password. */ 41 root_command( irc, send_cmd);40 root_command(irc, send_cmd); 42 41 return; 43 42 } 44 43 /* Handling in pre-logged-in state, first see if this server is 45 44 password-protected: */ 46 else if( global.conf->auth_pass && 47 ( strncmp( global.conf->auth_pass, "md5:", 4 ) == 0 ? 48 md5_verify_password( cmd[1], global.conf->auth_pass + 4 ) == 0 : 49 strcmp( cmd[1], global.conf->auth_pass ) == 0 ) ) 50 { 45 else if (global.conf->auth_pass && 46 (strncmp(global.conf->auth_pass, "md5:", 4) == 0 ? 47 md5_verify_password(cmd[1], global.conf->auth_pass + 4) == 0 : 48 strcmp(cmd[1], global.conf->auth_pass) == 0)) { 51 49 irc->status |= USTATUS_AUTHORIZED; 52 irc_check_login( irc ); 53 } 54 else if( global.conf->auth_pass ) 55 { 56 irc_send_num( irc, 464, ":Incorrect password" ); 57 } 58 else 59 { 50 irc_check_login(irc); 51 } else if (global.conf->auth_pass) { 52 irc_send_num(irc, 464, ":Incorrect password"); 53 } else { 60 54 /* Remember the password and try to identify after USER/NICK. */ 61 irc_setpass( irc, cmd[1]);62 irc_check_login( irc);63 } 64 } 65 66 static void irc_cmd_user( irc_t *irc, char **cmd)67 { 68 irc->user->user = g_strdup( cmd[1]);69 irc->user->fullname = g_strdup( cmd[4]);70 71 irc_check_login( irc);72 } 73 74 static void irc_cmd_nick( irc_t *irc, char **cmd)55 irc_setpass(irc, cmd[1]); 56 irc_check_login(irc); 57 } 58 } 59 60 static void irc_cmd_user(irc_t *irc, char **cmd) 61 { 62 irc->user->user = g_strdup(cmd[1]); 63 irc->user->fullname = g_strdup(cmd[4]); 64 65 irc_check_login(irc); 66 } 67 68 static void irc_cmd_nick(irc_t *irc, char **cmd) 75 69 { 76 70 irc_user_t *iu; 77 78 if( ( iu = irc_user_by_name( irc, cmd[1] ) ) && iu != irc->user ) 79 { 80 irc_send_num( irc, 433, "%s :This nick is already in use", cmd[1] ); 81 } 82 else if( !nick_ok( NULL, cmd[1] ) ) 83 { 71 72 if ((iu = irc_user_by_name(irc, cmd[1])) && iu != irc->user) { 73 irc_send_num(irc, 433, "%s :This nick is already in use", cmd[1]); 74 } else if (!nick_ok(NULL, cmd[1])) { 84 75 /* [SH] Invalid characters. */ 85 irc_send_num( irc, 432, "%s :This nick contains invalid characters", cmd[1] ); 86 } 87 else if( irc->status & USTATUS_LOGGED_IN ) 88 { 76 irc_send_num(irc, 432, "%s :This nick contains invalid characters", cmd[1]); 77 } else if (irc->status & USTATUS_LOGGED_IN) { 89 78 /* WATCH OUT: iu from the first if reused here to check if the 90 79 new nickname is the same (other than case, possibly). If it 91 80 is, no need to reset identify-status. */ 92 if( ( irc->status & USTATUS_IDENTIFIED ) && iu != irc->user ) 93 { 94 irc_setpass( irc, NULL ); 81 if ((irc->status & USTATUS_IDENTIFIED) && iu != irc->user) { 82 irc_setpass(irc, NULL); 95 83 irc->status &= ~USTATUS_IDENTIFIED; 96 irc_umode_set( irc, "-R", 1);97 irc_rootmsg( 98 99 100 "nick_changes\x02.");101 } 102 103 if ( strcmp( cmd[1], irc->user->nick ) != 0 )104 irc_user_set_nick( irc->user, cmd[1]);105 }106 else107 {108 g_free( irc->user->nick);109 irc->user->nick = g_strdup( cmd[1] ); 110 111 irc_check_login( irc );112 113 } 114 115 static void irc_cmd_quit( irc_t *irc, char **cmd ) 116 {117 if( cmd[1] && *cmd[1] )118 irc_abort( irc, 0, "Quit: %s", cmd[1] );119 else120 irc_abort( irc, 0, "Leaving..." );121 } 122 123 static void irc_cmd_ping( irc_t *irc, char **cmd)124 { 125 irc_write( 126 irc->root->host, cmd[1]?cmd[1]:irc->root->host);127 } 128 129 static void irc_cmd_pong( irc_t *irc, char **cmd)84 irc_umode_set(irc, "-R", 1); 85 irc_rootmsg(irc, "Changing nicks resets your identify status. " 86 "Re-identify or register a new account if you want " 87 "your configuration to be saved. See \x02help " 88 "nick_changes\x02."); 89 } 90 91 if (strcmp(cmd[1], irc->user->nick) != 0) { 92 irc_user_set_nick(irc->user, cmd[1]); 93 } 94 } else { 95 g_free(irc->user->nick); 96 irc->user->nick = g_strdup(cmd[1]); 97 98 irc_check_login(irc); 99 } 100 } 101 102 static void irc_cmd_quit(irc_t *irc, char **cmd) 103 { 104 if (cmd[1] && *cmd[1]) { 105 irc_abort(irc, 0, "Quit: %s", cmd[1]); 106 } else { 107 irc_abort(irc, 0, "Leaving..."); 108 } 109 } 110 111 static void irc_cmd_ping(irc_t *irc, char **cmd) 112 { 113 irc_write(irc, ":%s PONG %s :%s", irc->root->host, 114 irc->root->host, cmd[1] ? cmd[1] : irc->root->host); 115 } 116 117 static void irc_cmd_pong(irc_t *irc, char **cmd) 130 118 { 131 119 /* We could check the value we get back from the user, but in … … 135 123 } 136 124 137 static void irc_cmd_join( irc_t *irc, char **cmd)125 static void irc_cmd_join(irc_t *irc, char **cmd) 138 126 { 139 127 char *comma, *s = cmd[1]; 140 141 while( s ) 142 { 128 129 while (s) { 143 130 irc_channel_t *ic; 144 145 if ( ( comma = strchr( s, ',' ) ) )131 132 if ((comma = strchr(s, ','))) { 146 133 *comma = '\0'; 147 148 if( ( ic = irc_channel_by_name( irc, s ) ) == NULL && 149 ( ic = irc_channel_new( irc, s ) ) ) 150 { 151 if( strcmp( set_getstr( &ic->set, "type" ), "control" ) != 0 ) 152 { 134 } 135 136 if ((ic = irc_channel_by_name(irc, s)) == NULL && 137 (ic = irc_channel_new(irc, s))) { 138 if (strcmp(set_getstr(&ic->set, "type"), "control") != 0) { 153 139 /* Autoconfiguration is for control channels only ATM. */ 154 } 155 else if( bee_group_by_name( ic->irc->b, ic->name + 1, FALSE ) ) 156 { 157 set_setstr( &ic->set, "group", ic->name + 1 ); 158 set_setstr( &ic->set, "fill_by", "group" ); 159 } 160 else if( set_setstr( &ic->set, "protocol", ic->name + 1 ) ) 161 { 162 set_setstr( &ic->set, "fill_by", "protocol" ); 163 } 164 else if( set_setstr( &ic->set, "account", ic->name + 1 ) ) 165 { 166 set_setstr( &ic->set, "fill_by", "account" ); 167 } 168 else 169 { 140 } else if (bee_group_by_name(ic->irc->b, ic->name + 1, FALSE)) { 141 set_setstr(&ic->set, "group", ic->name + 1); 142 set_setstr(&ic->set, "fill_by", "group"); 143 } else if (set_setstr(&ic->set, "protocol", ic->name + 1)) { 144 set_setstr(&ic->set, "fill_by", "protocol"); 145 } else if (set_setstr(&ic->set, "account", ic->name + 1)) { 146 set_setstr(&ic->set, "fill_by", "account"); 147 } else { 170 148 /* The set commands above will run this already, 171 149 but if we didn't hit any, we have to fill the 172 150 channel with the default population. */ 173 bee_irc_channel_update( ic->irc, ic, NULL ); 174 } 175 } 176 else if( ic == NULL ) 177 { 178 irc_send_num( irc, 479, "%s :Invalid channel name", s ); 151 bee_irc_channel_update(ic->irc, ic, NULL); 152 } 153 } else if (ic == NULL) { 154 irc_send_num(irc, 479, "%s :Invalid channel name", s); 179 155 goto next; 180 156 } 181 182 if ( ic->flags & IRC_CHANNEL_JOINED )157 158 if (ic->flags & IRC_CHANNEL_JOINED) { 183 159 /* Dude, you're already there... 184 160 RFC doesn't have any reply for that though? */ 185 161 goto next; 186 187 if( ic->f->join && !ic->f->join( ic ) ) 162 } 163 164 if (ic->f->join && !ic->f->join(ic)) { 188 165 /* The story is: FALSE either means the handler 189 166 showed an error message, or is doing some work … … 193 170 user join the channel right away. */ 194 171 goto next; 195 196 irc_channel_add_user( ic, irc->user ); 197 172 } 173 174 irc_channel_add_user(ic, irc->user); 175 198 176 next: 199 if( comma ) 200 { 177 if (comma) { 201 178 s = comma + 1; 202 179 *comma = ','; 203 } 204 else 180 } else { 205 181 break; 206 } 207 } 208 209 static void irc_cmd_names( irc_t *irc, char **cmd ) 182 } 183 } 184 } 185 186 static void irc_cmd_names(irc_t *irc, char **cmd) 210 187 { 211 188 irc_channel_t *ic; 212 213 if( cmd[1] && ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) 214 irc_send_names( ic ); 189 190 if (cmd[1] && (ic = irc_channel_by_name(irc, cmd[1]))) { 191 irc_send_names(ic); 192 } 215 193 /* With no args, we should show /names of all chans. Make the code 216 194 below work well if necessary. 217 195 else 218 196 { 219 220 221 222 197 GSList *l; 198 199 for( l = irc->channels; l; l = l->next ) 200 irc_send_names( l->data ); 223 201 } 224 202 */ 225 203 } 226 204 227 static void irc_cmd_part( irc_t *irc, char **cmd)205 static void irc_cmd_part(irc_t *irc, char **cmd) 228 206 { 229 207 irc_channel_t *ic; 230 231 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 232 { 233 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 234 } 235 else if( irc_channel_del_user( ic, irc->user, IRC_CDU_PART, cmd[2] ) ) 236 { 237 if( ic->f->part ) 238 ic->f->part( ic, NULL ); 239 } 240 else 241 { 242 irc_send_num( irc, 442, "%s :You're not on that channel", cmd[1] ); 243 } 244 } 245 246 static void irc_cmd_whois( irc_t *irc, char **cmd ) 208 209 if ((ic = irc_channel_by_name(irc, cmd[1])) == NULL) { 210 irc_send_num(irc, 403, "%s :No such channel", cmd[1]); 211 } else if (irc_channel_del_user(ic, irc->user, IRC_CDU_PART, cmd[2])) { 212 if (ic->f->part) { 213 ic->f->part(ic, NULL); 214 } 215 } else { 216 irc_send_num(irc, 442, "%s :You're not on that channel", cmd[1]); 217 } 218 } 219 220 static void irc_cmd_whois(irc_t *irc, char **cmd) 247 221 { 248 222 char *nick = cmd[1]; 249 irc_user_t *iu = irc_user_by_name( irc, nick ); 250 251 if( iu ) 252 irc_send_whois( iu ); 253 else 254 irc_send_num( irc, 401, "%s :Nick does not exist", nick ); 255 } 256 257 static void irc_cmd_whowas( irc_t *irc, char **cmd ) 223 irc_user_t *iu = irc_user_by_name(irc, nick); 224 225 if (iu) { 226 irc_send_whois(iu); 227 } else { 228 irc_send_num(irc, 401, "%s :Nick does not exist", nick); 229 } 230 } 231 232 static void irc_cmd_whowas(irc_t *irc, char **cmd) 258 233 { 259 234 /* For some reason irssi tries a whowas when whois fails. We can … … 261 236 message from irssi which is a bit annoying. So just respond 262 237 with not-found and irssi users will get better error messages */ 263 264 irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] ); 265 irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] ); 266 } 267 268 static void irc_cmd_motd( irc_t *irc, char **cmd ) 269 { 270 irc_send_motd( irc ); 271 } 272 273 static void irc_cmd_mode( irc_t *irc, char **cmd ) 274 { 275 if( irc_channel_name_ok( cmd[1] ) ) 276 { 238 239 irc_send_num(irc, 406, "%s :Nick does not exist", cmd[1]); 240 irc_send_num(irc, 369, "%s :End of WHOWAS", cmd[1]); 241 } 242 243 static void irc_cmd_motd(irc_t *irc, char **cmd) 244 { 245 irc_send_motd(irc); 246 } 247 248 static void irc_cmd_mode(irc_t *irc, char **cmd) 249 { 250 if (irc_channel_name_ok(cmd[1])) { 277 251 irc_channel_t *ic; 278 279 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 280 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 281 else if( cmd[2] ) 282 { 283 if( *cmd[2] == '+' || *cmd[2] == '-' ) 284 irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] ); 285 else if( *cmd[2] == 'b' ) 286 irc_send_num( irc, 368, "%s :No bans possible", cmd[1] ); 287 } 288 else 289 irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode ); 290 } 291 else 292 { 293 if( nick_cmp( NULL, cmd[1], irc->user->nick ) == 0 ) 294 { 295 if( cmd[2] ) 296 irc_umode_set( irc, cmd[2], 0 ); 297 else 298 irc_send_num( irc, 221, "+%s", irc->umode ); 299 } 300 else 301 irc_send_num( irc, 502, ":Don't touch their modes" ); 302 } 303 } 304 305 static void irc_cmd_who( irc_t *irc, char **cmd ) 252 253 if ((ic = irc_channel_by_name(irc, cmd[1])) == NULL) { 254 irc_send_num(irc, 403, "%s :No such channel", cmd[1]); 255 } else if (cmd[2]) { 256 if (*cmd[2] == '+' || *cmd[2] == '-') { 257 irc_send_num(irc, 477, "%s :Can't change channel modes", cmd[1]); 258 } else if (*cmd[2] == 'b') { 259 irc_send_num(irc, 368, "%s :No bans possible", cmd[1]); 260 } 261 } else { 262 irc_send_num(irc, 324, "%s +%s", cmd[1], ic->mode); 263 } 264 } else { 265 if (nick_cmp(NULL, cmd[1], irc->user->nick) == 0) { 266 if (cmd[2]) { 267 irc_umode_set(irc, cmd[2], 0); 268 } else { 269 irc_send_num(irc, 221, "+%s", irc->umode); 270 } 271 } else { 272 irc_send_num(irc, 502, ":Don't touch their modes"); 273 } 274 } 275 } 276 277 static void irc_cmd_who(irc_t *irc, char **cmd) 306 278 { 307 279 char *channel = cmd[1]; 308 280 irc_channel_t *ic; 309 281 irc_user_t *iu; 310 311 if( !channel || *channel == '0' || *channel == '*' || !*channel ) 312 irc_send_who( irc, irc->users, "**" ); 313 else if( ( ic = irc_channel_by_name( irc, channel ) ) ) 314 irc_send_who( irc, ic->users, channel ); 315 else if( ( iu = irc_user_by_name( irc, channel ) ) ) 316 { 282 283 if (!channel || *channel == '0' || *channel == '*' || !*channel) { 284 irc_send_who(irc, irc->users, "**"); 285 } else if ((ic = irc_channel_by_name(irc, channel))) { 286 irc_send_who(irc, ic->users, channel); 287 } else if ((iu = irc_user_by_name(irc, channel))) { 317 288 /* Tiny hack! */ 318 GSList *l = g_slist_append( NULL, iu);319 irc_send_who( irc, l, channel);320 g_slist_free( l);321 } 322 else323 irc_send_num( irc, 403, "%s :No such channel", channel );324 } 325 326 static void irc_cmd_privmsg( irc_t *irc, char **cmd)289 GSList *l = g_slist_append(NULL, iu); 290 irc_send_who(irc, l, channel); 291 g_slist_free(l); 292 } else { 293 irc_send_num(irc, 403, "%s :No such channel", channel); 294 } 295 } 296 297 static void irc_cmd_privmsg(irc_t *irc, char **cmd) 327 298 { 328 299 irc_channel_t *ic; 329 300 irc_user_t *iu; 330 331 if( !cmd[2] ) 332 { 333 irc_send_num( irc, 412, ":No text to send" ); 334 return; 335 } 336 301 302 if (!cmd[2]) { 303 irc_send_num(irc, 412, ":No text to send"); 304 return; 305 } 306 337 307 /* Don't treat CTCP actions as real CTCPs, just convert them right now. */ 338 if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 ) 339 { 308 if (g_strncasecmp(cmd[2], "\001ACTION", 7) == 0) { 340 309 cmd[2] += 4; 341 memcpy( cmd[2], "/me", 3 ); 342 if( cmd[2][strlen(cmd[2])-1] == '\001' ) 343 cmd[2][strlen(cmd[2])-1] = '\0'; 344 } 345 346 if( irc_channel_name_ok( cmd[1] ) && 347 ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) 348 { 349 if( cmd[2][0] == '\001' ) 350 { 310 memcpy(cmd[2], "/me", 3); 311 if (cmd[2][strlen(cmd[2]) - 1] == '\001') { 312 cmd[2][strlen(cmd[2]) - 1] = '\0'; 313 } 314 } 315 316 if (irc_channel_name_ok(cmd[1]) && 317 (ic = irc_channel_by_name(irc, cmd[1]))) { 318 if (cmd[2][0] == '\001') { 351 319 /* CTCPs to channels? Nah. Maybe later. */ 352 } 353 else if( ic->f->privmsg ) 354 ic->f->privmsg( ic, cmd[2] ); 355 } 356 else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) ) 357 { 358 if( cmd[2][0] == '\001' ) 359 { 320 } else if (ic->f->privmsg) { 321 ic->f->privmsg(ic, cmd[2]); 322 } 323 } else if ((iu = irc_user_by_name(irc, cmd[1]))) { 324 if (cmd[2][0] == '\001') { 360 325 char **ctcp; 361 362 if ( iu->f->ctcp == NULL )326 327 if (iu->f->ctcp == NULL) { 363 328 return; 364 if( cmd[2][strlen(cmd[2])-1] == '\001' )365 cmd[2][strlen(cmd[2])-1] = '\0';366 367 ctcp = split_command_parts( cmd[2] + 1, 0 );368 iu->f->ctcp( iu, ctcp ); 369 }370 else if( iu->f->privmsg )371 {329 } 330 if (cmd[2][strlen(cmd[2]) - 1] == '\001') { 331 cmd[2][strlen(cmd[2]) - 1] = '\0'; 332 } 333 334 ctcp = split_command_parts(cmd[2] + 1, 0); 335 iu->f->ctcp(iu, ctcp); 336 } else if (iu->f->privmsg) { 372 337 iu->last_channel = NULL; 373 iu->f->privmsg( iu, cmd[2] ); 374 } 375 } 376 else 377 { 378 irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] ); 379 } 380 } 381 382 static void irc_cmd_notice( irc_t *irc, char **cmd ) 338 iu->f->privmsg(iu, cmd[2]); 339 } 340 } else { 341 irc_send_num(irc, 401, "%s :No such nick/channel", cmd[1]); 342 } 343 } 344 345 static void irc_cmd_notice(irc_t *irc, char **cmd) 383 346 { 384 347 irc_user_t *iu; 385 386 if( !cmd[2] ) 387 { 388 irc_send_num( irc, 412, ":No text to send" ); 389 return; 390 } 391 348 349 if (!cmd[2]) { 350 irc_send_num(irc, 412, ":No text to send"); 351 return; 352 } 353 392 354 /* At least for now just echo. IIRC some IRC clients use self-notices 393 355 for lag checks, so try to support that. */ 394 if( nick_cmp( NULL, cmd[1], irc->user->nick ) == 0 ) 395 irc_send_msg( irc->user, "NOTICE", irc->user->nick, cmd[2], NULL ); 396 else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) ) 397 iu->f->privmsg( iu, cmd[2] ); 398 } 399 400 static void irc_cmd_nickserv( irc_t *irc, char **cmd ) 356 if (nick_cmp(NULL, cmd[1], irc->user->nick) == 0) { 357 irc_send_msg(irc->user, "NOTICE", irc->user->nick, cmd[2], NULL); 358 } else if ((iu = irc_user_by_name(irc, cmd[1]))) { 359 iu->f->privmsg(iu, cmd[2]); 360 } 361 } 362 363 static void irc_cmd_nickserv(irc_t *irc, char **cmd) 401 364 { 402 365 /* [SH] This aliases the NickServ command to PRIVMSG root */ 403 366 /* [TV] This aliases the NS command to PRIVMSG root as well */ 404 root_command( irc, cmd + 1);405 } 406 407 static void irc_cmd_oper_hack( irc_t *irc, char **cmd);408 409 static void irc_cmd_oper( irc_t *irc, char **cmd)367 root_command(irc, cmd + 1); 368 } 369 370 static void irc_cmd_oper_hack(irc_t *irc, char **cmd); 371 372 static void irc_cmd_oper(irc_t *irc, char **cmd) 410 373 { 411 374 /* Very non-standard evil but useful/secure hack, see below. */ 412 if( irc->status & OPER_HACK_ANY ) 413 return irc_cmd_oper_hack( irc, cmd ); 414 415 if( global.conf->oper_pass && 416 ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? 417 md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : 418 strcmp( cmd[2], global.conf->oper_pass ) == 0 ) ) 419 { 420 irc_umode_set( irc, "+o", 1 ); 421 irc_send_num( irc, 381, ":Password accepted" ); 422 } 423 else 424 { 425 irc_send_num( irc, 491, ":Incorrect password" ); 426 } 427 } 428 429 static void irc_cmd_oper_hack( irc_t *irc, char **cmd ) 430 { 431 char *password = g_strjoinv( " ", cmd + 2 ); 432 375 if (irc->status & OPER_HACK_ANY) { 376 return irc_cmd_oper_hack(irc, cmd); 377 } 378 379 if (global.conf->oper_pass && 380 (strncmp(global.conf->oper_pass, "md5:", 4) == 0 ? 381 md5_verify_password(cmd[2], global.conf->oper_pass + 4) == 0 : 382 strcmp(cmd[2], global.conf->oper_pass) == 0)) { 383 irc_umode_set(irc, "+o", 1); 384 irc_send_num(irc, 381, ":Password accepted"); 385 } else { 386 irc_send_num(irc, 491, ":Incorrect password"); 387 } 388 } 389 390 static void irc_cmd_oper_hack(irc_t *irc, char **cmd) 391 { 392 char *password = g_strjoinv(" ", cmd + 2); 393 433 394 /* /OPER can now also be used to enter IM/identify passwords without 434 395 echoing. It's a hack but the extra password security is worth it. */ 435 if( irc->status & OPER_HACK_ACCOUNT_PASSWORD ) 436 { 396 if (irc->status & OPER_HACK_ACCOUNT_PASSWORD) { 437 397 account_t *a; 438 439 for( a = irc->b->accounts; a; a = a->next ) 440 if( strcmp( a->pass, PASSWORD_PENDING ) == 0 ) 441 { 442 set_setstr( &a->set, "password", password ); 443 irc_rootmsg( irc, "Password added to IM account " 444 "%s", a->tag ); 398 399 for (a = irc->b->accounts; a; a = a->next) { 400 if (strcmp(a->pass, PASSWORD_PENDING) == 0) { 401 set_setstr(&a->set, "password", password); 402 irc_rootmsg(irc, "Password added to IM account " 403 "%s", a->tag); 445 404 /* The IRC client may expect this. 491 suggests the OPER 446 405 password was wrong, so the client won't expect a +o. 447 406 It may however repeat the password prompt. We'll see. */ 448 irc_send_num( irc, 491, ":Password added to IM account " 449 "%s", a->tag ); 450 } 451 } 452 else if( irc->status & OPER_HACK_IDENTIFY ) 453 { 407 irc_send_num(irc, 491, ":Password added to IM account " 408 "%s", a->tag); 409 } 410 } 411 } else if (irc->status & OPER_HACK_IDENTIFY) { 454 412 char *send_cmd[] = { "identify", password, NULL, NULL }; 455 413 irc->status &= ~OPER_HACK_IDENTIFY; 456 if( irc->status & OPER_HACK_IDENTIFY_NOLOAD ) 457 { 414 if (irc->status & OPER_HACK_IDENTIFY_NOLOAD) { 458 415 send_cmd[1] = "-noload"; 459 416 send_cmd[2] = password; 460 } 461 else if( irc->status & OPER_HACK_IDENTIFY_FORCE ) 462 { 417 } else if (irc->status & OPER_HACK_IDENTIFY_FORCE) { 463 418 send_cmd[1] = "-force"; 464 419 send_cmd[2] = password; 465 420 } 466 irc_send_num( irc, 491, ":Trying to identify" ); 467 root_command( irc, send_cmd ); 468 } 469 else if( irc->status & OPER_HACK_REGISTER ) 470 { 421 irc_send_num(irc, 491, ":Trying to identify"); 422 root_command(irc, send_cmd); 423 } else if (irc->status & OPER_HACK_REGISTER) { 471 424 char *send_cmd[] = { "register", password, NULL }; 472 irc_send_num( irc, 491, ":Trying to identify");473 root_command( irc, send_cmd);474 } 475 425 irc_send_num(irc, 491, ":Trying to identify"); 426 root_command(irc, send_cmd); 427 } 428 476 429 irc->status &= ~OPER_HACK_ANY; 477 g_free( password);478 } 479 480 static void irc_cmd_invite( irc_t *irc, char **cmd)430 g_free(password); 431 } 432 433 static void irc_cmd_invite(irc_t *irc, char **cmd) 481 434 { 482 435 irc_channel_t *ic; 483 436 irc_user_t *iu; 484 485 if( ( iu = irc_user_by_name( irc, cmd[1] ) ) == NULL ) 486 { 487 irc_send_num( irc, 401, "%s :No such nick", cmd[1] ); 488 return; 489 } 490 else if( ( ic = irc_channel_by_name( irc, cmd[2] ) ) == NULL ) 491 { 492 irc_send_num( irc, 403, "%s :No such channel", cmd[2] ); 493 return; 494 } 495 496 if( !ic->f->invite ) 497 irc_send_num( irc, 482, "%s :Can't invite people here", cmd[2] ); 498 else if( ic->f->invite( ic, iu ) ) 499 irc_send_num( irc, 341, "%s %s", iu->nick, ic->name ); 500 } 501 502 static void irc_cmd_kick( irc_t *irc, char **cmd ) 437 438 if ((iu = irc_user_by_name(irc, cmd[1])) == NULL) { 439 irc_send_num(irc, 401, "%s :No such nick", cmd[1]); 440 return; 441 } else if ((ic = irc_channel_by_name(irc, cmd[2])) == NULL) { 442 irc_send_num(irc, 403, "%s :No such channel", cmd[2]); 443 return; 444 } 445 446 if (!ic->f->invite) { 447 irc_send_num(irc, 482, "%s :Can't invite people here", cmd[2]); 448 } else if (ic->f->invite(ic, iu)) { 449 irc_send_num(irc, 341, "%s %s", iu->nick, ic->name); 450 } 451 } 452 453 static void irc_cmd_kick(irc_t *irc, char **cmd) 503 454 { 504 455 irc_channel_t *ic; 505 456 irc_user_t *iu; 506 507 if( ( iu = irc_user_by_name( irc, cmd[2] ) ) == NULL ) 508 { 509 irc_send_num( irc, 401, "%s :No such nick", cmd[2] ); 510 return; 511 } 512 else if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) 513 { 514 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 515 return; 516 } 517 else if( !ic->f->kick ) 518 { 519 irc_send_num( irc, 482, "%s :Can't kick people here", cmd[1] ); 520 return; 521 } 522 523 ic->f->kick( ic, iu, cmd[3] ? cmd[3] : NULL ); 524 } 525 526 static void irc_cmd_userhost( irc_t *irc, char **cmd ) 457 458 if ((iu = irc_user_by_name(irc, cmd[2])) == NULL) { 459 irc_send_num(irc, 401, "%s :No such nick", cmd[2]); 460 return; 461 } else if ((ic = irc_channel_by_name(irc, cmd[1])) == NULL) { 462 irc_send_num(irc, 403, "%s :No such channel", cmd[1]); 463 return; 464 } else if (!ic->f->kick) { 465 irc_send_num(irc, 482, "%s :Can't kick people here", cmd[1]); 466 return; 467 } 468 469 ic->f->kick(ic, iu, cmd[3] ? cmd[3] : NULL); 470 } 471 472 static void irc_cmd_userhost(irc_t *irc, char **cmd) 527 473 { 528 474 int i; 529 475 530 476 /* [TV] Usable USERHOST-implementation according to 531 532 533 477 RFC1459. Without this, mIRC shows an error 478 while connecting, and the used way of rejecting 479 breaks standards. 534 480 */ 535 536 for ( i = 1; cmd[i]; i ++ )537 {538 irc_user_t *iu = irc_user_by_name( irc, cmd[i] ); 539 540 if( iu )541 irc_send_num( irc, 302, ":%s=%c%s@%s", iu->nick,542 irc_user_get_away( iu ) ? '-' : '+',543 iu->user, iu->host );544 } 545 } 546 547 static void irc_cmd_ison( irc_t *irc, char **cmd)481 482 for (i = 1; cmd[i]; i++) { 483 irc_user_t *iu = irc_user_by_name(irc, cmd[i]); 484 485 if (iu) { 486 irc_send_num(irc, 302, ":%s=%c%s@%s", iu->nick, 487 irc_user_get_away(iu) ? '-' : '+', 488 iu->user, iu->host); 489 } 490 } 491 } 492 493 static void irc_cmd_ison(irc_t *irc, char **cmd) 548 494 { 549 495 char buff[IRC_MAX_LINE]; 550 496 int lenleft, i; 551 497 552 498 buff[0] = '\0'; 553 499 554 500 /* [SH] Leave room for : and \0 */ 555 501 lenleft = IRC_MAX_LINE - 2; 556 557 for( i = 1; cmd[i]; i ++ ) 558 { 502 503 for (i = 1; cmd[i]; i++) { 559 504 char *this, *next; 560 505 561 506 this = cmd[i]; 562 while( *this ) 563 { 507 while (*this) { 564 508 irc_user_t *iu; 565 566 if ( ( next = strchr( this, ' ' ) ) )509 510 if ((next = strchr(this, ' '))) { 567 511 *next = 0; 568 569 if( ( iu = irc_user_by_name( irc, this ) ) && 570 iu->bu && iu->bu->flags & BEE_USER_ONLINE )571 {572 lenleft -= strlen( iu->nick) + 1;573 574 if ( lenleft < 0 )512 } 513 514 if ((iu = irc_user_by_name(irc, this)) && 515 iu->bu && iu->bu->flags & BEE_USER_ONLINE) { 516 lenleft -= strlen(iu->nick) + 1; 517 518 if (lenleft < 0) { 575 519 break; 576 577 strcat( buff, iu->nick ); 578 strcat( buff, " ");579 }580 581 if( next ) 582 {520 } 521 522 strcat(buff, iu->nick); 523 strcat(buff, " "); 524 } 525 526 if (next) { 583 527 *next = ' '; 584 528 this = next + 1; 585 } 586 else 587 { 529 } else { 588 530 break; 589 } 590 } 591 531 } 532 } 533 592 534 /* *sigh* */ 593 if ( lenleft < 0 )535 if (lenleft < 0) { 594 536 break; 595 } 596 597 if( strlen( buff ) > 0 ) 598 buff[strlen(buff)-1] = '\0'; 599 600 irc_send_num( irc, 303, ":%s", buff ); 601 } 602 603 static void irc_cmd_watch( irc_t *irc, char **cmd ) 537 } 538 } 539 540 if (strlen(buff) > 0) { 541 buff[strlen(buff) - 1] = '\0'; 542 } 543 544 irc_send_num(irc, 303, ":%s", buff); 545 } 546 547 static void irc_cmd_watch(irc_t *irc, char **cmd) 604 548 { 605 549 int i; 606 550 607 551 /* Obviously we could also mark a user structure as being 608 552 watched, but what if the WATCH command is sent right 609 553 after connecting? The user won't exist yet then... */ 610 for( i = 1; cmd[i]; i ++ ) 611 { 554 for (i = 1; cmd[i]; i++) { 612 555 char *nick; 613 556 irc_user_t *iu; 614 615 if ( !cmd[i][0] || !cmd[i][1] )557 558 if (!cmd[i][0] || !cmd[i][1]) { 616 559 break; 617 618 nick = g_strdup( cmd[i] + 1 ); 619 nick _lc( irc, nick);620 621 iu = irc_user_by_name( irc, nick ); 622 623 if( cmd[i][0] == '+' ) 624 {625 if ( !g_hash_table_lookup( irc->watches, nick ) )626 g_hash_table_insert( irc->watches, nick, nick);627 628 if( iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE ) 629 irc_send_num( irc, 604, "%s %s %s %d :%s", iu->nick, iu->user,630 iu->host, (int) time( NULL ), "is online" );631 else632 irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*",633 (int) time( NULL ), "is offline" );634 }635 else if( cmd[i][0] == '-' )636 {560 } 561 562 nick = g_strdup(cmd[i] + 1); 563 nick_lc(irc, nick); 564 565 iu = irc_user_by_name(irc, nick); 566 567 if (cmd[i][0] == '+') { 568 if (!g_hash_table_lookup(irc->watches, nick)) { 569 g_hash_table_insert(irc->watches, nick, nick); 570 } 571 572 if (iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE) { 573 irc_send_num(irc, 604, "%s %s %s %d :%s", iu->nick, iu->user, 574 iu->host, (int) time(NULL), "is online"); 575 } else { 576 irc_send_num(irc, 605, "%s %s %s %d :%s", nick, "*", "*", 577 (int) time(NULL), "is offline"); 578 } 579 } else if (cmd[i][0] == '-') { 637 580 gpointer okey, ovalue; 638 639 if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) ) 640 { 641 g_hash_table_remove( irc->watches, okey ); 642 g_free( okey ); 643 644 irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" ); 645 } 646 } 647 } 648 } 649 650 static void irc_cmd_topic( irc_t *irc, char **cmd ) 651 { 652 irc_channel_t *ic = irc_channel_by_name( irc, cmd[1] ); 581 582 if (g_hash_table_lookup_extended(irc->watches, nick, &okey, &ovalue)) { 583 g_hash_table_remove(irc->watches, okey); 584 g_free(okey); 585 586 irc_send_num(irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching"); 587 } 588 } 589 } 590 } 591 592 static void irc_cmd_topic(irc_t *irc, char **cmd) 593 { 594 irc_channel_t *ic = irc_channel_by_name(irc, cmd[1]); 653 595 const char *new = cmd[2]; 654 655 if( ic == NULL ) 656 { 657 irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); 658 } 659 else if( new ) 660 { 661 if( ic->f->topic == NULL ) 662 irc_send_num( irc, 482, "%s :Can't change this channel's topic", ic->name ); 663 else if( ic->f->topic( ic, new ) ) 664 irc_send_topic( ic, TRUE ); 665 } 666 else 667 { 668 irc_send_topic( ic, FALSE ); 669 } 670 } 671 672 static void irc_cmd_away( irc_t *irc, char **cmd ) 673 { 674 if( cmd[1] && *cmd[1] ) 675 { 676 char away[strlen(cmd[1])+1]; 596 597 if (ic == NULL) { 598 irc_send_num(irc, 403, "%s :No such channel", cmd[1]); 599 } else if (new) { 600 if (ic->f->topic == NULL) { 601 irc_send_num(irc, 482, "%s :Can't change this channel's topic", ic->name); 602 } else if (ic->f->topic(ic, new)) { 603 irc_send_topic(ic, TRUE); 604 } 605 } else { 606 irc_send_topic(ic, FALSE); 607 } 608 } 609 610 static void irc_cmd_away(irc_t *irc, char **cmd) 611 { 612 if (cmd[1] && *cmd[1]) { 613 char away[strlen(cmd[1]) + 1]; 677 614 int i, j; 678 615 679 616 /* Copy away string, but skip control chars. Mainly because 680 617 Jabber really doesn't like them. */ 681 for( i = j = 0; cmd[1][i]; i ++ ) 682 if( (unsigned char) ( away[j] = cmd[1][i] ) >= ' ' ) 683 j ++; 618 for (i = j = 0; cmd[1][i]; i++) { 619 if ((unsigned char) (away[j] = cmd[1][i]) >= ' ') { 620 j++; 621 } 622 } 684 623 away[j] = '\0'; 685 686 irc_send_num( irc, 306, ":You're now away: %s", away ); 687 set_setstr( &irc->b->set, "away", away ); 688 } 689 else 690 { 691 irc_send_num( irc, 305, ":Welcome back" ); 692 set_setstr( &irc->b->set, "away", NULL ); 693 } 694 } 695 696 static void irc_cmd_list( irc_t *irc, char **cmd ) 624 625 irc_send_num(irc, 306, ":You're now away: %s", away); 626 set_setstr(&irc->b->set, "away", away); 627 } else { 628 irc_send_num(irc, 305, ":Welcome back"); 629 set_setstr(&irc->b->set, "away", NULL); 630 } 631 } 632 633 static void irc_cmd_list(irc_t *irc, char **cmd) 697 634 { 698 635 GSList *l; 699 700 for( l = irc->channels; l; l = l->next ) 701 { 636 637 for (l = irc->channels; l; l = l->next) { 702 638 irc_channel_t *ic = l->data; 703 704 irc_send_num( 705 ic->name, g_slist_length( ic->users ), ic->topic ? : "");706 } 707 irc_send_num( irc, 323, ":%s", "End of /LIST");708 } 709 710 static void irc_cmd_version( irc_t *irc, char **cmd)711 { 712 irc_send_num( 713 PACKAGE, BITLBEE_VERSION, irc->root->host, ARCH, CPU);714 } 715 716 static void irc_cmd_completions( irc_t *irc, char **cmd)639 640 irc_send_num(irc, 322, "%s %d :%s", 641 ic->name, g_slist_length(ic->users), ic->topic ? : ""); 642 } 643 irc_send_num(irc, 323, ":%s", "End of /LIST"); 644 } 645 646 static void irc_cmd_version(irc_t *irc, char **cmd) 647 { 648 irc_send_num(irc, 351, "%s-%s. %s :%s/%s ", 649 PACKAGE, BITLBEE_VERSION, irc->root->host, ARCH, CPU); 650 } 651 652 static void irc_cmd_completions(irc_t *irc, char **cmd) 717 653 { 718 654 help_t *h; 719 655 set_t *s; 720 656 int i; 721 722 irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK" ); 723 724 for( i = 0; root_commands[i].command; i ++ ) 725 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", root_commands[i].command ); 726 727 for( h = global.help; h; h = h->next ) 728 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS help %s", h->title ); 729 730 for( s = irc->b->set; s; s = s->next ) 731 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS set %s", s->key ); 732 733 irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END" ); 734 } 735 736 static void irc_cmd_rehash( irc_t *irc, char **cmd ) 737 { 738 if( global.conf->runmode == RUNMODE_INETD ) 739 ipc_master_cmd_rehash( NULL, NULL ); 740 else 741 ipc_to_master( cmd ); 742 743 irc_send_num( irc, 382, "%s :Rehashing", global.conf_file ); 657 658 irc_send_msg_raw(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK"); 659 660 for (i = 0; root_commands[i].command; i++) { 661 irc_send_msg_f(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", root_commands[i].command); 662 } 663 664 for (h = global.help; h; h = h->next) { 665 irc_send_msg_f(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS help %s", h->title); 666 } 667 668 for (s = irc->b->set; s; s = s->next) { 669 irc_send_msg_f(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS set %s", s->key); 670 } 671 672 irc_send_msg_raw(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END"); 673 } 674 675 static void irc_cmd_rehash(irc_t *irc, char **cmd) 676 { 677 if (global.conf->runmode == RUNMODE_INETD) { 678 ipc_master_cmd_rehash(NULL, NULL); 679 } else { 680 ipc_to_master(cmd); 681 } 682 683 irc_send_num(irc, 382, "%s :Rehashing", global.conf_file); 744 684 } 745 685 … … 784 724 }; 785 725 786 void irc_exec( irc_t *irc, char *cmd[])787 { 726 void irc_exec(irc_t *irc, char *cmd[]) 727 { 788 728 int i, n_arg; 789 790 if ( !cmd[0] )791 return; 792 793 for( i = 0; irc_commands[i].command; i++ ) 794 if( g_strcasecmp( irc_commands[i].command, cmd[0] ) == 0 )795 {729 730 if (!cmd[0]) { 731 return; 732 } 733 734 for (i = 0; irc_commands[i].command; i++) { 735 if (g_strcasecmp(irc_commands[i].command, cmd[0]) == 0) { 796 736 /* There should be no typo in the next line: */ 797 for ( n_arg = 0; cmd[n_arg]; n_arg ++ )737 for (n_arg = 0; cmd[n_arg]; n_arg++) { 798 738 ; 739 } 799 740 n_arg--; 800 801 if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN ) 802 { 803 irc_send_num( irc, 462, ":Only allowed before logging in" ); 804 } 805 else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) ) 806 { 807 irc_send_num( irc, 451, ":Register first" ); 808 } 809 else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) ) 810 { 811 irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" ); 812 } 813 else if( n_arg < irc_commands[i].required_parameters ) 814 { 815 irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] ); 816 } 817 else if( irc_commands[i].flags & IRC_CMD_TO_MASTER ) 818 { 741 742 if (irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN) { 743 irc_send_num(irc, 462, ":Only allowed before logging in"); 744 } else if (irc_commands[i].flags & IRC_CMD_LOGGED_IN && !(irc->status & USTATUS_LOGGED_IN)) { 745 irc_send_num(irc, 451, ":Register first"); 746 } else if (irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr(irc->umode, 'o')) { 747 irc_send_num(irc, 481, ":Permission denied - You're not an IRC operator"); 748 } else if (n_arg < irc_commands[i].required_parameters) { 749 irc_send_num(irc, 461, "%s :Need more parameters", cmd[0]); 750 } else if (irc_commands[i].flags & IRC_CMD_TO_MASTER) { 819 751 /* IPC doesn't make sense in inetd mode, 820 752 but the function will catch that. */ 821 ipc_to_master( cmd ); 822 } 823 else 824 { 825 irc_commands[i].execute( irc, cmd ); 826 } 827 753 ipc_to_master(cmd); 754 } else { 755 irc_commands[i].execute(irc, cmd); 756 } 757 828 758 return; 829 759 } 830 831 if( irc->status & USTATUS_LOGGED_IN ) 832 irc_send_num( irc, 421, "%s :Unknown command", cmd[0] ); 833 } 760 } 761 762 if (irc->status & USTATUS_LOGGED_IN) { 763 irc_send_num(irc, 421, "%s :Unknown command", cmd[0]); 764 } 765 }
Note: See TracChangeset
for help on using the changeset viewer.