Mercurial > pidgin
comparison src/protocols/irc/irc.c @ 10365:d2f999970f91
[gaim-migrate @ 11583]
SSL for IRC ... thanks to datallah
committer: Tailor Script <tailor@pidgin.im>
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Tue, 14 Dec 2004 05:16:40 +0000 |
parents | 357d4fa1bfbe |
children | 3e4ecbdf8d0a |
comparison
equal
deleted
inserted
replaced
10364:db5e8c8b2abb | 10365:d2f999970f91 |
---|---|
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; |
322 | 390 |
323 if (gc->inpa) | 391 if (gc->inpa) |
324 gaim_input_remove(gc->inpa); | 392 gaim_input_remove(gc->inpa); |
325 | 393 |
326 g_free(irc->inbuf); | 394 g_free(irc->inbuf); |
327 close(irc->fd); | 395 if (irc->gsc) { |
396 gaim_ssl_close(irc->gsc); | |
397 } else if (irc->fd > 0) { | |
398 close(irc->fd); | |
399 } | |
328 if (irc->timer) | 400 if (irc->timer) |
329 gaim_timeout_remove(irc->timer); | 401 gaim_timeout_remove(irc->timer); |
330 g_hash_table_destroy(irc->cmds); | 402 g_hash_table_destroy(irc->cmds); |
331 g_hash_table_destroy(irc->msgs); | 403 g_hash_table_destroy(irc->msgs); |
332 if (irc->motd) | 404 if (irc->motd) |
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 |