- 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.c
raf359b4 r5ebff60 1 1 /********************************************************************\ 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * … … 32 32 GSList *irc_plugins; 33 33 34 static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond);35 static char *set_eval_charset( set_t *set, char *value);36 static char *set_eval_password( set_t *set, char *value);37 static char *set_eval_bw_compat( set_t *set, char *value);38 static char *set_eval_utf8_nicks( set_t *set, char *value);39 40 irc_t *irc_new( int fd)34 static gboolean irc_userping(gpointer _irc, gint fd, b_input_condition cond); 35 static char *set_eval_charset(set_t *set, char *value); 36 static char *set_eval_password(set_t *set, char *value); 37 static char *set_eval_bw_compat(set_t *set, char *value); 38 static char *set_eval_utf8_nicks(set_t *set, char *value); 39 40 irc_t *irc_new(int fd) 41 41 { 42 42 irc_t *irc; 43 43 struct sockaddr_storage sock; 44 socklen_t socklen = sizeof( sock);44 socklen_t socklen = sizeof(sock); 45 45 char *host = NULL, *myhost = NULL; 46 46 irc_user_t *iu; … … 48 48 set_t *s; 49 49 bee_t *b; 50 51 irc = g_new0( irc_t, 1);52 50 51 irc = g_new0(irc_t, 1); 52 53 53 irc->fd = fd; 54 sock_make_nonblocking( irc->fd);55 56 irc->r_watch_source_id = b_input_add( irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc);57 54 sock_make_nonblocking(irc->fd); 55 56 irc->r_watch_source_id = b_input_add(irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc); 57 58 58 irc->status = USTATUS_OFFLINE; 59 59 irc->last_pong = gettime(); 60 61 irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal ); 62 irc->watches = g_hash_table_new( g_str_hash, g_str_equal ); 63 64 irc->iconv = (GIConv) -1; 65 irc->oconv = (GIConv) -1; 66 67 if( global.conf->hostname ) 68 { 69 myhost = g_strdup( global.conf->hostname ); 70 } 71 else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) 72 { 73 char buf[NI_MAXHOST+1]; 74 75 if( getnameinfo( (struct sockaddr *) &sock, socklen, buf, 76 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 77 { 78 myhost = g_strdup( ipv6_unwrap( buf ) ); 79 } 80 } 81 82 if( getpeername( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) 83 { 84 char buf[NI_MAXHOST+1]; 85 86 if( getnameinfo( (struct sockaddr *)&sock, socklen, buf, 87 NI_MAXHOST, NULL, 0, 0 ) == 0 ) 88 { 89 host = g_strdup( ipv6_unwrap( buf ) ); 90 } 91 } 92 93 if( host == NULL ) 94 host = g_strdup( "localhost.localdomain" ); 95 if( myhost == NULL ) 96 myhost = g_strdup( "localhost.localdomain" ); 97 98 if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 ) 99 irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc ); 100 101 irc_connection_list = g_slist_append( irc_connection_list, irc ); 102 60 61 irc->nick_user_hash = g_hash_table_new(g_str_hash, g_str_equal); 62 irc->watches = g_hash_table_new(g_str_hash, g_str_equal); 63 64 irc->iconv = (GIConv) - 1; 65 irc->oconv = (GIConv) - 1; 66 67 if (global.conf->hostname) { 68 myhost = g_strdup(global.conf->hostname); 69 } else if (getsockname(irc->fd, (struct sockaddr*) &sock, &socklen) == 0) { 70 char buf[NI_MAXHOST + 1]; 71 72 if (getnameinfo((struct sockaddr *) &sock, socklen, buf, 73 NI_MAXHOST, NULL, 0, 0) == 0) { 74 myhost = g_strdup(ipv6_unwrap(buf)); 75 } 76 } 77 78 if (getpeername(irc->fd, (struct sockaddr*) &sock, &socklen) == 0) { 79 char buf[NI_MAXHOST + 1]; 80 81 if (getnameinfo((struct sockaddr *) &sock, socklen, buf, 82 NI_MAXHOST, NULL, 0, 0) == 0) { 83 host = g_strdup(ipv6_unwrap(buf)); 84 } 85 } 86 87 if (host == NULL) { 88 host = g_strdup("localhost.localdomain"); 89 } 90 if (myhost == NULL) { 91 myhost = g_strdup("localhost.localdomain"); 92 } 93 94 if (global.conf->ping_interval > 0 && global.conf->ping_timeout > 0) { 95 irc->ping_source_id = b_timeout_add(global.conf->ping_interval * 1000, irc_userping, irc); 96 } 97 98 irc_connection_list = g_slist_append(irc_connection_list, irc); 99 103 100 b = irc->b = bee_new(); 104 101 b->ui_data = irc; 105 102 b->ui = &irc_ui_funcs; 106 107 s = set_add( &b->set, "allow_takeover", "true", set_eval_bool, irc);108 s = set_add( &b->set, "away_devoice", "true", set_eval_bw_compat, irc);103 104 s = set_add(&b->set, "allow_takeover", "true", set_eval_bool, irc); 105 s = set_add(&b->set, "away_devoice", "true", set_eval_bw_compat, irc); 109 106 s->flags |= SET_HIDDEN; 110 s = set_add( &b->set, "away_reply_timeout", "3600", set_eval_int, irc);111 s = set_add( &b->set, "charset", "utf-8", set_eval_charset, irc);112 s = set_add( &b->set, "default_target", "root", NULL, irc);113 s = set_add( &b->set, "display_namechanges", "false", set_eval_bool, irc);114 s = set_add( &b->set, "display_timestamps", "true", set_eval_bool, irc);115 s = set_add( &b->set, "handle_unknown", "add_channel", NULL, irc);116 s = set_add( &b->set, "last_version", "0", NULL, irc);107 s = set_add(&b->set, "away_reply_timeout", "3600", set_eval_int, irc); 108 s = set_add(&b->set, "charset", "utf-8", set_eval_charset, irc); 109 s = set_add(&b->set, "default_target", "root", NULL, irc); 110 s = set_add(&b->set, "display_namechanges", "false", set_eval_bool, irc); 111 s = set_add(&b->set, "display_timestamps", "true", set_eval_bool, irc); 112 s = set_add(&b->set, "handle_unknown", "add_channel", NULL, irc); 113 s = set_add(&b->set, "last_version", "0", NULL, irc); 117 114 s->flags |= SET_HIDDEN; 118 s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc);119 s = set_add( &b->set, "nick_format", "%-@nick", NULL, irc);120 s = set_add( &b->set, "offline_user_quits", "true", set_eval_bool, irc);121 s = set_add( &b->set, "ops", "both", set_eval_irc_channel_ops, irc);122 s = set_add( &b->set, "paste_buffer", "false", set_eval_bool, irc);123 s->old_key = g_strdup( "buddy_sendbuffer");124 s = set_add( &b->set, "paste_buffer_delay", "200", set_eval_int, irc);125 s->old_key = g_strdup( "buddy_sendbuffer_delay");126 s = set_add( &b->set, "password", NULL, set_eval_password, irc);115 s = set_add(&b->set, "lcnicks", "true", set_eval_bool, irc); 116 s = set_add(&b->set, "nick_format", "%-@nick", NULL, irc); 117 s = set_add(&b->set, "offline_user_quits", "true", set_eval_bool, irc); 118 s = set_add(&b->set, "ops", "both", set_eval_irc_channel_ops, irc); 119 s = set_add(&b->set, "paste_buffer", "false", set_eval_bool, irc); 120 s->old_key = g_strdup("buddy_sendbuffer"); 121 s = set_add(&b->set, "paste_buffer_delay", "200", set_eval_int, irc); 122 s->old_key = g_strdup("buddy_sendbuffer_delay"); 123 s = set_add(&b->set, "password", NULL, set_eval_password, irc); 127 124 s->flags |= SET_NULL_OK | SET_PASSWORD; 128 s = set_add( &b->set, "private", "true", set_eval_bool, irc);129 s = set_add( &b->set, "query_order", "lifo", NULL, irc);130 s = set_add( &b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc);125 s = set_add(&b->set, "private", "true", set_eval_bool, irc); 126 s = set_add(&b->set, "query_order", "lifo", NULL, irc); 127 s = set_add(&b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc); 131 128 s->flags |= SET_HIDDEN; 132 s = set_add( &b->set, "show_offline", "false", set_eval_bw_compat, irc);129 s = set_add(&b->set, "show_offline", "false", set_eval_bw_compat, irc); 133 130 s->flags |= SET_HIDDEN; 134 s = set_add( &b->set, "simulate_netsplit", "true", set_eval_bool, irc);135 s = set_add( &b->set, "timezone", "local", set_eval_timezone, irc);136 s = set_add( &b->set, "to_char", ": ", set_eval_to_char, irc);137 s = set_add( &b->set, "typing_notice", "false", set_eval_bool, irc);138 s = set_add( &b->set, "utf8_nicks", "false", set_eval_utf8_nicks, irc);139 140 irc->root = iu = irc_user_new( irc, ROOT_NICK);141 iu->host = g_strdup( myhost);142 iu->fullname = g_strdup( ROOT_FN);131 s = set_add(&b->set, "simulate_netsplit", "true", set_eval_bool, irc); 132 s = set_add(&b->set, "timezone", "local", set_eval_timezone, irc); 133 s = set_add(&b->set, "to_char", ": ", set_eval_to_char, irc); 134 s = set_add(&b->set, "typing_notice", "false", set_eval_bool, irc); 135 s = set_add(&b->set, "utf8_nicks", "false", set_eval_utf8_nicks, irc); 136 137 irc->root = iu = irc_user_new(irc, ROOT_NICK); 138 iu->host = g_strdup(myhost); 139 iu->fullname = g_strdup(ROOT_FN); 143 140 iu->f = &irc_user_root_funcs; 144 145 iu = irc_user_new( irc, NS_NICK);146 iu->host = g_strdup( myhost);147 iu->fullname = g_strdup( ROOT_FN);141 142 iu = irc_user_new(irc, NS_NICK); 143 iu->host = g_strdup(myhost); 144 iu->fullname = g_strdup(ROOT_FN); 148 145 iu->f = &irc_user_root_funcs; 149 150 irc->user = g_new0( irc_user_t, 1);151 irc->user->host = g_strdup( host);152 153 conf_loaddefaults( irc);154 146 147 irc->user = g_new0(irc_user_t, 1); 148 irc->user->host = g_strdup(host); 149 150 conf_loaddefaults(irc); 151 155 152 /* Evaluator sets the iconv/oconv structures. */ 156 set_eval_charset( set_find( &b->set, "charset" ), set_getstr( &b->set, "charset" ) ); 157 158 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on" ); 159 if( isatty( irc->fd ) ) 160 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, 161 "If you read this, you most likely accidentally " 162 "started BitlBee in inetd mode on the command line. " 163 "You probably want to run it in (Fork)Daemon mode. " 164 "See doc/README for more information." ); 165 166 g_free( myhost ); 167 g_free( host ); 168 153 set_eval_charset(set_find(&b->set, "charset"), set_getstr(&b->set, "charset")); 154 155 irc_write(irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on"); 156 if (isatty(irc->fd)) { 157 irc_write(irc, ":%s NOTICE AUTH :%s", irc->root->host, 158 "If you read this, you most likely accidentally " 159 "started BitlBee in inetd mode on the command line. " 160 "You probably want to run it in (Fork)Daemon mode. " 161 "See doc/README for more information."); 162 } 163 164 g_free(myhost); 165 g_free(host); 166 169 167 /* libpurple doesn't like fork()s after initializing itself, so this 170 168 is the right moment to initialize it. */ … … 177 175 work if a fork is detected */ 178 176 ssl_init(); 179 180 for( l = irc_plugins; l; l = l->next ) 181 { 177 178 for (l = irc_plugins; l; l = l->next) { 182 179 irc_plugin_t *p = l->data; 183 if( p->irc_new ) 184 p->irc_new( irc ); 185 } 186 180 if (p->irc_new) { 181 p->irc_new(irc); 182 } 183 } 184 187 185 return irc; 188 186 } … … 191 189 this one will "log". In case the connection is already broken and we 192 190 shouldn't try to write to it. */ 193 void irc_abort( irc_t *irc, int immed, char *format, ...)191 void irc_abort(irc_t *irc, int immed, char *format, ...) 194 192 { 195 193 char *reason = NULL; 196 197 if( format != NULL ) 198 { 194 195 if (format != NULL) { 199 196 va_list params; 200 201 va_start( params, format ); 202 reason = g_strdup_vprintf( format, params ); 203 va_end( params ); 204 } 205 206 if( reason ) 207 irc_write( irc, "ERROR :Closing link: %s", reason ); 208 209 ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", 210 irc->user->nick ? irc->user->nick : "(NONE)", 211 irc->user->host, reason ? : "" ); 212 213 g_free( reason ); 214 215 irc_flush( irc ); 216 if( immed ) 217 { 218 irc_free( irc ); 219 } 220 else 221 { 222 b_event_remove( irc->ping_source_id ); 223 irc->ping_source_id = b_timeout_add( 1, (b_event_handler) irc_free, irc ); 224 } 225 } 226 227 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ); 228 229 void irc_free( irc_t * irc ) 197 198 va_start(params, format); 199 reason = g_strdup_vprintf(format, params); 200 va_end(params); 201 } 202 203 if (reason) { 204 irc_write(irc, "ERROR :Closing link: %s", reason); 205 } 206 207 ipc_to_master_str("OPERMSG :Client exiting: %s@%s [%s]\r\n", 208 irc->user->nick ? irc->user->nick : "(NONE)", 209 irc->user->host, reason ? : ""); 210 211 g_free(reason); 212 213 irc_flush(irc); 214 if (immed) { 215 irc_free(irc); 216 } else { 217 b_event_remove(irc->ping_source_id); 218 irc->ping_source_id = b_timeout_add(1, (b_event_handler) irc_free, irc); 219 } 220 } 221 222 static gboolean irc_free_hashkey(gpointer key, gpointer value, gpointer data); 223 224 void irc_free(irc_t * irc) 230 225 { 231 226 GSList *l; 232 227 233 228 irc->status |= USTATUS_SHUTDOWN; 234 235 log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); 236 237 if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) ) 238 if( storage_save( irc, NULL, TRUE ) != STORAGE_OK ) 239 log_message( LOGLVL_WARNING, "Error while saving settings for user %s", irc->user->nick ); 240 241 for( l = irc_plugins; l; l = l->next ) 242 { 229 230 log_message(LOGLVL_INFO, "Destroying connection with fd %d", irc->fd); 231 232 if (irc->status & USTATUS_IDENTIFIED && set_getbool(&irc->b->set, "save_on_quit")) { 233 if (storage_save(irc, NULL, TRUE) != STORAGE_OK) { 234 log_message(LOGLVL_WARNING, "Error while saving settings for user %s", irc->user->nick); 235 } 236 } 237 238 for (l = irc_plugins; l; l = l->next) { 243 239 irc_plugin_t *p = l->data; 244 if( p->irc_free ) 245 p->irc_free( irc ); 246 } 247 248 irc_connection_list = g_slist_remove( irc_connection_list, irc ); 249 250 while( irc->queries != NULL ) 251 query_del( irc, irc->queries ); 252 240 if (p->irc_free) { 241 p->irc_free(irc); 242 } 243 } 244 245 irc_connection_list = g_slist_remove(irc_connection_list, irc); 246 247 while (irc->queries != NULL) { 248 query_del(irc, irc->queries); 249 } 250 253 251 /* This is a little bit messy: bee_free() frees all b->users which 254 252 calls us back to free the corresponding irc->users. So do this 255 253 before we clear the remaining ones ourselves. */ 256 bee_free( irc->b ); 257 258 while( irc->users ) 259 irc_user_free( irc, (irc_user_t *) irc->users->data ); 260 261 while( irc->channels ) 262 irc_channel_free( irc->channels->data ); 263 264 if( irc->ping_source_id > 0 ) 265 b_event_remove( irc->ping_source_id ); 266 if( irc->r_watch_source_id > 0 ) 267 b_event_remove( irc->r_watch_source_id ); 268 if( irc->w_watch_source_id > 0 ) 269 b_event_remove( irc->w_watch_source_id ); 270 271 closesocket( irc->fd ); 254 bee_free(irc->b); 255 256 while (irc->users) { 257 irc_user_free(irc, (irc_user_t *) irc->users->data); 258 } 259 260 while (irc->channels) { 261 irc_channel_free(irc->channels->data); 262 } 263 264 if (irc->ping_source_id > 0) { 265 b_event_remove(irc->ping_source_id); 266 } 267 if (irc->r_watch_source_id > 0) { 268 b_event_remove(irc->r_watch_source_id); 269 } 270 if (irc->w_watch_source_id > 0) { 271 b_event_remove(irc->w_watch_source_id); 272 } 273 274 closesocket(irc->fd); 272 275 irc->fd = -1; 273 274 g_hash_table_foreach_remove( irc->nick_user_hash, irc_free_hashkey, NULL ); 275 g_hash_table_destroy( irc->nick_user_hash ); 276 277 g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL ); 278 g_hash_table_destroy( irc->watches ); 279 280 if( irc->iconv != (GIConv) -1 ) 281 g_iconv_close( irc->iconv ); 282 if( irc->oconv != (GIConv) -1 ) 283 g_iconv_close( irc->oconv ); 284 285 g_free( irc->sendbuffer ); 286 g_free( irc->readbuffer ); 287 g_free( irc->password ); 288 289 g_free( irc ); 290 291 if( global.conf->runmode == RUNMODE_INETD || 276 277 g_hash_table_foreach_remove(irc->nick_user_hash, irc_free_hashkey, NULL); 278 g_hash_table_destroy(irc->nick_user_hash); 279 280 g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL); 281 g_hash_table_destroy(irc->watches); 282 283 if (irc->iconv != (GIConv) - 1) { 284 g_iconv_close(irc->iconv); 285 } 286 if (irc->oconv != (GIConv) - 1) { 287 g_iconv_close(irc->oconv); 288 } 289 290 g_free(irc->sendbuffer); 291 g_free(irc->readbuffer); 292 g_free(irc->password); 293 294 g_free(irc); 295 296 if (global.conf->runmode == RUNMODE_INETD || 292 297 global.conf->runmode == RUNMODE_FORKDAEMON || 293 ( 294 295 irc_connection_list == NULL ) )298 (global.conf->runmode == RUNMODE_DAEMON && 299 global.listen_socket == -1 && 300 irc_connection_list == NULL)) { 296 301 b_main_quit(); 297 } 298 299 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) 300 { 301 g_free( key ); 302 303 return( TRUE ); 302 } 303 } 304 305 static gboolean irc_free_hashkey(gpointer key, gpointer value, gpointer data) 306 { 307 g_free(key); 308 309 return(TRUE); 304 310 } 305 311 306 312 /* USE WITH CAUTION! 307 313 Sets pass without checking */ 308 void irc_setpass 309 { 310 g_free 311 314 void irc_setpass(irc_t *irc, const char *pass) 315 { 316 g_free(irc->password); 317 312 318 if (pass) { 313 irc->password = g_strdup 319 irc->password = g_strdup(pass); 314 320 } else { 315 321 irc->password = NULL; … … 317 323 } 318 324 319 static char *set_eval_password( set_t *set, char *value)325 static char *set_eval_password(set_t *set, char *value) 320 326 { 321 327 irc_t *irc = set->data; 322 323 if( irc->status & USTATUS_IDENTIFIED && value ) 324 { 325 irc_setpass( irc, value ); 328 329 if (irc->status & USTATUS_IDENTIFIED && value) { 330 irc_setpass(irc, value); 326 331 return NULL; 327 } 328 else 329 { 332 } else { 330 333 return SET_INVALID; 331 334 } 332 335 } 333 336 334 static char **irc_splitlines( char *buffer);335 336 void irc_process( irc_t *irc)337 static char **irc_splitlines(char *buffer); 338 339 void irc_process(irc_t *irc) 337 340 { 338 341 char **lines, *temp, **cmd; 339 342 int i; 340 343 341 if( irc->readbuffer != NULL ) 342 { 343 lines = irc_splitlines( irc->readbuffer ); 344 345 for( i = 0; *lines[i] != '\0'; i ++ ) 346 { 344 if (irc->readbuffer != NULL) { 345 lines = irc_splitlines(irc->readbuffer); 346 347 for (i = 0; *lines[i] != '\0'; i++) { 347 348 char *conv = NULL; 348 349 349 350 /* [WvG] If the last line isn't empty, it's an incomplete line and we 350 351 should wait for the rest to come in before processing it. */ 351 if( lines[i+1] == NULL ) 352 { 353 temp = g_strdup( lines[i] ); 354 g_free( irc->readbuffer ); 352 if (lines[i + 1] == NULL) { 353 temp = g_strdup(lines[i]); 354 g_free(irc->readbuffer); 355 355 irc->readbuffer = temp; 356 i 356 i++; 357 357 break; 358 358 } 359 360 if( irc->iconv != (GIConv) -1 ) 361 { 359 360 if (irc->iconv != (GIConv) - 1) { 362 361 gsize bytes_read, bytes_written; 363 364 conv = g_convert_with_iconv( lines[i], -1, irc->iconv, 365 &bytes_read, &bytes_written, NULL ); 366 367 if( conv == NULL || bytes_read != strlen( lines[i] ) ) 368 { 362 363 conv = g_convert_with_iconv(lines[i], -1, irc->iconv, 364 &bytes_read, &bytes_written, NULL); 365 366 if (conv == NULL || bytes_read != strlen(lines[i])) { 369 367 /* GLib can do strange things if things are not in the expected charset, 370 368 so let's be a little bit paranoid here: */ 371 if( irc->status & USTATUS_LOGGED_IN ) 372 { 373 irc_rootmsg( irc, "Error: Charset mismatch detected. The charset " 374 "setting is currently set to %s, so please make " 375 "sure your IRC client will send and accept text in " 376 "that charset, or tell BitlBee which charset to " 377 "expect by changing the charset setting. See " 378 "`help set charset' for more information. Your " 379 "message was ignored.", 380 set_getstr( &irc->b->set, "charset" ) ); 381 382 g_free( conv ); 369 if (irc->status & USTATUS_LOGGED_IN) { 370 irc_rootmsg(irc, "Error: Charset mismatch detected. The charset " 371 "setting is currently set to %s, so please make " 372 "sure your IRC client will send and accept text in " 373 "that charset, or tell BitlBee which charset to " 374 "expect by changing the charset setting. See " 375 "`help set charset' for more information. Your " 376 "message was ignored.", 377 set_getstr(&irc->b->set, "charset")); 378 379 g_free(conv); 383 380 conv = NULL; 384 } 385 else 386 { 387 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, 388 "Warning: invalid characters received at login time." ); 389 390 conv = g_strdup( lines[i] ); 391 for( temp = conv; *temp; temp ++ ) 392 if( *temp & 0x80 ) 381 } else { 382 irc_write(irc, ":%s NOTICE AUTH :%s", irc->root->host, 383 "Warning: invalid characters received at login time."); 384 385 conv = g_strdup(lines[i]); 386 for (temp = conv; *temp; temp++) { 387 if (*temp & 0x80) { 393 388 *temp = '?'; 389 } 390 } 394 391 } 395 392 } 396 393 lines[i] = conv; 397 394 } 398 399 if( lines[i] && ( cmd = irc_parse_line( lines[i] ) ) ) 400 { 401 irc_exec( irc, cmd ); 402 g_free( cmd ); 403 } 404 405 g_free( conv ); 406 395 396 if (lines[i] && (cmd = irc_parse_line(lines[i]))) { 397 irc_exec(irc, cmd); 398 g_free(cmd); 399 } 400 401 g_free(conv); 402 407 403 /* Shouldn't really happen, but just in case... */ 408 if( !g_slist_find( irc_connection_list, irc ) ) 409 { 410 g_free( lines ); 404 if (!g_slist_find(irc_connection_list, irc)) { 405 g_free(lines); 411 406 return; 412 407 } 413 408 } 414 415 if( lines[i] != NULL ) 416 { 417 g_free( irc->readbuffer ); 409 410 if (lines[i] != NULL) { 411 g_free(irc->readbuffer); 418 412 irc->readbuffer = NULL; 419 413 } 420 421 g_free( lines);414 415 g_free(lines); 422 416 } 423 417 } … … 427 421 an empty string. Could use g_strsplit() but this one does it in-place. 428 422 (So yes, it's destructive.) */ 429 static char **irc_splitlines( char *buffer)423 static char **irc_splitlines(char *buffer) 430 424 { 431 425 int i, j, n = 3; … … 433 427 434 428 /* Allocate n+1 elements. */ 435 lines = g_new( char *, n + 1);436 429 lines = g_new(char *, n + 1); 430 437 431 lines[0] = buffer; 438 432 439 433 /* Split the buffer in several strings, and accept any kind of line endings, 440 434 * knowing that ERC on Windows may send something interesting like \r\r\n, 441 435 * and surely there must be clients that think just \n is enough... */ 442 for( i = 0, j = 0; buffer[i] != '\0'; i ++ ) 443 { 444 if( buffer[i] == '\r' || buffer[i] == '\n' ) 445 { 446 while( buffer[i] == '\r' || buffer[i] == '\n' ) 436 for (i = 0, j = 0; buffer[i] != '\0'; i++) { 437 if (buffer[i] == '\r' || buffer[i] == '\n') { 438 while (buffer[i] == '\r' || buffer[i] == '\n') { 447 439 buffer[i++] = '\0'; 448 440 } 441 449 442 lines[++j] = buffer + i; 450 451 if( j >= n ) 452 { 443 444 if (j >= n) { 453 445 n *= 2; 454 lines = g_renew( char *, lines, n + 1);455 } 456 457 if ( buffer[i] == '\0' )446 lines = g_renew(char *, lines, n + 1); 447 } 448 449 if (buffer[i] == '\0') { 458 450 break; 459 } 460 } 461 462 /* NULL terminate our list. */ 451 } 452 } 453 } 454 455 /* NULL terminate our list. */ 463 456 lines[++j] = NULL; 464 457 465 458 return lines; 466 459 } 467 460 468 461 /* Split an IRC-style line into little parts/arguments. */ 469 char **irc_parse_line( char *line)462 char **irc_parse_line(char *line) 470 463 { 471 464 int i, j; 472 465 char **cmd; 473 466 474 467 /* Move the line pointer to the start of the command, skipping spaces and the optional prefix. */ 475 if( line[0] == ':' ) 476 { 477 for( i = 0; line[i] && line[i] != ' '; i ++ ); 468 if (line[0] == ':') { 469 for (i = 0; line[i] && line[i] != ' '; i++) { 470 ; 471 } 478 472 line = line + i; 479 473 } 480 for( i = 0; line[i] == ' '; i ++ ); 474 for (i = 0; line[i] == ' '; i++) { 475 ; 476 } 481 477 line = line + i; 482 478 483 479 /* If we're already at the end of the line, return. If not, we're going to need at least one element. */ 484 if ( line[0] == '\0')480 if (line[0] == '\0') { 485 481 return NULL; 486 482 } 483 487 484 /* Count the number of char **cmd elements we're going to need. */ 488 485 j = 1; 489 for( i = 0; line[i] != '\0'; i ++ ) 490 { 491 if( line[i] == ' ' ) 492 { 493 j ++; 494 495 if( line[i+1] == ':' ) 486 for (i = 0; line[i] != '\0'; i++) { 487 if (line[i] == ' ') { 488 j++; 489 490 if (line[i + 1] == ':') { 496 491 break; 497 } 498 } 492 } 493 } 494 } 499 495 500 496 /* Allocate the space we need. */ 501 cmd = g_new( char *, j + 1);497 cmd = g_new(char *, j + 1); 502 498 cmd[j] = NULL; 503 499 504 500 /* Do the actual line splitting, format is: 505 501 * Input: "PRIVMSG #bitlbee :foo bar" … … 508 504 509 505 cmd[0] = line; 510 for( i = 0, j = 0; line[i] != '\0'; i ++ ) 511 { 512 if( line[i] == ' ' ) 513 { 506 for (i = 0, j = 0; line[i] != '\0'; i++) { 507 if (line[i] == ' ') { 514 508 line[i] = '\0'; 515 509 cmd[++j] = line + i + 1; 516 517 if( line[i+1] == ':' ) 518 { 519 cmd[j] ++; 510 511 if (line[i + 1] == ':') { 512 cmd[j]++; 520 513 break; 521 514 } 522 515 } 523 516 } 524 517 525 518 return cmd; 526 519 } 527 520 528 521 /* Converts such an array back into a command string. Mainly used for the IPC code right now. */ 529 char *irc_build_line( char **cmd)522 char *irc_build_line(char **cmd) 530 523 { 531 524 int i, len; 532 525 char *s; 533 534 if ( cmd[0] == NULL )526 527 if (cmd[0] == NULL) { 535 528 return NULL; 536 529 } 530 537 531 len = 1; 538 for( i = 0; cmd[i]; i ++ ) 539 len += strlen( cmd[i] ) + 1; 540 541 if( strchr( cmd[i-1], ' ' ) != NULL ) 542 len ++; 543 544 s = g_new0( char, len + 1 ); 545 for( i = 0; cmd[i]; i ++ ) 546 { 547 if( cmd[i+1] == NULL && strchr( cmd[i], ' ' ) != NULL ) 548 strcat( s, ":" ); 549 550 strcat( s, cmd[i] ); 551 552 if( cmd[i+1] ) 553 strcat( s, " " ); 554 } 555 strcat( s, "\r\n" ); 556 532 for (i = 0; cmd[i]; i++) { 533 len += strlen(cmd[i]) + 1; 534 } 535 536 if (strchr(cmd[i - 1], ' ') != NULL) { 537 len++; 538 } 539 540 s = g_new0(char, len + 1); 541 for (i = 0; cmd[i]; i++) { 542 if (cmd[i + 1] == NULL && strchr(cmd[i], ' ') != NULL) { 543 strcat(s, ":"); 544 } 545 546 strcat(s, cmd[i]); 547 548 if (cmd[i + 1]) { 549 strcat(s, " "); 550 } 551 } 552 strcat(s, "\r\n"); 553 557 554 return s; 558 555 } 559 556 560 void irc_write( irc_t *irc, char *format, ... )557 void irc_write(irc_t *irc, char *format, ...) 561 558 { 562 559 va_list params; 563 560 564 va_start( params, format);565 irc_vawrite( irc, format, params );566 va_end( params);561 va_start(params, format); 562 irc_vawrite(irc, format, params); 563 va_end(params); 567 564 568 565 return; 569 566 } 570 567 571 void irc_write_all( int now, char *format, ...)568 void irc_write_all(int now, char *format, ...) 572 569 { 573 570 va_list params; 574 GSList *temp; 575 576 va_start( params, format);577 571 GSList *temp; 572 573 va_start(params, format); 574 578 575 temp = irc_connection_list; 579 while( temp != NULL ) 580 { 576 while (temp != NULL) { 581 577 irc_t *irc = temp->data; 582 583 if( now ) 584 { 585 g_free( irc->sendbuffer ); 586 irc->sendbuffer = g_strdup( "\r\n" ); 587 } 588 irc_vawrite( temp->data, format, params ); 589 if( now ) 590 { 591 bitlbee_io_current_client_write( irc, irc->fd, B_EV_IO_WRITE ); 578 579 if (now) { 580 g_free(irc->sendbuffer); 581 irc->sendbuffer = g_strdup("\r\n"); 582 } 583 irc_vawrite(temp->data, format, params); 584 if (now) { 585 bitlbee_io_current_client_write(irc, irc->fd, B_EV_IO_WRITE); 592 586 } 593 587 temp = temp->next; 594 588 } 595 596 va_end( params);589 590 va_end(params); 597 591 return; 598 } 599 600 void irc_vawrite( irc_t *irc, char *format, va_list params)592 } 593 594 void irc_vawrite(irc_t *irc, char *format, va_list params) 601 595 { 602 596 int size; 603 char line[IRC_MAX_LINE +1];604 597 char line[IRC_MAX_LINE + 1]; 598 605 599 /* Don't try to write anything new anymore when shutting down. */ 606 if ( irc->status & USTATUS_SHUTDOWN )600 if (irc->status & USTATUS_SHUTDOWN) { 607 601 return; 608 609 memset( line, 0, sizeof( line ) ); 610 g_vsnprintf( line, IRC_MAX_LINE - 2, format, params);611 strip_newlines( line);612 613 if( irc->oconv != (GIConv) -1 ) 614 {602 } 603 604 memset(line, 0, sizeof(line)); 605 g_vsnprintf(line, IRC_MAX_LINE - 2, format, params); 606 strip_newlines(line); 607 608 if (irc->oconv != (GIConv) - 1) { 615 609 gsize bytes_read, bytes_written; 616 610 char *conv; 617 618 conv = g_convert_with_iconv( line, -1, irc->oconv, 619 &bytes_read, &bytes_written, NULL ); 620 621 if( bytes_read == strlen( line ) ) 622 strncpy( line, conv, IRC_MAX_LINE - 2 ); 623 624 g_free( conv ); 625 } 626 g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 ); 627 628 if( irc->sendbuffer != NULL ) 629 { 630 size = strlen( irc->sendbuffer ) + strlen( line ); 631 irc->sendbuffer = g_renew ( char, irc->sendbuffer, size + 1 ); 632 strcpy( ( irc->sendbuffer + strlen( irc->sendbuffer ) ), line ); 633 } 634 else 635 { 611 612 conv = g_convert_with_iconv(line, -1, irc->oconv, 613 &bytes_read, &bytes_written, NULL); 614 615 if (bytes_read == strlen(line)) { 616 strncpy(line, conv, IRC_MAX_LINE - 2); 617 } 618 619 g_free(conv); 620 } 621 g_strlcat(line, "\r\n", IRC_MAX_LINE + 1); 622 623 if (irc->sendbuffer != NULL) { 624 size = strlen(irc->sendbuffer) + strlen(line); 625 irc->sendbuffer = g_renew(char, irc->sendbuffer, size + 1); 626 strcpy((irc->sendbuffer + strlen(irc->sendbuffer)), line); 627 } else { 636 628 irc->sendbuffer = g_strdup(line); 637 629 } 638 639 if( irc->w_watch_source_id == 0 ) 640 { 630 631 if (irc->w_watch_source_id == 0) { 641 632 /* If the buffer is empty we can probably write, so call the write event handler 642 633 immediately. If it returns TRUE, it should be called again, so add the event to … … 645 636 /* Really can't be done as long as the code doesn't do error checking very well: 646 637 if( bitlbee_io_current_client_write( irc, irc->fd, B_EV_IO_WRITE ) ) */ 647 638 648 639 /* So just always do it via the event handler. */ 649 irc->w_watch_source_id = b_input_add( irc->fd, B_EV_IO_WRITE, bitlbee_io_current_client_write, irc);650 } 651 640 irc->w_watch_source_id = b_input_add(irc->fd, B_EV_IO_WRITE, bitlbee_io_current_client_write, irc); 641 } 642 652 643 return; 653 644 } … … 655 646 /* Flush sendbuffer if you can. If it fails, fail silently and let some 656 647 I/O event handler clean up. */ 657 void irc_flush( irc_t *irc)648 void irc_flush(irc_t *irc) 658 649 { 659 650 ssize_t n; 660 651 size_t len; 661 662 if ( irc->sendbuffer == NULL )652 653 if (irc->sendbuffer == NULL) { 663 654 return; 664 665 len = strlen( irc->sendbuffer ); 666 if( ( n = send( irc->fd, irc->sendbuffer, len, 0 ) ) == len )667 {668 g_free( irc->sendbuffer);655 } 656 657 len = strlen(irc->sendbuffer); 658 if ((n = send(irc->fd, irc->sendbuffer, len, 0)) == len) { 659 g_free(irc->sendbuffer); 669 660 irc->sendbuffer = NULL; 670 671 b_event_remove( irc->w_watch_source_id);661 662 b_event_remove(irc->w_watch_source_id); 672 663 irc->w_watch_source_id = 0; 673 } 674 else if( n > 0 ) 675 { 676 char *s = g_strdup( irc->sendbuffer + n ); 677 g_free( irc->sendbuffer ); 664 } else if (n > 0) { 665 char *s = g_strdup(irc->sendbuffer + n); 666 g_free(irc->sendbuffer); 678 667 irc->sendbuffer = s; 679 668 } … … 685 674 /* Meant for takeover functionality. Transfer an IRC connection to a different 686 675 socket. */ 687 void irc_switch_fd( irc_t *irc, int fd ) 688 { 689 irc_write( irc, "ERROR :Transferring session to a new connection" ); 690 irc_flush( irc ); /* Write it now or forget about it forever. */ 691 692 if( irc->sendbuffer ) 693 { 694 b_event_remove( irc->w_watch_source_id ); 676 void irc_switch_fd(irc_t *irc, int fd) 677 { 678 irc_write(irc, "ERROR :Transferring session to a new connection"); 679 irc_flush(irc); /* Write it now or forget about it forever. */ 680 681 if (irc->sendbuffer) { 682 b_event_remove(irc->w_watch_source_id); 695 683 irc->w_watch_source_id = 0; 696 g_free( irc->sendbuffer);684 g_free(irc->sendbuffer); 697 685 irc->sendbuffer = NULL; 698 686 } 699 700 b_event_remove( irc->r_watch_source_id);701 closesocket( irc->fd);687 688 b_event_remove(irc->r_watch_source_id); 689 closesocket(irc->fd); 702 690 irc->fd = fd; 703 irc->r_watch_source_id = b_input_add( irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc);704 } 705 706 void irc_sync( irc_t *irc)691 irc->r_watch_source_id = b_input_add(irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc); 692 } 693 694 void irc_sync(irc_t *irc) 707 695 { 708 696 GSList *l; 709 710 irc_write( irc, ":%s!%s@%s MODE %s :+%s", irc->user->nick, 711 irc->user->user, irc->user->host, irc->user->nick, 712 irc->umode ); 713 714 for( l = irc->channels; l; l = l->next ) 715 { 697 698 irc_write(irc, ":%s!%s@%s MODE %s :+%s", irc->user->nick, 699 irc->user->user, irc->user->host, irc->user->nick, 700 irc->umode); 701 702 for (l = irc->channels; l; l = l->next) { 716 703 irc_channel_t *ic = l->data; 717 if( ic->flags & IRC_CHANNEL_JOINED ) 718 irc_send_join( ic, irc->user ); 719 } 720 704 if (ic->flags & IRC_CHANNEL_JOINED) { 705 irc_send_join(ic, irc->user); 706 } 707 } 708 721 709 /* We may be waiting for a PONG from the previous client connection. */ 722 710 irc->pinging = FALSE; 723 711 } 724 712 725 void irc_desync( irc_t *irc)713 void irc_desync(irc_t *irc) 726 714 { 727 715 GSList *l; 728 729 for( l = irc->channels; l; l = l->next ) 730 irc_channel_del_user( l->data, irc->user, IRC_CDU_KICK, 731 "Switching to old session" ); 732 733 irc_write( irc, ":%s!%s@%s MODE %s :-%s", irc->user->nick, 734 irc->user->user, irc->user->host, irc->user->nick, 735 irc->umode ); 736 } 737 738 int irc_check_login( irc_t *irc ) 739 { 740 if( irc->user->user && irc->user->nick ) 741 { 742 if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) ) 743 { 744 irc_send_num( irc, 464, ":This server is password-protected." ); 716 717 for (l = irc->channels; l; l = l->next) { 718 irc_channel_del_user(l->data, irc->user, IRC_CDU_KICK, 719 "Switching to old session"); 720 } 721 722 irc_write(irc, ":%s!%s@%s MODE %s :-%s", irc->user->nick, 723 irc->user->user, irc->user->host, irc->user->nick, 724 irc->umode); 725 } 726 727 int irc_check_login(irc_t *irc) 728 { 729 if (irc->user->user && irc->user->nick) { 730 if (global.conf->authmode == AUTHMODE_CLOSED && !(irc->status & USTATUS_AUTHORIZED)) { 731 irc_send_num(irc, 464, ":This server is password-protected."); 745 732 return 0; 746 } 747 else 748 { 733 } else { 749 734 irc_channel_t *ic; 750 735 irc_user_t *iu = irc->user; 751 752 irc->user = irc_user_new( irc, iu->nick);736 737 irc->user = irc_user_new(irc, iu->nick); 753 738 irc->user->user = iu->user; 754 739 irc->user->host = iu->host; 755 740 irc->user->fullname = iu->fullname; 756 741 irc->user->f = &irc_user_self_funcs; 757 g_free( iu->nick ); 758 g_free( iu ); 759 760 if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) 761 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname ); 762 742 g_free(iu->nick); 743 g_free(iu); 744 745 if (global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON) { 746 ipc_to_master_str("CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, 747 irc->user->fullname); 748 } 749 763 750 irc->status |= USTATUS_LOGGED_IN; 764 765 irc_send_login( irc);766 751 752 irc_send_login(irc); 753 767 754 irc->umode[0] = '\0'; 768 irc_umode_set( irc, "+" UMODE, TRUE);769 770 ic = irc->default_channel = irc_channel_new( irc, ROOT_CHAN);771 irc_channel_set_topic( ic, CONTROL_TOPIC, irc->root);772 set_setstr( &ic->set, "auto_join", "true");773 irc_channel_auto_joins( irc, NULL);774 755 irc_umode_set(irc, "+" UMODE, TRUE); 756 757 ic = irc->default_channel = irc_channel_new(irc, ROOT_CHAN); 758 irc_channel_set_topic(ic, CONTROL_TOPIC, irc->root); 759 set_setstr(&ic->set, "auto_join", "true"); 760 irc_channel_auto_joins(irc, NULL); 761 775 762 irc->root->last_channel = irc->default_channel; 776 777 irc_rootmsg( 778 779 780 781 782 783 "\x02identify\x02 command to identify yourself.");784 763 764 irc_rootmsg(irc, 765 "Welcome to the BitlBee gateway!\n\n" 766 "If you've never used BitlBee before, please do read the help " 767 "information using the \x02help\x02 command. Lots of FAQs are " 768 "answered there.\n" 769 "If you already have an account on this server, just use the " 770 "\x02identify\x02 command to identify yourself."); 771 785 772 /* This is for bug #209 (use PASS to identify to NickServ). */ 786 if( irc->password != NULL ) 787 { 788 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL }; 789 790 irc_setpass( irc, NULL ); 791 root_command( irc, send_cmd ); 792 g_free( send_cmd[1] ); 793 } 794 773 if (irc->password != NULL) { 774 char *send_cmd[] = { "identify", g_strdup(irc->password), NULL }; 775 776 irc_setpass(irc, NULL); 777 root_command(irc, send_cmd); 778 g_free(send_cmd[1]); 779 } 780 795 781 return 1; 796 782 } 797 } 798 else 799 { 783 } else { 800 784 /* More information needed. */ 801 785 return 0; … … 805 789 /* TODO: This is a mess, but this function is a bit too complicated to be 806 790 converted to something more generic. */ 807 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv)791 void irc_umode_set(irc_t *irc, const char *s, gboolean allow_priv) 808 792 { 809 793 /* allow_priv: Set to 0 if s contains user input, 1 if you want … … 814 798 char changes[512], st2 = 2; 815 799 char badflag = 0; 816 817 memset( m, 0, sizeof( m ));818 800 801 memset(m, 0, sizeof(m)); 802 819 803 /* Keep track of which modes are enabled in this array. */ 820 for( t = irc->umode; *t; t ++ ) 821 if( *t < sizeof( m ) ) 822 m[(int)*t] = 1; 823 804 for (t = irc->umode; *t; t++) { 805 if (*t < sizeof(m)) { 806 m[(int) *t] = 1; 807 } 808 } 809 824 810 i = 0; 825 for( t = s; *t && i < sizeof( changes ) - 3; t ++ ) 826 { 827 if( *t == '+' || *t == '-' ) 811 for (t = s; *t && i < sizeof(changes) - 3; t++) { 812 if (*t == '+' || *t == '-') { 828 813 st = *t == '+'; 829 else if( ( st == 0 && ( !strchr( UMODES_KEEP, *t ) || allow_priv ) ) || 830 ( st == 1 && strchr( UMODES, *t ) ) || 831 ( st == 1 && allow_priv && strchr( UMODES_PRIV, *t ) ) ) 832 { 833 if( m[(int)*t] != st) 834 { 814 } else if ((st == 0 && (!strchr(UMODES_KEEP, *t) || allow_priv)) || 815 (st == 1 && strchr(UMODES, *t)) || 816 (st == 1 && allow_priv && strchr(UMODES_PRIV, *t))) { 817 if (m[(int) *t] != st) { 835 818 /* If we're actually making a change, remember this 836 819 for the response. */ 837 if ( st != st2 )820 if (st != st2) { 838 821 st2 = st, changes[i++] = st ? '+' : '-'; 822 } 839 823 changes[i++] = *t; 840 824 } 841 m[(int)*t] = st; 842 } 843 else 825 m[(int) *t] = st; 826 } else { 844 827 badflag = 1; 828 } 845 829 } 846 830 changes[i] = '\0'; 847 831 848 832 /* Convert the m array back into an umode string. */ 849 memset( irc->umode, 0, sizeof( irc->umode ));850 for ( i = 'A'; i <= 'z' && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )851 if ( m[i] )833 memset(irc->umode, 0, sizeof(irc->umode)); 834 for (i = 'A'; i <= 'z' && strlen(irc->umode) < (sizeof(irc->umode) - 1); i++) { 835 if (m[i]) { 852 836 irc->umode[strlen(irc->umode)] = i; 853 854 if( badflag ) 855 irc_send_num( irc, 501, ":Unknown MODE flag" ); 856 if( *changes ) 857 irc_write( irc, ":%s!%s@%s MODE %s :%s", irc->user->nick, 858 irc->user->user, irc->user->host, irc->user->nick, 859 changes ); 837 } 838 } 839 840 if (badflag) { 841 irc_send_num(irc, 501, ":Unknown MODE flag"); 842 } 843 if (*changes) { 844 irc_write(irc, ":%s!%s@%s MODE %s :%s", irc->user->nick, 845 irc->user->user, irc->user->host, irc->user->nick, 846 changes); 847 } 860 848 } 861 849 … … 864 852 pongs from the user. When not connected yet, we don't ping but drop the 865 853 connection when the user fails to connect in IRC_LOGIN_TIMEOUT secs. */ 866 static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond)854 static gboolean irc_userping(gpointer _irc, gint fd, b_input_condition cond) 867 855 { 868 856 double now = gettime(); 869 857 irc_t *irc = _irc; 870 858 int fail = 0; 871 872 if( !( irc->status & USTATUS_LOGGED_IN ) ) 873 { 874 if( now > ( irc->last_pong + IRC_LOGIN_TIMEOUT ) ) 859 860 if (!(irc->status & USTATUS_LOGGED_IN)) { 861 if (now > (irc->last_pong + IRC_LOGIN_TIMEOUT)) { 875 862 fail = now - irc->last_pong; 876 } 877 else 878 { 879 if( now > ( irc->last_pong + global.conf->ping_timeout ) ) 880 { 863 } 864 } else { 865 if (now > (irc->last_pong + global.conf->ping_timeout)) { 881 866 fail = now - irc->last_pong; 882 } 883 else 884 { 885 irc_write( irc, "PING :%s", IRC_PING_STRING ); 886 } 887 } 888 889 if( fail > 0 ) 890 { 891 irc_abort( irc, 0, "Ping Timeout: %d seconds", fail ); 867 } else { 868 irc_write(irc, "PING :%s", IRC_PING_STRING); 869 } 870 } 871 872 if (fail > 0) { 873 irc_abort(irc, 0, "Ping Timeout: %d seconds", fail); 892 874 return FALSE; 893 875 } 894 876 895 877 return TRUE; 896 878 } 897 879 898 static char *set_eval_charset( set_t *set, char *value)899 { 900 irc_t *irc = (irc_t *) set->data;880 static char *set_eval_charset(set_t *set, char *value) 881 { 882 irc_t *irc = (irc_t *) set->data; 901 883 char *test; 902 884 gsize test_bytes = 0; 903 885 GIConv ic, oc; 904 886 905 if ( g_strcasecmp( value, "none" ) == 0 )906 value = g_strdup( "utf-8");907 908 if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 ) 909 {887 if (g_strcasecmp(value, "none") == 0) { 888 value = g_strdup("utf-8"); 889 } 890 891 if ((oc = g_iconv_open(value, "utf-8")) == (GIConv) - 1) { 910 892 return NULL; 911 893 } 912 894 913 895 /* Do a test iconv to see if the user picked an IRC-compatible 914 896 charset (for example utf-16 goes *horribly* wrong). */ 915 if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL || 916 test_bytes > 1 ) 917 { 918 g_free( test ); 919 g_iconv_close( oc ); 920 irc_rootmsg( irc, "Unsupported character set: The IRC protocol " 921 "only supports 8-bit character sets." ); 897 if ((test = g_convert_with_iconv(" ", 1, oc, NULL, &test_bytes, NULL)) == NULL || 898 test_bytes > 1) { 899 g_free(test); 900 g_iconv_close(oc); 901 irc_rootmsg(irc, "Unsupported character set: The IRC protocol " 902 "only supports 8-bit character sets."); 922 903 return NULL; 923 904 } 924 g_free( test ); 925 926 if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 ) 927 { 928 g_iconv_close( oc ); 905 g_free(test); 906 907 if ((ic = g_iconv_open("utf-8", value)) == (GIConv) - 1) { 908 g_iconv_close(oc); 929 909 return NULL; 930 910 } 931 932 if( irc->iconv != (GIConv) -1 ) 933 g_iconv_close( irc->iconv ); 934 if( irc->oconv != (GIConv) -1 ) 935 g_iconv_close( irc->oconv ); 936 911 912 if (irc->iconv != (GIConv) - 1) { 913 g_iconv_close(irc->iconv); 914 } 915 if (irc->oconv != (GIConv) - 1) { 916 g_iconv_close(irc->oconv); 917 } 918 937 919 irc->iconv = ic; 938 920 irc->oconv = oc; … … 943 925 /* Mostly meant for upgrades. If one of these is set to the non-default, 944 926 set show_users of all channels to something with the same effect. */ 945 static char *set_eval_bw_compat( set_t *set, char *value)927 static char *set_eval_bw_compat(set_t *set, char *value) 946 928 { 947 929 irc_t *irc = set->data; 948 930 char *val; 949 931 GSList *l; 950 951 irc_rootmsg( 952 "channel setting instead.", set->key);953 954 if ( strcmp( set->key, "away_devoice" ) == 0 && !bool2int( value ) )932 933 irc_rootmsg(irc, "Setting `%s' is obsolete, use the `show_users' " 934 "channel setting instead.", set->key); 935 936 if (strcmp(set->key, "away_devoice") == 0 && !bool2int(value)) { 955 937 val = "online,special%,away"; 956 else if( strcmp( set->key, "show_offline" ) == 0 && bool2int( value ) )938 } else if (strcmp(set->key, "show_offline") == 0 && bool2int(value)) { 957 939 val = "online@,special%,away+,offline"; 958 else940 } else { 959 941 val = "online+,special%,away"; 960 961 for( l = irc->channels; l; l = l->next ) 962 {942 } 943 944 for (l = irc->channels; l; l = l->next) { 963 945 irc_channel_t *ic = l->data; 964 946 /* No need to check channel type, if the setting doesn't exist it 965 947 will just be ignored. */ 966 set_setstr( &ic->set, "show_users", val);967 } 968 948 set_setstr(&ic->set, "show_users", val); 949 } 950 969 951 return SET_INVALID; 970 952 } 971 953 972 static char *set_eval_utf8_nicks( set_t *set, char *value)954 static char *set_eval_utf8_nicks(set_t *set, char *value) 973 955 { 974 956 irc_t *irc = set->data; 975 gboolean val = bool2int( value);976 957 gboolean val = bool2int(value); 958 977 959 /* Do *NOT* unset this flag in the middle of a session. There will 978 960 be UTF-8 nicks around already so if we suddenly disable support 979 961 for them, various functions might behave strangely. */ 980 if ( val )962 if (val) { 981 963 irc->status |= IRC_UTF8_NICKS; 982 else if( irc->status & IRC_UTF8_NICKS ) 983 irc_rootmsg( irc, "You need to reconnect to BitlBee for this " 984 "change to take effect." ); 985 986 return set_eval_bool( set, value ); 987 } 988 989 void register_irc_plugin( const struct irc_plugin *p ) 990 { 991 irc_plugins = g_slist_prepend( irc_plugins, (gpointer) p ); 992 } 964 } else if (irc->status & IRC_UTF8_NICKS) { 965 irc_rootmsg(irc, "You need to reconnect to BitlBee for this " 966 "change to take effect."); 967 } 968 969 return set_eval_bool(set, value); 970 } 971 972 void register_irc_plugin(const struct irc_plugin *p) 973 { 974 irc_plugins = g_slist_prepend(irc_plugins, (gpointer) p); 975 }
Note: See TracChangeset
for help on using the changeset viewer.