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