| 43 static void irc_blist_emblems(GaimBuddy *b, const char **se, const char **sw, const char **nw, const char **ne); |
43 static void irc_blist_emblems(GaimBuddy *b, const char **se, const char **sw, const char **nw, const char **ne); |
| 44 static GList *irc_status_types(GaimAccount *account); |
44 static GList *irc_status_types(GaimAccount *account); |
| 45 static GList *irc_actions(GaimPlugin *plugin, gpointer context); |
45 static GList *irc_actions(GaimPlugin *plugin, gpointer context); |
| 46 /* static GList *irc_chat_info(GaimConnection *gc); */ |
46 /* static GList *irc_chat_info(GaimConnection *gc); */ |
| 47 static void irc_login(GaimAccount *account); |
47 static void irc_login(GaimAccount *account); |
| |
48 static void irc_login_cb_ssl(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond); |
| 48 static void irc_login_cb(gpointer data, gint source, GaimInputCondition cond); |
49 static void irc_login_cb(gpointer data, gint source, GaimInputCondition cond); |
| |
50 static void irc_ssl_connect_failure(GaimSslConnection *gsc, GaimSslErrorType error, gpointer data); |
| 49 static void irc_close(GaimConnection *gc); |
51 static void irc_close(GaimConnection *gc); |
| 50 static int irc_im_send(GaimConnection *gc, const char *who, const char *what, GaimConvImFlags flags); |
52 static int irc_im_send(GaimConnection *gc, const char *who, const char *what, GaimConvImFlags flags); |
| 51 static int irc_chat_send(GaimConnection *gc, int id, const char *what); |
53 static int irc_chat_send(GaimConnection *gc, int id, const char *what); |
| 52 static void irc_chat_join (GaimConnection *gc, GHashTable *data); |
54 static void irc_chat_join (GaimConnection *gc, GHashTable *data); |
| 53 static void irc_input_cb(gpointer data, gint source, GaimInputCondition cond); |
55 static void irc_input_cb(gpointer data, gint source, GaimInputCondition cond); |
| |
56 static void irc_input_cb_ssl(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond); |
| 54 |
57 |
| 55 static guint irc_nick_hash(const char *nick); |
58 static guint irc_nick_hash(const char *nick); |
| 56 static gboolean irc_nick_equal(const char *nick1, const char *nick2); |
59 static gboolean irc_nick_equal(const char *nick1, const char *nick2); |
| 57 static void irc_buddy_free(struct irc_buddy *ib); |
60 static void irc_buddy_free(struct irc_buddy *ib); |
| 58 |
61 |
| 82 |
85 |
| 83 int irc_send(struct irc_conn *irc, const char *buf) |
86 int irc_send(struct irc_conn *irc, const char *buf) |
| 84 { |
87 { |
| 85 int ret; |
88 int ret; |
| 86 |
89 |
| 87 if (irc->fd < 0) |
90 if (irc->gsc) { |
| 88 return -1; |
91 ret = gaim_ssl_write(irc->gsc, buf, strlen(buf)); |
| 89 |
92 } else { |
| 90 /* gaim_debug(GAIM_DEBUG_MISC, "irc", "sent: %s", buf); */ |
93 if (irc->fd < 0) |
| 91 if ((ret = write(irc->fd, buf, strlen(buf))) < 0) |
94 return -1; |
| |
95 ret = write(irc->fd, buf, strlen(buf)); |
| |
96 } |
| |
97 |
| |
98 /* gaim_debug(GAIM_DEBUG_MISC, "irc", "sent%s: %s", |
| |
99 irc->gsc ? " (ssl)" : "", buf); */ |
| |
100 if (ret < 0) { |
| 92 gaim_connection_error(gaim_account_get_connection(irc->account), |
101 gaim_connection_error(gaim_account_get_connection(irc->account), |
| 93 _("Server has disconnected")); |
102 _("Server has disconnected")); |
| |
103 } |
| 94 |
104 |
| 95 return ret; |
105 return ret; |
| 96 } |
106 } |
| 97 |
107 |
| 98 /* XXX I don't like messing directly with these buddies */ |
108 /* XXX I don't like messing directly with these buddies */ |
| 248 |
258 |
| 249 buf = g_strdup_printf(_("Logging in: %s"), username); |
259 buf = g_strdup_printf(_("Logging in: %s"), username); |
| 250 gaim_connection_update_progress(gc, buf, 1, 2); |
260 gaim_connection_update_progress(gc, buf, 1, 2); |
| 251 g_free(buf); |
261 g_free(buf); |
| 252 |
262 |
| 253 err = gaim_proxy_connect(account, irc->server, |
263 if (gaim_account_get_bool(account, "ssl", FALSE)) { |
| |
264 if (gaim_ssl_is_supported()) { |
| |
265 irc->gsc = gaim_ssl_connect(account, irc->server, |
| |
266 gaim_account_get_int(account, "port", IRC_DEFAULT_SSL_PORT), |
| |
267 irc_login_cb_ssl, irc_ssl_connect_failure, gc); |
| |
268 } else { |
| |
269 gaim_connection_error(gc, _("SSL support unavailable")); |
| |
270 } |
| |
271 } |
| |
272 |
| |
273 if (!irc->gsc) { |
| |
274 |
| |
275 err = gaim_proxy_connect(account, irc->server, |
| 254 gaim_account_get_int(account, "port", IRC_DEFAULT_PORT), |
276 gaim_account_get_int(account, "port", IRC_DEFAULT_PORT), |
| 255 irc_login_cb, gc); |
277 irc_login_cb, gc); |
| 256 |
278 |
| 257 if (err || !account->gc) { |
279 if (err || !account->gc) { |
| 258 gaim_connection_error(gc, _("Couldn't create socket")); |
280 gaim_connection_error(gc, _("Couldn't create socket")); |
| 259 return; |
281 return; |
| 260 } |
282 } |
| 261 } |
283 } |
| 262 |
284 } |
| 263 static void irc_login_cb(gpointer data, gint source, GaimInputCondition cond) |
285 |
| 264 { |
286 static gboolean do_login(GaimConnection *gc) { |
| 265 GaimConnection *gc = data; |
287 char *buf; |
| 266 struct irc_conn *irc = gc->proto_data; |
|
| 267 char hostname[256]; |
288 char hostname[256]; |
| 268 char *buf; |
|
| 269 const char *username, *realname; |
289 const char *username, *realname; |
| 270 GList *connections = gaim_connections_get_all(); |
290 struct irc_conn *irc = gc->proto_data; |
| 271 |
|
| 272 if (source < 0) { |
|
| 273 gaim_connection_error(gc, _("Couldn't connect to host")); |
|
| 274 return; |
|
| 275 } |
|
| 276 |
|
| 277 if (!g_list_find(connections, gc)) { |
|
| 278 close(source); |
|
| 279 return; |
|
| 280 } |
|
| 281 |
|
| 282 irc->fd = source; |
|
| 283 |
291 |
| 284 if (gc->account->password && *gc->account->password) { |
292 if (gc->account->password && *gc->account->password) { |
| 285 buf = irc_format(irc, "vv", "PASS", gc->account->password); |
293 buf = irc_format(irc, "vv", "PASS", gc->account->password); |
| 286 if (irc_send(irc, buf) < 0) { |
294 if (irc_send(irc, buf) < 0) { |
| 287 gaim_connection_error(gc, "Error sending password"); |
295 gaim_connection_error(gc, "Error sending password"); |
| 288 return; |
296 return FALSE; |
| 289 } |
297 } |
| 290 g_free(buf); |
298 g_free(buf); |
| 291 } |
299 } |
| 292 |
300 |
| 293 gethostname(hostname, sizeof(hostname)); |
301 gethostname(hostname, sizeof(hostname)); |
| 296 realname = gaim_account_get_string(irc->account, "realname", ""); |
304 realname = gaim_account_get_string(irc->account, "realname", ""); |
| 297 buf = irc_format(irc, "vvvv:", "USER", strlen(username) ? username : g_get_user_name(), hostname, irc->server, |
305 buf = irc_format(irc, "vvvv:", "USER", strlen(username) ? username : g_get_user_name(), hostname, irc->server, |
| 298 strlen(realname) ? realname : IRC_DEFAULT_ALIAS); |
306 strlen(realname) ? realname : IRC_DEFAULT_ALIAS); |
| 299 if (irc_send(irc, buf) < 0) { |
307 if (irc_send(irc, buf) < 0) { |
| 300 gaim_connection_error(gc, "Error registering with server"); |
308 gaim_connection_error(gc, "Error registering with server"); |
| 301 return; |
309 return FALSE; |
| 302 } |
310 } |
| 303 g_free(buf); |
311 g_free(buf); |
| 304 buf = irc_format(irc, "vn", "NICK", gaim_connection_get_display_name(gc)); |
312 buf = irc_format(irc, "vn", "NICK", gaim_connection_get_display_name(gc)); |
| 305 if (irc_send(irc, buf) < 0) { |
313 if (irc_send(irc, buf) < 0) { |
| 306 gaim_connection_error(gc, "Error sending nickname"); |
314 gaim_connection_error(gc, "Error sending nickname"); |
| 307 return; |
315 return FALSE; |
| 308 } |
316 } |
| 309 g_free(buf); |
317 g_free(buf); |
| 310 |
318 |
| 311 gc->inpa = gaim_input_add(irc->fd, GAIM_INPUT_READ, irc_input_cb, gc); |
319 return TRUE; |
| |
320 } |
| |
321 |
| |
322 static void irc_login_cb_ssl(gpointer data, GaimSslConnection *gsc, |
| |
323 GaimInputCondition cond) |
| |
324 { |
| |
325 GaimConnection *gc = data; |
| |
326 struct irc_conn *irc = gc->proto_data; |
| |
327 |
| |
328 if(!g_list_find(gaim_connections_get_all(), gc)) { |
| |
329 gaim_ssl_close(gsc); |
| |
330 return; |
| |
331 } |
| |
332 |
| |
333 irc->gsc = gsc; |
| |
334 |
| |
335 if (do_login(gc)) { |
| |
336 gaim_ssl_input_add(gsc, irc_input_cb_ssl, gc); |
| |
337 } |
| |
338 } |
| |
339 |
| |
340 static void irc_login_cb(gpointer data, gint source, GaimInputCondition cond) |
| |
341 { |
| |
342 GaimConnection *gc = data; |
| |
343 struct irc_conn *irc = gc->proto_data; |
| |
344 GList *connections = gaim_connections_get_all(); |
| |
345 |
| |
346 if (source < 0) { |
| |
347 gaim_connection_error(gc, _("Couldn't connect to host")); |
| |
348 return; |
| |
349 } |
| |
350 |
| |
351 if (!g_list_find(connections, gc)) { |
| |
352 close(source); |
| |
353 return; |
| |
354 } |
| |
355 |
| |
356 irc->fd = source; |
| |
357 |
| |
358 if (do_login(gc)) { |
| |
359 gc->inpa = gaim_input_add(irc->fd, GAIM_INPUT_READ, irc_input_cb, gc); |
| |
360 } |
| |
361 } |
| |
362 |
| |
363 static void |
| |
364 irc_ssl_connect_failure(GaimSslConnection *gsc, GaimSslErrorType error, |
| |
365 gpointer data) |
| |
366 { |
| |
367 GaimConnection *gc = data; |
| |
368 struct irc_conn *irc = gc->proto_data; |
| |
369 |
| |
370 switch(error) { |
| |
371 case GAIM_SSL_CONNECT_FAILED: |
| |
372 gaim_connection_error(gc, _("Connection Failed")); |
| |
373 break; |
| |
374 case GAIM_SSL_HANDSHAKE_FAILED: |
| |
375 gaim_connection_error(gc, _("SSL Handshake Failed")); |
| |
376 break; |
| |
377 } |
| |
378 |
| |
379 irc->gsc = NULL; |
| 312 } |
380 } |
| 313 |
381 |
| 314 static void irc_close(GaimConnection *gc) |
382 static void irc_close(GaimConnection *gc) |
| 315 { |
383 { |
| 316 struct irc_conn *irc = gc->proto_data; |
384 struct irc_conn *irc = gc->proto_data; |
| 391 { |
463 { |
| 392 struct irc_conn *irc = (struct irc_conn *)gc->proto_data; |
464 struct irc_conn *irc = (struct irc_conn *)gc->proto_data; |
| 393 g_hash_table_remove(irc->buddies, buddy->name); |
465 g_hash_table_remove(irc->buddies, buddy->name); |
| 394 } |
466 } |
| 395 |
467 |
| 396 static void irc_input_cb(gpointer data, gint source, GaimInputCondition cond) |
468 static void read_input(struct irc_conn *irc, int len) |
| 397 { |
469 { |
| 398 GaimConnection *gc = data; |
|
| 399 struct irc_conn *irc = gc->proto_data; |
|
| 400 char *cur, *end; |
470 char *cur, *end; |
| 401 int len; |
|
| 402 |
|
| 403 if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { |
|
| 404 irc->inbuflen += IRC_INITIAL_BUFSIZE; |
|
| 405 irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); |
|
| 406 } |
|
| 407 |
|
| 408 if ((len = read(irc->fd, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1)) < 0) { |
|
| 409 gaim_connection_error(gc, _("Read error")); |
|
| 410 return; |
|
| 411 } else if (len == 0) { |
|
| 412 gaim_connection_error(gc, _("Server has disconnected")); |
|
| 413 return; |
|
| 414 } |
|
| 415 |
471 |
| 416 irc->inbufused += len; |
472 irc->inbufused += len; |
| 417 irc->inbuf[irc->inbufused] = '\0'; |
473 irc->inbuf[irc->inbufused] = '\0'; |
| 418 |
474 |
| 419 cur = irc->inbuf; |
475 cur = irc->inbuf; |
| 428 irc->inbufused -= (cur - irc->inbuf); |
484 irc->inbufused -= (cur - irc->inbuf); |
| 429 memmove(irc->inbuf, cur, irc->inbufused); |
485 memmove(irc->inbuf, cur, irc->inbufused); |
| 430 } else { |
486 } else { |
| 431 irc->inbufused = 0; |
487 irc->inbufused = 0; |
| 432 } |
488 } |
| |
489 } |
| |
490 |
| |
491 static void irc_input_cb_ssl(gpointer data, GaimSslConnection *gsc, |
| |
492 GaimInputCondition cond) |
| |
493 { |
| |
494 |
| |
495 GaimConnection *gc = data; |
| |
496 struct irc_conn *irc = gc->proto_data; |
| |
497 int len; |
| |
498 |
| |
499 if(!g_list_find(gaim_connections_get_all(), gc)) { |
| |
500 gaim_ssl_close(gsc); |
| |
501 return; |
| |
502 } |
| |
503 |
| |
504 if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { |
| |
505 irc->inbuflen += IRC_INITIAL_BUFSIZE; |
| |
506 irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); |
| |
507 } |
| |
508 |
| |
509 if ((len = gaim_ssl_read(gsc, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1)) < 0) { |
| |
510 gaim_connection_error(gc, _("Read error")); |
| |
511 return; |
| |
512 } else if (len == 0) { |
| |
513 gaim_connection_error(gc, _("Server has disconnected")); |
| |
514 return; |
| |
515 } |
| |
516 |
| |
517 read_input(irc, len); |
| |
518 } |
| |
519 |
| |
520 static void irc_input_cb(gpointer data, gint source, GaimInputCondition cond) |
| |
521 { |
| |
522 GaimConnection *gc = data; |
| |
523 struct irc_conn *irc = gc->proto_data; |
| |
524 int len; |
| |
525 |
| |
526 if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { |
| |
527 irc->inbuflen += IRC_INITIAL_BUFSIZE; |
| |
528 irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); |
| |
529 } |
| |
530 |
| |
531 if ((len = read(irc->fd, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1)) < 0) { |
| |
532 gaim_connection_error(gc, _("Read error")); |
| |
533 return; |
| |
534 } else if (len == 0) { |
| |
535 gaim_connection_error(gc, _("Server has disconnected")); |
| |
536 return; |
| |
537 } |
| |
538 |
| |
539 read_input(irc, len); |
| 433 } |
540 } |
| 434 |
541 |
| 435 static void irc_chat_join (GaimConnection *gc, GHashTable *data) |
542 static void irc_chat_join (GaimConnection *gc, GHashTable *data) |
| 436 { |
543 { |
| 437 struct irc_conn *irc = gc->proto_data; |
544 struct irc_conn *irc = gc->proto_data; |
| 704 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
811 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
| 705 |
812 |
| 706 option = gaim_account_option_string_new(_("Real name"), "realname", ""); |
813 option = gaim_account_option_string_new(_("Real name"), "realname", ""); |
| 707 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
814 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
| 708 |
815 |
| |
816 option = gaim_account_option_bool_new(_("Use SSL"), "ssl", FALSE); |
| |
817 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
| |
818 |
| 709 _irc_plugin = plugin; |
819 _irc_plugin = plugin; |
| 710 |
820 |
| 711 irc_register_commands(); |
821 irc_register_commands(); |
| 712 } |
822 } |
| 713 |
823 |