comparison src/protocols/irc/irc.c @ 3751:e25577506dec

[gaim-migrate @ 3889] from Jonas Birme' (birme): * CTCP PING now calculates with usec. * Some minor code cleanup. from Ethan Blanton (eblanton): This adds another option to IRC on a per-account basis that specifies the encoding one wishes to use for non-ASCII text. Like most of my recent patches, send-path is not well tested but receive path appears correct. With this patch, accented chars/etc. should work properly again over IRC. In addition, even IRC users in different locales should be able to communicate using non-ASCII character sets. :-) committer: Tailor Script <tailor@pidgin.im>
author Luke Schierer <lschiere@pidgin.im>
date Sat, 19 Oct 2002 05:04:58 +0000
parents 242e52b37a78
children fb519383a058
comparison
equal deleted inserted replaced
3750:ddd9e50e547a 3751:e25577506dec
53 #define IRC_BUF_LEN 4096 53 #define IRC_BUF_LEN 4096
54 #define PDIWORDS 32 54 #define PDIWORDS 32
55 55
56 #define USEROPT_SERV 0 56 #define USEROPT_SERV 0
57 #define USEROPT_PORT 1 57 #define USEROPT_PORT 1
58 #define USEROPT_CHARSET 2
58 59
59 /* for win32 compatability */ 60 /* for win32 compatability */
60 G_MODULE_IMPORT GSList *connections; 61 G_MODULE_IMPORT GSList *connections;
61 62
62 63
63 static void irc_start_chat(struct gaim_connection *gc, char *who); 64 /* Datastructs */
64 static void irc_ctcp_clientinfo(struct gaim_connection *gc, char *who);
65 static void irc_ctcp_userinfo(struct gaim_connection *gc, char *who);
66 static void irc_ctcp_version(struct gaim_connection *gc, char *who);
67 static void irc_ctcp_ping(struct gaim_connection *gc, char *who);
68
69 static void irc_send_privmsg(struct gaim_connection *gc, char *who, char *what);
70 static void irc_send_notice(struct gaim_connection *gc, char *who, char *what);
71
72 struct dcc_chat 65 struct dcc_chat
73 { 66 {
74 struct gaim_connection *gc; 67 struct gaim_connection *gc;
75 char ip_address[12]; 68 char ip_address[12];
76 int port; 69 int port;
92 int fd; 85 int fd;
93 int cur; 86 int cur;
94 struct gaim_connection *gc; 87 struct gaim_connection *gc;
95 }; 88 };
96 89
97 GSList *dcc_chat_list = NULL;
98
99 struct irc_data { 90 struct irc_data {
100 int fd; 91 int fd;
101 gboolean online; 92 gboolean online;
102 guint32 timer; 93 guint32 timer;
103 94
115 gboolean in_whois; 106 gboolean in_whois;
116 gboolean in_list; 107 gboolean in_list;
117 GString *liststr; 108 GString *liststr;
118 GSList *file_transfers; 109 GSList *file_transfers;
119 }; 110 };
111
112 /* Prototypes */
113 static void irc_start_chat(struct gaim_connection *gc, char *who);
114 static void irc_ctcp_clientinfo(struct gaim_connection *gc, char *who);
115 static void irc_ctcp_userinfo(struct gaim_connection *gc, char *who);
116 static void irc_ctcp_version(struct gaim_connection *gc, char *who);
117 static void irc_ctcp_ping(struct gaim_connection *gc, char *who);
118
119 static void irc_send_privmsg(struct gaim_connection *gc, char *who, char *what, gboolean fragment);
120 static void irc_send_notice(struct gaim_connection *gc, char *who, char *what);
121
122 static char *irc_send_convert(struct gaim_connection *gc, char *string, int maxlen, int *done);
123 static char *irc_recv_convert(struct gaim_connection *gc, char *string);
124 static void irc_parse_notice(struct gaim_connection *gc, char *nick, char *ex,
125 char *word[], char *word_eol[]);
126 static void irc_parse_join(struct gaim_connection *gc, char *nick,
127 char *word[], char *word_eol[]);
128 static gboolean irc_parse_part(struct gaim_connection *gc, char *nick, char *cmd,
129 char *word[], char *word_eol[]);
130 static void irc_parse_topic(struct gaim_connection *gc, char *nick,
131 char *word[], char *word_eol[]);
132
133 static void dcc_chat_cancel(struct dcc_chat *);
134
135 /* Global variables */
136 GSList *dcc_chat_list = NULL;
120 137
121 struct dcc_chat * 138 struct dcc_chat *
122 find_dcc_chat (struct gaim_connection *gc, char *nick) 139 find_dcc_chat (struct gaim_connection *gc, char *nick)
123 { 140 {
124 GSList *tmp; 141 GSList *tmp;
137 tmp = tmp->next; 154 tmp = tmp->next;
138 } 155 }
139 return NULL; 156 return NULL;
140 } 157 }
141 158
142 static int irc_write(int fd, char *data, int len) 159 static int
160 irc_write(int fd, char *data, int len)
143 { 161 {
144 debug_printf("IRC C: %s", data); 162 debug_printf("IRC C: %s", data);
145 return write(fd, data, len); 163 return write(fd, data, len);
146 } 164 }
147 165
148 static struct conversation *irc_find_chat(struct gaim_connection *gc, char *name) 166 static char *
167 irc_send_convert(struct gaim_connection *gc, char *string, int maxlen, int *done)
168 {
169 char *converted = g_malloc(maxlen + 1);
170 gchar *inptr = string, *outptr = converted;
171 int inleft = strlen(string), outleft = maxlen;
172 GIConv conv;
173
174 conv = g_iconv_open(gc->user->proto_opt[USEROPT_CHARSET], "UTF-8");
175 if (g_iconv(conv, &inptr, &inleft, &outptr, &outleft) == -1) {
176 debug_printf("IRC charset conversion error\n");
177 debug_printf("Sending as UTF-8 (this is a hack!)\n");
178 g_free(converted);
179 *done = maxlen;
180 return(g_strndup(string, maxlen));
181 }
182
183 *done = strlen(string) - inleft;
184 *outptr = '\0';
185 return(converted);
186 }
187
188 static char *
189 irc_recv_convert(struct gaim_connection *gc, char *string)
190 {
191 char *utf8;
192 GError *err = NULL;
193
194 utf8 = g_convert(string, strlen(string), "UTF-8",
195 gc->user->proto_opt[USEROPT_CHARSET], NULL, NULL, &err);
196 if (err) {
197 debug_printf("IRC recv conversion error: %s\n", err->message);
198 utf8 = g_strdup(_("(There was an error converting this message. Check the 'Encoding' option in the Account Editor)"));
199 }
200
201 return (utf8);
202 }
203
204 static struct conversation *
205 irc_find_chat(struct gaim_connection *gc, char *name)
149 { 206 {
150 GSList *bcs = gc->buddy_chats; 207 GSList *bcs = gc->buddy_chats;
151 208
152 while (bcs) { 209 while (bcs) {
153 struct conversation *b = bcs->data; 210 struct conversation *b = bcs->data;
156 bcs = bcs->next; 213 bcs = bcs->next;
157 } 214 }
158 return NULL; 215 return NULL;
159 } 216 }
160 217
161 static struct conversation *irc_find_chat_by_id(struct gaim_connection *gc, int id) 218 static struct conversation *
219 irc_find_chat_by_id(struct gaim_connection *gc, int id)
162 { 220 {
163 GSList *bcs = gc->buddy_chats; 221 GSList *bcs = gc->buddy_chats;
164 222
165 while (bcs) { 223 while (bcs) {
166 struct conversation *b = bcs->data; 224 struct conversation *b = bcs->data;
169 bcs = bcs->next; 227 bcs = bcs->next;
170 } 228 }
171 return NULL; 229 return NULL;
172 } 230 }
173 231
174 static void process_data_init(char *buf, char *cmd, char *word[], char *eol[], gboolean quotes) 232 static void
233 process_data_init(char *buf, char *cmd, char *word[], char *eol[], gboolean quotes)
175 { 234 {
176 int wordcount = 2; 235 int wordcount = 2;
177 gboolean space = FALSE; 236 gboolean space = FALSE;
178 gboolean quote = FALSE; 237 gboolean quote = FALSE;
179 int j = 0; 238 int j = 0;
221 } 280 }
222 cmd++; 281 cmd++;
223 } 282 }
224 } 283 }
225 284
226 static void handle_005(struct gaim_connection *gc, char *word[], char *word_eol[]) 285 static void
286 handle_005(struct gaim_connection *gc, char *word[], char *word_eol[])
227 { 287 {
228 int w = 4; 288 int w = 4;
229 struct irc_data *id = gc->proto_data; 289 struct irc_data *id = gc->proto_data;
230 290
231 while (w < PDIWORDS && *word[w]) { 291 while (w < PDIWORDS && *word[w]) {
248 } 308 }
249 w++; 309 w++;
250 } 310 }
251 } 311 }
252 312
253 static char *int_to_col(int c) 313 static char *
314 int_to_col(int c)
254 { 315 {
255 switch(c) { 316 switch(c) {
256 case 1: 317 case 1:
257 return "#ffffff"; 318 return "#ffffff";
258 case 2: 319 case 2:
286 default: 347 default:
287 return "#000000"; 348 return "#000000";
288 } 349 }
289 } 350 }
290 351
291 static GString *encode_html(char *msg) 352 static GString *
353 encode_html(char *msg)
292 { 354 {
293 GString *str = g_string_new(""); 355 GString *str = g_string_new("");
294 char *cur = msg, *end = msg; 356 char *cur = msg, *end = msg;
295 gboolean bold = FALSE, underline = FALSE, italics = FALSE; 357 gboolean bold = FALSE, underline = FALSE, italics = FALSE;
296 358
341 } 403 }
342 str = g_string_append(str, cur); 404 str = g_string_append(str, cur);
343 return str; 405 return str;
344 } 406 }
345 407
346 static GString *decode_html(char *msg) 408 static GString *
409 decode_html(char *msg)
347 { 410 {
348 GString /* oo la la */ *str = g_string_new(""); 411 GString /* oo la la */ *str = g_string_new("");
349 char *cur = msg, *end = msg; 412 char *cur = msg, *end = msg;
350 gboolean bold = FALSE, underline = FALSE, fg = FALSE, bg = FALSE; 413 gboolean bold = FALSE, underline = FALSE, fg = FALSE, bg = FALSE;
351 int fore, back; 414 int fore, back;
438 if (*cur) 501 if (*cur)
439 str = g_string_append(str, cur); 502 str = g_string_append(str, cur);
440 return str; 503 return str;
441 } 504 }
442 505
443 static void irc_got_im(struct gaim_connection *gc, char *who, char *what, int flags, time_t t) 506 static void
444 { 507 irc_got_im(struct gaim_connection *gc, char *who, char *what, int flags, time_t t)
445 GString *str = decode_html(what); 508 {
509 char *utf8 = irc_recv_convert(gc, what);
510 GString *str = decode_html(utf8);
446 serv_got_im(gc, who, str->str, flags, t, -1); 511 serv_got_im(gc, who, str->str, flags, t, -1);
447 g_string_free(str, TRUE); 512 g_string_free(str, TRUE);
448 } 513 g_free(utf8);
449 514 }
450 static void dcc_chat_cancel(struct dcc_chat *); 515
516 static void
517 dcc_chat_cancel(struct dcc_chat *);
451 518
452 void 519 void
453 dcc_chat_in (gpointer data, gint source, GaimInputCondition condition) 520 dcc_chat_in (gpointer data, gint source, GaimInputCondition condition)
454 { 521 {
455 struct dcc_chat *chat = data; 522 struct dcc_chat *chat = data;
479 time ((time_t) NULL), -1); 546 time ((time_t) NULL), -1);
480 dcc_chat_cancel (chat); 547 dcc_chat_cancel (chat);
481 } 548 }
482 } 549 }
483 550
484 static void irc_file_transfer_do(struct gaim_connection *gc, struct irc_file_transfer *ift) { 551 static void
552 irc_file_transfer_do(struct gaim_connection *gc, struct irc_file_transfer *ift) {
485 /* Ok, we better be receiving some crap here boyeee */ 553 /* Ok, we better be receiving some crap here boyeee */
486 if (transfer_in_do(ift->xfer, ift->fd, ift->name, ift->len)) { 554 if (transfer_in_do(ift->xfer, ift->fd, ift->name, ift->len)) {
487 gaim_input_remove(ift->watcher); 555 gaim_input_remove(ift->watcher);
488 ift->watcher = 0; 556 ift->watcher = 0;
489 } 557 }
490 } 558 }
491 559
492 560
493 void irc_read_dcc_ack (gpointer data, gint source, GaimInputCondition condition) { 561 void
562 irc_read_dcc_ack (gpointer data, gint source, GaimInputCondition condition) {
494 /* Read ACK Here */ 563 /* Read ACK Here */
495 564
496 } 565 }
497 566
498 void dcc_send_callback (gpointer data, gint source, GaimInputCondition condition) { 567 void
568 dcc_send_callback (gpointer data, gint source, GaimInputCondition condition) {
499 struct irc_file_transfer *ift = data; 569 struct irc_file_transfer *ift = data;
500 struct sockaddr_in addr; 570 struct sockaddr_in addr;
501 int len = sizeof(addr); 571 int len = sizeof(addr);
502 572
503 addr.sin_family = AF_INET; 573 addr.sin_family = AF_INET;
517 gaim_input_remove(ift->watcher); 587 gaim_input_remove(ift->watcher);
518 ift->watcher = 0; 588 ift->watcher = 0;
519 } 589 }
520 } 590 }
521 591
522 void dcc_recv_callback (gpointer data, gint source, GaimInputCondition condition) { 592 void
593 dcc_recv_callback (gpointer data, gint source, GaimInputCondition condition) {
523 struct irc_file_transfer *ift = data; 594 struct irc_file_transfer *ift = data;
524 595
525 ift->fd = source; 596 ift->fd = source;
526 irc_file_transfer_do(ift->gc, ift); 597 irc_file_transfer_do(ift->gc, ift);
527 } 598 }
528 599
529 void dcc_chat_callback (gpointer data, gint source, GaimInputCondition condition) { 600 void
601 dcc_chat_callback (gpointer data, gint source, GaimInputCondition condition) {
530 struct dcc_chat *chat = data; 602 struct dcc_chat *chat = data;
531 struct conversation *convo = new_conversation (chat->nick); 603 struct conversation *convo = new_conversation (chat->nick);
532 char buf[IRC_BUF_LEN]; 604 char buf[IRC_BUF_LEN];
533 chat->fd = source; 605 chat->fd = source;
534 g_snprintf (buf, sizeof buf, 606 g_snprintf (buf, sizeof buf,
540 dcc_chat_list = g_slist_append (dcc_chat_list, chat); 612 dcc_chat_list = g_slist_append (dcc_chat_list, chat);
541 gaim_input_remove(chat->inpa); 613 gaim_input_remove(chat->inpa);
542 chat->inpa = gaim_input_add(source, GAIM_INPUT_READ, dcc_chat_in, chat); 614 chat->inpa = gaim_input_add(source, GAIM_INPUT_READ, dcc_chat_in, chat);
543 } 615 }
544 616
545 static void irc_got_chat_in(struct gaim_connection *gc, int id, char *who, int whisper, char *msg, time_t t) 617 static void
546 { 618 irc_got_chat_in(struct gaim_connection *gc, int id, char *who, int whisper, char *msg, time_t t)
547 GString *str = decode_html(msg); 619 {
620 char *utf8 = irc_recv_convert(gc, msg);
621 GString *str = decode_html(utf8);
548 serv_got_chat_in(gc, id, who, whisper, str->str, t); 622 serv_got_chat_in(gc, id, who, whisper, str->str, t);
549 g_string_free(str, TRUE); 623 g_string_free(str, TRUE);
550 } 624 g_free(utf8);
551 625 }
552 static void handle_list(struct gaim_connection *gc, char *list) 626
627 static void
628 handle_list(struct gaim_connection *gc, char *list)
553 { 629 {
554 struct irc_data *id = gc->proto_data; 630 struct irc_data *id = gc->proto_data;
555 GSList *gr; 631 GSList *gr;
556 632
557 id->str = g_string_append_c(id->str, ' '); 633 id->str = g_string_append_c(id->str, ' ');
584 } 660 }
585 g_string_free(id->str, TRUE); 661 g_string_free(id->str, TRUE);
586 id->str = g_string_new(""); 662 id->str = g_string_new("");
587 } 663 }
588 664
589 static gboolean irc_request_buddy_update(gpointer data) 665 static gboolean
666 irc_request_buddy_update(gpointer data)
590 { 667 {
591 struct gaim_connection *gc = data; 668 struct gaim_connection *gc = data;
592 struct irc_data *id = gc->proto_data; 669 struct irc_data *id = gc->proto_data;
593 char buf[500]; 670 char buf[500];
594 int n = g_snprintf(buf, sizeof(buf), "ISON"); 671 int n = g_snprintf(buf, sizeof(buf), "ISON");
617 irc_write(id->fd, buf, strlen(buf)); 694 irc_write(id->fd, buf, strlen(buf));
618 id->bc++; 695 id->bc++;
619 return TRUE; 696 return TRUE;
620 } 697 }
621 698
622 static void handle_names(struct gaim_connection *gc, char *chan, char *names) 699 static void
700 handle_names(struct gaim_connection *gc, char *chan, char *names)
623 { 701 {
624 struct conversation *c = irc_find_chat(gc, chan); 702 struct conversation *c = irc_find_chat(gc, chan);
625 char **buf, **tmp; 703 char **buf, **tmp;
626 if (!c) return; 704 if (!c) return;
627 if (*names == ':') names++; 705 if (*names == ':') names++;
629 for (tmp = buf; *tmp; tmp++) 707 for (tmp = buf; *tmp; tmp++)
630 add_chat_buddy(c, *tmp, NULL); 708 add_chat_buddy(c, *tmp, NULL);
631 g_strfreev(buf); 709 g_strfreev(buf);
632 } 710 }
633 711
634 static void handle_notopic(struct gaim_connection *gc, char *text) 712 static void
713 handle_notopic(struct gaim_connection *gc, char *text)
635 { 714 {
636 struct conversation *c; 715 struct conversation *c;
637 if ((c = irc_find_chat(gc, text))) { 716 if ((c = irc_find_chat(gc, text))) {
638 char buf[IRC_BUF_LEN]; 717 char buf[IRC_BUF_LEN];
639 g_snprintf(buf, sizeof(buf), _("No topic is set")); 718 g_snprintf(buf, sizeof(buf), _("No topic is set"));
640 chat_set_topic(c, NULL, buf); 719 chat_set_topic(c, NULL, buf);
641 } 720 }
642 } 721 }
643 722
644 static void handle_topic(struct gaim_connection *gc, char *text) 723 static void
724 handle_topic(struct gaim_connection *gc, char *text)
645 { 725 {
646 struct conversation *c; 726 struct conversation *c;
647 char *po = strchr(text, ' '); 727 char *po = strchr(text, ' ');
648 728
649 if (!po) 729 if (!po)
659 text, po); 739 text, po);
660 write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); 740 write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL), -1);
661 } 741 }
662 } 742 }
663 743
664 static gboolean mode_has_arg(struct gaim_connection *gc, char sign, char mode) 744 static gboolean
745 mode_has_arg(struct gaim_connection *gc, char sign, char mode)
665 { 746 {
666 struct irc_data *id = gc->proto_data; 747 struct irc_data *id = gc->proto_data;
667 char *cm = id->chanmodes; 748 char *cm = id->chanmodes;
668 int type = 0; 749 int type = 0;
669 750
689 } 770 }
690 771
691 return FALSE; 772 return FALSE;
692 } 773 }
693 774
694 static void irc_chan_mode(struct gaim_connection *gc, char *room, char sign, char mode, char *argstr, char *who) 775 static void
776 irc_chan_mode(struct gaim_connection *gc, char *room, char sign, char mode, char *argstr, char *who)
695 { 777 {
696 struct conversation *c = irc_find_chat(gc, room); 778 struct conversation *c = irc_find_chat(gc, room);
697 char buf[IRC_BUF_LEN]; 779 char buf[IRC_BUF_LEN];
698 char *nick = g_strndup(who, strchr(who, '!') - who); 780 char *nick = g_strndup(who, strchr(who, '!') - who);
699 781
702 nick); 784 nick);
703 g_free(nick); 785 g_free(nick);
704 write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL), -1); 786 write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL), -1);
705 } 787 }
706 788
707 static void irc_user_mode(struct gaim_connection *gc, char *room, char sign, char mode, char *nick) 789 static void
790 irc_user_mode(struct gaim_connection *gc, char *room, char sign, char mode, char *nick)
708 { 791 {
709 struct conversation *c = irc_find_chat(gc, room); 792 struct conversation *c = irc_find_chat(gc, room);
710 GList *r; 793 GList *r;
711 794
712 if (mode != 'o' && mode != 'v') 795 if (mode != 'o' && mode != 'v')
750 } 833 }
751 r = r->next; 834 r = r->next;
752 } 835 }
753 } 836 }
754 837
755 static void handle_mode(struct gaim_connection *gc, char *word[], char *word_eol[], gboolean n324) 838 static void
839 handle_mode(struct gaim_connection *gc, char *word[], char *word_eol[], gboolean n324)
756 { 840 {
757 struct irc_data *id = gc->proto_data; 841 struct irc_data *id = gc->proto_data;
758 int offset = n324 ? 4 : 3; 842 int offset = n324 ? 4 : 3;
759 char *chan = word[offset]; 843 char *chan = word[offset];
760 struct conversation *c = irc_find_chat(gc, chan); 844 struct conversation *c = irc_find_chat(gc, chan);
791 } 875 }
792 modes++; 876 modes++;
793 } 877 }
794 } 878 }
795 879
796 static void handle_version(struct gaim_connection *gc, char *word[], char *word_eol[], int num) 880 static void
881 handle_version(struct gaim_connection *gc, char *word[], char *word_eol[], int num)
797 { 882 {
798 struct irc_data *id = gc->proto_data; 883 struct irc_data *id = gc->proto_data;
799 GString *str; 884 GString *str;
800 885
801 id->liststr = g_string_new(""); 886 id->liststr = g_string_new("");
808 g_string_free(str, TRUE); 893 g_string_free(str, TRUE);
809 g_string_free(id->liststr, TRUE); 894 g_string_free(id->liststr, TRUE);
810 id->liststr = NULL; 895 id->liststr = NULL;
811 } 896 }
812 897
813 static void handle_who(struct gaim_connection *gc, char *word[], char *word_eol[], int num) 898 static void
899 handle_who(struct gaim_connection *gc, char *word[], char *word_eol[], int num)
814 { 900 {
815 struct irc_data *id = gc->proto_data; 901 struct irc_data *id = gc->proto_data;
816 char buf[IRC_BUF_LEN]; 902 char buf[IRC_BUF_LEN];
817 903
818 if (!id->in_whois) { 904 if (!id->in_whois) {
831 917
832 /* Handle our whois stuff here. You know what, I have a sore throat. You know 918 /* Handle our whois stuff here. You know what, I have a sore throat. You know
833 * what I think about that? I'm not too pleased with it. Perhaps I should take 919 * what I think about that? I'm not too pleased with it. Perhaps I should take
834 * some medicine, or perhaps I should go to bed? Blah!! */ 920 * some medicine, or perhaps I should go to bed? Blah!! */
835 921
836 static void handle_whois(struct gaim_connection *gc, char *word[], char *word_eol[], int num) 922 static void
923 handle_whois(struct gaim_connection *gc, char *word[], char *word_eol[], int num)
837 { 924 {
838 struct irc_data *id = gc->proto_data; 925 struct irc_data *id = gc->proto_data;
839 char tmp[1024]; 926 char tmp[1024];
840 927
841 if (!id->in_whois) { 928 if (!id->in_whois) {
887 } 974 }
888 else 975 else
889 id->liststr = g_string_append(id->liststr, word_eol[5]); 976 id->liststr = g_string_append(id->liststr, word_eol[5]);
890 } 977 }
891 978
892 static void handle_roomlist(struct gaim_connection *gc, char *word[], char *word_eol[]) 979 static void
980 handle_roomlist(struct gaim_connection *gc, char *word[], char *word_eol[])
893 { 981 {
894 struct irc_data *id = gc->proto_data; 982 struct irc_data *id = gc->proto_data;
895 983
896 if (!id->in_list) { 984 if (!id->in_list) {
897 id->in_list = TRUE; 985 id->in_list = TRUE;
902 } 990 }
903 991
904 id->liststr = g_string_append(id->liststr, word_eol[4]); 992 id->liststr = g_string_append(id->liststr, word_eol[4]);
905 } 993 }
906 994
907 static void irc_change_nick(void *a, char *b) { 995 static void
996 irc_change_nick(void *a, char *b) {
908 struct gaim_connection *gc = a; 997 struct gaim_connection *gc = a;
909 struct irc_data *id = gc->proto_data; 998 struct irc_data *id = gc->proto_data;
910 char buf[IRC_BUF_LEN]; 999 char buf[IRC_BUF_LEN];
911 g_snprintf(buf, sizeof(buf), "NICK %s\r\n", b); 1000 g_snprintf(buf, sizeof(buf), "NICK %s\r\n", b);
912 irc_write(id->fd, buf, strlen(buf)); 1001 irc_write(id->fd, buf, strlen(buf));
913 } 1002 }
914 1003
915 static void process_numeric(struct gaim_connection *gc, char *word[], char *word_eol[]) 1004 static void
1005 process_numeric(struct gaim_connection *gc, char *word[], char *word_eol[])
916 { 1006 {
917 struct irc_data *id = gc->proto_data; 1007 struct irc_data *id = gc->proto_data;
918 char *text = word_eol[3]; 1008 char *text = word_eol[3];
919 int n = atoi(word[2]); 1009 int n = atoi(word[2]);
920 1010
1022 } 1112 }
1023 break; 1113 break;
1024 } 1114 }
1025 } 1115 }
1026 1116
1027 static gboolean is_channel(struct gaim_connection *gc, char *name) 1117 static gboolean
1118 is_channel(struct gaim_connection *gc, char *name)
1028 { 1119 {
1029 struct irc_data *id = gc->proto_data; 1120 struct irc_data *id = gc->proto_data;
1030 if (strchr(id->chantypes, *name)) 1121 if (strchr(id->chantypes, *name))
1031 return TRUE; 1122 return TRUE;
1032 return FALSE; 1123 return FALSE;
1033 } 1124 }
1034 1125
1035 static void irc_rem_chat_bud(struct gaim_connection *gc, char *nick, char *reason) 1126 static void
1127 irc_rem_chat_bud(struct gaim_connection *gc, char *nick, char *reason)
1036 { 1128 {
1037 GSList *bcs = gc->buddy_chats; 1129 GSList *bcs = gc->buddy_chats;
1038 1130
1039 while (bcs) { 1131 while (bcs) {
1040 struct conversation *b = bcs->data; 1132 struct conversation *b = bcs->data;
1056 } 1148 }
1057 bcs = bcs->next; 1149 bcs = bcs->next;
1058 } 1150 }
1059 } 1151 }
1060 1152
1061 static void irc_change_name(struct gaim_connection *gc, char *old, char *new) 1153 static void
1154 irc_change_name(struct gaim_connection *gc, char *old, char *new)
1062 { 1155 {
1063 GSList *bcs = gc->buddy_chats; 1156 GSList *bcs = gc->buddy_chats;
1064 char buf[IRC_BUF_LEN]; 1157 char buf[IRC_BUF_LEN];
1065 1158
1066 while (bcs) { 1159 while (bcs) {
1086 } 1179 }
1087 bcs = bcs->next; 1180 bcs = bcs->next;
1088 } 1181 }
1089 } 1182 }
1090 1183
1091 static void handle_privmsg(struct gaim_connection *gc, char *to, char *nick, char *msg) 1184 static void
1185 handle_privmsg(struct gaim_connection *gc, char *to, char *nick, char *msg)
1092 { 1186 {
1093 if (is_channel(gc, to)) { 1187 if (is_channel(gc, to)) {
1094 struct conversation *c = irc_find_chat(gc, to); 1188 struct conversation *c = irc_find_chat(gc, to);
1095 if (!c) 1189 if (!c)
1096 return; 1190 return;
1109 } 1203 }
1110 g_free(tmp); 1204 g_free(tmp);
1111 } 1205 }
1112 } 1206 }
1113 1207
1114 static void dcc_chat_init(struct dcc_chat *data) { 1208 static void
1209 dcc_chat_init(struct dcc_chat *data) {
1115 proxy_connect(data->ip_address, data->port, dcc_chat_callback, data); 1210 proxy_connect(data->ip_address, data->port, dcc_chat_callback, data);
1116 } 1211 }
1117 1212
1118 static void dcc_chat_cancel(struct dcc_chat *data){ 1213 static void
1214 dcc_chat_cancel(struct dcc_chat *data){
1119 if (find_dcc_chat(data->gc, data->nick)) { 1215 if (find_dcc_chat(data->gc, data->nick)) {
1120 dcc_chat_list = g_slist_remove(dcc_chat_list, data); 1216 dcc_chat_list = g_slist_remove(dcc_chat_list, data);
1121 gaim_input_remove (data->inpa); 1217 gaim_input_remove (data->inpa);
1122 close (data->fd); 1218 close (data->fd);
1123 } 1219 }
1124 g_free(data); 1220 g_free(data);
1125 } 1221 }
1126 1222
1127 static void irc_convo_closed(struct gaim_connection *gc, char *who) 1223 static void
1224 irc_convo_closed(struct gaim_connection *gc, char *who)
1128 { 1225 {
1129 struct dcc_chat *dchat = find_dcc_chat(gc, who); 1226 struct dcc_chat *dchat = find_dcc_chat(gc, who);
1130 if (!dchat) 1227 if (!dchat)
1131 return; 1228 return;
1132 1229
1133 dcc_chat_cancel(dchat); 1230 dcc_chat_cancel(dchat);
1134 } 1231 }
1135 1232
1136 static void handle_ctcp(struct gaim_connection *gc, char *to, char *nick, 1233 static void
1234 handle_ctcp(struct gaim_connection *gc, char *to, char *nick,
1137 char *msg, char *word[], char *word_eol[]) 1235 char *msg, char *word[], char *word_eol[])
1138 { 1236 {
1139 struct irc_data *id = gc->proto_data; 1237 struct irc_data *id = gc->proto_data;
1140 char buf[IRC_BUF_LEN]; 1238 char buf[IRC_BUF_LEN];
1141 char out[IRC_BUF_LEN]; 1239 char out[IRC_BUF_LEN];
1207 } 1305 }
1208 1306
1209 /*write_to_conv(c, out, WFLAG_SYSTEM, NULL, time(NULL), -1);*/ 1307 /*write_to_conv(c, out, WFLAG_SYSTEM, NULL, time(NULL), -1);*/
1210 } 1308 }
1211 1309
1212 static gboolean irc_parse(struct gaim_connection *gc, char *buf) 1310 static gboolean
1311 irc_parse(struct gaim_connection *gc, char *buf)
1213 { 1312 {
1214 struct irc_data *idata = gc->proto_data; 1313 struct irc_data *idata = gc->proto_data;
1215 gchar outbuf[IRC_BUF_LEN]; 1314 gchar outbuf[IRC_BUF_LEN];
1216 char *word[PDIWORDS], *word_eol[PDIWORDS]; 1315 char *word[PDIWORDS], *word_eol[PDIWORDS];
1217 char pdibuf[522]; 1316 char pdibuf[522];
1279 1378
1280 if (!strcmp(cmd, "INVITE")) { 1379 if (!strcmp(cmd, "INVITE")) {
1281 char *chan = g_strdup(word[4]); 1380 char *chan = g_strdup(word[4]);
1282 serv_got_chat_invite(gc, chan + 1, nick, NULL, g_list_append(NULL, chan)); 1381 serv_got_chat_invite(gc, chan + 1, nick, NULL, g_list_append(NULL, chan));
1283 } else if (!strcmp(cmd, "JOIN")) { 1382 } else if (!strcmp(cmd, "JOIN")) {
1284 char *chan = *word[3] == ':' ? word[3] + 1 : word[3]; 1383 irc_parse_join(gc, nick, word, word_eol);
1285 if (!g_strcasecmp(gc->displayname, nick)) {
1286 static int id = 1;
1287 serv_got_joined_chat(gc, id++, chan);
1288 } else {
1289 struct conversation *c = irc_find_chat(gc, chan);
1290 if (c) {
1291 char *hostmask = g_strdup(word[1]);
1292 char *p = strchr(hostmask, '!');
1293 if (p) {
1294 char *pend = strchr(p, ' ');
1295 if (pend) {
1296 *pend = 0;
1297 }
1298 add_chat_buddy(c, nick, p+1);
1299 g_free(hostmask);
1300 }
1301 }
1302 }
1303
1304 } else if (!strcmp(cmd, "KICK")) { 1384 } else if (!strcmp(cmd, "KICK")) {
1305 if (!strcmp(gc->displayname, word[4])) { 1385 if (!strcmp(gc->displayname, word[4])) {
1306 struct conversation *c = irc_find_chat(gc, word[3]); 1386 struct conversation *c = irc_find_chat(gc, word[3]);
1307 if (!c) 1387 if (!c)
1308 return FALSE; 1388 return FALSE;
1324 char *new = *word_eol[3] == ':' ? word_eol[3] + 1 : word_eol[3]; 1404 char *new = *word_eol[3] == ':' ? word_eol[3] + 1 : word_eol[3];
1325 if (!strcmp(gc->displayname, nick)) 1405 if (!strcmp(gc->displayname, nick))
1326 g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", new); 1406 g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", new);
1327 irc_change_name(gc, nick, new); 1407 irc_change_name(gc, nick, new);
1328 } else if (!strcmp(cmd, "NOTICE")) { 1408 } else if (!strcmp(cmd, "NOTICE")) {
1329 char buf[IRC_BUF_LEN]; 1409 irc_parse_notice(gc, nick, ex, word, word_eol);
1330 if (!g_strcasecmp(word[4], ":\001CLIENTINFO")) {
1331 char *p = strrchr(word_eol[5], '\001');
1332 *p = 0;
1333 g_snprintf(buf, sizeof(buf), "CTCP Answer: %s",
1334 word_eol[5]);
1335 do_error_dialog(buf, _("CTCP ClientInfo"), GAIM_INFO);
1336 } else if (!g_strcasecmp(word[4], ":\001USERINFO")) {
1337 char *p = strrchr(word_eol[5], '\001');
1338 *p = 0;
1339 g_snprintf(buf, sizeof(buf), "CTCP Answer: %s",
1340 word_eol[5]);
1341 do_error_dialog(buf, _("CTCP UserInfo"), GAIM_INFO);
1342 } else if (!g_strcasecmp(word[4], ":\001VERSION")) {
1343 char *p = strrchr(word_eol[5], '\001');
1344 *p = 0;
1345 g_snprintf(buf, sizeof(buf), "CTCP Answer: %s",
1346 word_eol[5]);
1347 do_error_dialog(buf, _("CTCP Version"), GAIM_INFO);
1348 } else if (!g_strcasecmp(word[4], ":\001PING")) {
1349 char *p = strrchr(word_eol[5], '\001');
1350 time_t ping_time;
1351 if (p)
1352 *p = 0;
1353 ping_time = time(NULL) - atol(word_eol[5]);
1354 g_snprintf(buf, sizeof(buf), "CTCP Ping reply from %s; %d seconds",
1355 word[3], ping_time);
1356 do_error_dialog(buf, _("CTCP Ping"), GAIM_INFO);
1357 } else {
1358 if (*word_eol[4] == ':') word_eol[4]++;
1359 if (ex)
1360 irc_got_im(gc, nick, word_eol[4], 0,
1361 time(NULL));
1362 }
1363 } else if (!strcmp(cmd, "PART")) { 1410 } else if (!strcmp(cmd, "PART")) {
1364 char *chan = cmd + 5; 1411 if (!irc_parse_part(gc, nick, cmd, word, word_eol))
1365 struct conversation *c;
1366 char *reason = word_eol[4];
1367 GList *r;
1368 if (*chan == ':')
1369 chan++;
1370 if (*reason == ':')
1371 reason++;
1372 if (!(c = irc_find_chat(gc, chan)))
1373 return FALSE; 1412 return FALSE;
1374 if (!strcmp(nick, gc->displayname)) {
1375 serv_got_chat_left(gc, c->id);
1376 return FALSE;
1377 }
1378 r = c->in_room;
1379 while (r) {
1380 char *who = r->data;
1381 if (*who == '@')
1382 who++;
1383 if (*who == '+')
1384 who++;
1385 if (!g_strcasecmp(who, nick)) {
1386 char *tmp = g_strdup(r->data);
1387 remove_chat_buddy(c, tmp, reason);
1388 g_free(tmp);
1389 break;
1390 }
1391 r = r->next;
1392 }
1393 } else if (!strcmp(cmd, "PRIVMSG")) { 1413 } else if (!strcmp(cmd, "PRIVMSG")) {
1394 char *to, *msg; 1414 char *to, *msg;
1395 if (!*word[3]) 1415 if (!*word[3])
1396 return FALSE; 1416 return FALSE;
1397 to = word[3]; 1417 to = word[3];
1405 } 1425 }
1406 } else if (!strcmp(cmd, "PONG")) { /* */ 1426 } else if (!strcmp(cmd, "PONG")) { /* */
1407 } else if (!strcmp(cmd, "QUIT")) { 1427 } else if (!strcmp(cmd, "QUIT")) {
1408 irc_rem_chat_bud(gc, nick, *word_eol[3] == ':' ? word_eol[3] + 1 : word_eol[3]); 1428 irc_rem_chat_bud(gc, nick, *word_eol[3] == ':' ? word_eol[3] + 1 : word_eol[3]);
1409 } else if (!strcmp(cmd, "TOPIC")) { 1429 } else if (!strcmp(cmd, "TOPIC")) {
1410 struct conversation *c = irc_find_chat(gc, word[3]); 1430 irc_parse_topic(gc, nick, word, word_eol);
1411 char *topic = *word_eol[4] == ':' ? word_eol[4] + 1 : word_eol[4];
1412 if (c) {
1413 char buf[IRC_BUF_LEN];
1414 chat_set_topic(c, nick, topic);
1415 g_snprintf(buf, sizeof(buf), _("<B>%s has changed the topic to: %s</B>"),
1416 nick, topic);
1417 write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL), -1);
1418 }
1419 } else if (!strcmp(cmd, "WALLOPS")) { /* Don't know if a dialog box is the right way? */ 1431 } else if (!strcmp(cmd, "WALLOPS")) { /* Don't know if a dialog box is the right way? */
1420 char *msg = strrchr(word_eol[0], ':'); 1432 char *msg = strrchr(word_eol[0], ':');
1421 if (msg) 1433 if (msg)
1422 do_error_dialog(msg+1, _("IRC Operator"), GAIM_ERROR); 1434 do_error_dialog(msg+1, _("IRC Operator"), GAIM_ERROR);
1423 } 1435 }
1424 1436
1425 return FALSE; 1437 return FALSE;
1426 } 1438 }
1427 1439
1428 static void irc_callback(gpointer data, gint source, GaimInputCondition condition) 1440 /* CTCP by jonas@birme.se */
1441 static void
1442 irc_parse_notice(struct gaim_connection *gc, char *nick, char *ex,
1443 char *word[], char *word_eol[])
1444 {
1445 char buf[IRC_BUF_LEN];
1446
1447 if (!g_strcasecmp(word[4], ":\001CLIENTINFO")) {
1448 char *p = g_strrstr(word_eol[5], "\001");
1449 *p = 0;
1450 g_snprintf(buf, sizeof(buf), "CTCP Answer: %s",
1451 word_eol[5]);
1452 do_error_dialog(buf, _("CTCP ClientInfo"), GAIM_INFO);
1453 } else if (!g_strcasecmp(word[4], ":\001USERINFO")) {
1454 char *p = g_strrstr(word_eol[5], "\001");
1455 *p = 0;
1456 g_snprintf(buf, sizeof(buf), "CTCP Answer: %s",
1457 word_eol[5]);
1458 do_error_dialog(buf, _("CTCP UserInfo"), GAIM_INFO);
1459 } else if (!g_strcasecmp(word[4], ":\001VERSION")) {
1460 char *p = g_strrstr(word_eol[5], "\001");
1461 *p = 0;
1462 g_snprintf(buf, sizeof(buf), "CTCP Answer: %s",
1463 word_eol[5]);
1464 do_error_dialog(buf, _("CTCP Version"), GAIM_INFO);
1465 } else if (!g_strcasecmp(word[4], ":\001PING")) {
1466 char *p = g_strrstr(word_eol[5], "\001");
1467 struct timeval ping_time;
1468 struct timeval now;
1469 gchar **vector;
1470 if (p)
1471 *p = 0;
1472 vector = g_strsplit(word_eol[5], " ", 2);
1473 if (gettimeofday(&now, NULL) == 0 && vector != NULL) {
1474 if (now.tv_usec - atol(vector[1]) < 0) {
1475 ping_time.tv_sec = now.tv_sec - atol(vector[0]) - 1;
1476 ping_time.tv_usec = now.tv_usec - atol(vector[1]) + 1000000;
1477 } else {
1478 ping_time.tv_sec = now.tv_sec - atol(vector[0]);
1479 ping_time.tv_usec = now.tv_usec - atol(vector[1]);
1480 }
1481 g_snprintf(buf, sizeof(buf),
1482 "CTCP Ping reply from %s: %lu.%.03lu seconds",
1483 nick, ping_time.tv_sec, (ping_time.tv_usec/1000));
1484 do_error_dialog(buf, _("CTCP Ping"), GAIM_INFO);
1485 g_strfreev(vector);
1486 }
1487 } else {
1488 if (*word_eol[4] == ':') word_eol[4]++;
1489 if (ex)
1490 irc_got_im(gc, nick, word_eol[4], 0,
1491 time(NULL));
1492 }
1493
1494 }
1495
1496 static void
1497 irc_parse_join(struct gaim_connection *gc, char *nick,
1498 char *word[], char *word_eol[])
1499 {
1500 char *chan = *word[3] == ':' ? word[3] + 1 : word[3];
1501 static int id = 1;
1502 struct conversation *c;
1503 char *hostmask, *p;
1504
1505 if (!g_strcasecmp(gc->displayname, nick)) {
1506 serv_got_joined_chat(gc, id++, chan);
1507 } else {
1508 c = irc_find_chat(gc, chan);
1509 if (c) {
1510 hostmask = g_strdup(word[1]);
1511 p = strchr(hostmask, '!');
1512 if (p) {
1513 char *pend = strchr(p, ' ');
1514 if (pend) {
1515 *pend = 0;
1516 }
1517 add_chat_buddy(c, nick, p+1);
1518 g_free(hostmask);
1519 }
1520 }
1521 }
1522 }
1523
1524 static void
1525 irc_parse_topic(struct gaim_connection *gc, char *nick,
1526 char *word[], char *word_eol[])
1527 {
1528 struct conversation *c = irc_find_chat(gc, word[3]);
1529 char *topic = *word_eol[4] == ':' ? word_eol[4] + 1 : word_eol[4];
1530 char buf[IRC_BUF_LEN];
1531
1532 if (c) {
1533 chat_set_topic(c, nick, topic);
1534 g_snprintf(buf, sizeof(buf), _("<B>%s has changed the topic to: %s</B>"),
1535 nick, topic);
1536 write_to_conv(c, buf, WFLAG_SYSTEM, NULL, time(NULL), -1);
1537 }
1538 }
1539
1540 static gboolean
1541 irc_parse_part(struct gaim_connection *gc, char *nick, char *cmd,
1542 char *word[], char *word_eol[])
1543 {
1544 char *chan = cmd + 5;
1545 struct conversation *c;
1546 char *reason = word_eol[4];
1547 GList *r;
1548
1549 if (*chan == ':')
1550 chan++;
1551 if (*reason == ':')
1552 reason++;
1553 if (!(c = irc_find_chat(gc, chan)))
1554 return FALSE;
1555 if (!strcmp(nick, gc->displayname)) {
1556 serv_got_chat_left(gc, c->id);
1557 return FALSE;
1558 }
1559 r = c->in_room;
1560 while (r) {
1561 char *who = r->data;
1562 if (*who == '@')
1563 who++;
1564 if (*who == '+')
1565 who++;
1566 if (!g_strcasecmp(who, nick)) {
1567 char *tmp = g_strdup(r->data);
1568 remove_chat_buddy(c, tmp, reason);
1569 g_free(tmp);
1570 break;
1571 }
1572 r = r->next;
1573 }
1574 }
1575
1576 static void
1577 irc_callback(gpointer data, gint source,
1578 GaimInputCondition condition)
1429 { 1579 {
1430 struct gaim_connection *gc = data; 1580 struct gaim_connection *gc = data;
1431 struct irc_data *idata = gc->proto_data; 1581 struct irc_data *idata = gc->proto_data;
1432 int i = 0; 1582 int i = 0;
1433 gchar buf[1024]; 1583 gchar buf[1024];
1456 d = g_strndup(idata->rxqueue, len); 1606 d = g_strndup(idata->rxqueue, len);
1457 g_strchomp(d); 1607 g_strchomp(d);
1458 debug_printf("IRC S: %s\n", d); 1608 debug_printf("IRC S: %s\n", d);
1459 1609
1460 /* REMOVE ME BEFORE SUBMIT! */ 1610 /* REMOVE ME BEFORE SUBMIT! */
1461 /* fprintf(stderr, "IRC S: %s\n", d); */ 1611 /*fprintf(stderr, "IRC S: %s\n", d);*/
1462 1612
1463 idata->rxlen -= len; 1613 idata->rxlen -= len;
1464 if (idata->rxlen) { 1614 if (idata->rxlen) {
1465 char *tmp = g_strdup(e + 1); 1615 char *tmp = g_strdup(e + 1);
1466 g_free(idata->rxqueue); 1616 g_free(idata->rxqueue);
1477 if (off) 1627 if (off)
1478 return; 1628 return;
1479 } 1629 }
1480 } 1630 }
1481 1631
1482 static void irc_login_callback(gpointer data, gint source, GaimInputCondition condition) 1632 static void
1633 irc_login_callback(gpointer data, gint source, GaimInputCondition condition)
1483 { 1634 {
1484 struct gaim_connection *gc = data; 1635 struct gaim_connection *gc = data;
1485 struct irc_data *idata; 1636 struct irc_data *idata;
1486 char hostname[256]; 1637 char hostname[256];
1487 char buf[IRC_BUF_LEN]; 1638 char buf[IRC_BUF_LEN];
1488 1639 char *test;
1640 GError *err = NULL;
1641
1489 if (!g_slist_find(connections, gc)) { 1642 if (!g_slist_find(connections, gc)) {
1490 close(source); 1643 close(source);
1491 return; 1644 return;
1492 } 1645 }
1493 1646
1497 hide_login_progress(gc, "Write error"); 1650 hide_login_progress(gc, "Write error");
1498 signoff(gc); 1651 signoff(gc);
1499 return; 1652 return;
1500 } 1653 }
1501 1654
1655
1656 /* Try a quick conversion to see if the specified encoding is OK */
1657 test = g_convert("test", strlen("test"), gc->user->proto_opt[USEROPT_CHARSET],
1658 "UTF-8", NULL, NULL, &err);
1659 if (err) {
1660 debug_printf("Couldn't initialize %s for IRC charset conversion, using ISO-8859-1\n",
1661 gc->user->proto_opt[USEROPT_CHARSET]);
1662 strcpy(gc->user->proto_opt[USEROPT_CHARSET], "ISO-8859-1");
1663 }
1664
1502 if (idata->fd != source) 1665 if (idata->fd != source)
1503 idata->fd = source; 1666 idata->fd = source;
1504 1667
1505 gethostname(hostname, sizeof(hostname) - 1); 1668 gethostname(hostname, sizeof(hostname) - 1);
1506 hostname[sizeof(hostname) - 1] = 0; 1669 hostname[sizeof(hostname) - 1] = 0;
1524 } 1687 }
1525 1688
1526 gc->inpa = gaim_input_add(idata->fd, GAIM_INPUT_READ, irc_callback, gc); 1689 gc->inpa = gaim_input_add(idata->fd, GAIM_INPUT_READ, irc_callback, gc);
1527 } 1690 }
1528 1691
1529 static void irc_login(struct aim_user *user) 1692 static void
1693 irc_login(struct aim_user *user)
1530 { 1694 {
1531 char buf[IRC_BUF_LEN]; 1695 char buf[IRC_BUF_LEN];
1532 1696
1533 struct gaim_connection *gc = new_gaim_conn(user); 1697 struct gaim_connection *gc = new_gaim_conn(user);
1534 struct irc_data *idata = gc->proto_data = g_new0(struct irc_data, 1); 1698 struct irc_data *idata = gc->proto_data = g_new0(struct irc_data, 1);
1552 signoff(gc); 1716 signoff(gc);
1553 return; 1717 return;
1554 } 1718 }
1555 } 1719 }
1556 1720
1557 static void irc_close(struct gaim_connection *gc) 1721 static void
1722 irc_close(struct gaim_connection *gc)
1558 { 1723 {
1559 struct irc_data *idata = (struct irc_data *)gc->proto_data; 1724 struct irc_data *idata = (struct irc_data *)gc->proto_data;
1560 1725
1561 gchar buf[IRC_BUF_LEN]; 1726 gchar buf[IRC_BUF_LEN];
1562 1727
1605 1770
1606 close(idata->fd); 1771 close(idata->fd);
1607 g_free(gc->proto_data); 1772 g_free(gc->proto_data);
1608 } 1773 }
1609 1774
1610 static void set_mode_3(struct gaim_connection *gc, char *who, int sign, int mode, 1775 static void
1776 set_mode_3(struct gaim_connection *gc, char *who, int sign, int mode,
1611 int start, int end, char *word[]) 1777 int start, int end, char *word[])
1612 { 1778 {
1613 struct irc_data *id = gc->proto_data; 1779 struct irc_data *id = gc->proto_data;
1614 char buf[IRC_BUF_LEN]; 1780 char buf[IRC_BUF_LEN];
1615 int left; 1781 int left;
1641 if (left < 3) 1807 if (left < 3)
1642 return; 1808 return;
1643 } 1809 }
1644 } 1810 }
1645 1811
1646 static void set_mode_6(struct gaim_connection *gc, char *who, int sign, int mode, 1812 static void
1813 set_mode_6(struct gaim_connection *gc, char *who, int sign, int mode,
1647 int start, int end, char *word[]) 1814 int start, int end, char *word[])
1648 { 1815 {
1649 struct irc_data *id = gc->proto_data; 1816 struct irc_data *id = gc->proto_data;
1650 char buf[IRC_BUF_LEN]; 1817 char buf[IRC_BUF_LEN];
1651 int left; 1818 int left;
1697 if (left < 6) 1864 if (left < 6)
1698 return; 1865 return;
1699 } 1866 }
1700 } 1867 }
1701 1868
1702 static void set_mode(struct gaim_connection *gc, char *who, int sign, int mode, char *word[]) 1869 static void
1870 set_mode(struct gaim_connection *gc, char *who, int sign, int mode, char *word[])
1703 { 1871 {
1704 struct irc_data *id = gc->proto_data; 1872 struct irc_data *id = gc->proto_data;
1705 int i = 2; 1873 int i = 2;
1706 1874
1707 while (1) { 1875 while (1) {
1716 } 1884 }
1717 i++; 1885 i++;
1718 } 1886 }
1719 } 1887 }
1720 1888
1721 static void set_chan_mode(struct gaim_connection *gc, char *chan, char *mode_str) 1889 static void
1890 set_chan_mode(struct gaim_connection *gc, char *chan, char *mode_str)
1722 { 1891 {
1723 struct irc_data *id = gc->proto_data; 1892 struct irc_data *id = gc->proto_data;
1724 char buf[IRC_BUF_LEN]; 1893 char buf[IRC_BUF_LEN];
1725 1894
1726 if ((mode_str[0] == '-') || (mode_str[0] == '+')) { 1895 if ((mode_str[0] == '-') || (mode_str[0] == '+')) {
1727 g_snprintf(buf, sizeof(buf), "MODE %s %s\r\n", chan, mode_str); 1896 g_snprintf(buf, sizeof(buf), "MODE %s %s\r\n", chan, mode_str);
1728 irc_write(id->fd, buf, strlen(buf)); 1897 irc_write(id->fd, buf, strlen(buf));
1729 } 1898 }
1730 } 1899 }
1731 1900
1732 static int handle_command(struct gaim_connection *gc, char *who, char *what) 1901 static int
1902 handle_command(struct gaim_connection *gc, char *who, char *what)
1733 { 1903 {
1734 char buf[IRC_BUF_LEN]; 1904 char buf[IRC_BUF_LEN];
1735 char pdibuf[IRC_BUF_LEN]; 1905 char pdibuf[IRC_BUF_LEN];
1736 char *word[PDIWORDS], *word_eol[PDIWORDS]; 1906 char *word[PDIWORDS], *word_eol[PDIWORDS];
1737 char *tmp = g_strdup(what); 1907 char *tmp = g_strdup(what);
1738 GString *str = encode_html(tmp); 1908 GString *str = encode_html(tmp);
1909 char *intl;
1910 int len;
1739 struct dcc_chat *dccchat = find_dcc_chat(gc, who); 1911 struct dcc_chat *dccchat = find_dcc_chat(gc, who);
1740 struct irc_data *id = gc->proto_data; 1912 struct irc_data *id = gc->proto_data;
1741 g_free(tmp); 1913 g_free(tmp);
1742 what = str->str; 1914 what = str->str;
1743 if (*what != '/') { 1915 if (*what != '/') {
1744 unsigned int max = 440 - strlen(who);
1745 char t;
1746 while (strlen(what) > max) {
1747 t = what[max];
1748 what[max] = 0;
1749 if (dccchat) {
1750 g_snprintf(buf, sizeof(buf), "%s\r\n", what);
1751 irc_write(dccchat->fd, buf, strlen(buf));
1752 g_string_free(str, TRUE);
1753 return 1;
1754 }
1755 /*g_snprintf(buf, sizeof(buf), "PRIVMSG %s :%s\r\n", who, what);
1756 irc_write(id->fd, buf, strlen(buf));*/
1757 irc_send_privmsg (gc, who, what);
1758 what[max] = t;
1759 what = what + max;
1760 }
1761 if (dccchat) { 1916 if (dccchat) {
1762 g_snprintf(buf, sizeof(buf), "%s\r\n", what); 1917 intl = irc_send_convert(gc, what, sizeof(buf), &len);
1918 g_snprintf(buf, sizeof(buf), "%s\r\n", intl);
1919 g_free(intl);
1763 irc_write(dccchat->fd, buf, strlen(buf)); 1920 irc_write(dccchat->fd, buf, strlen(buf));
1764 g_string_free(str, TRUE); 1921 g_string_free(str, TRUE);
1765 return 1; 1922 return 1;
1766 } 1923 }
1767 /* 1924 irc_send_privmsg (gc, who, what, TRUE);
1768 g_snprintf(buf, sizeof(buf), "PRIVMSG %s :%s\r\n", who, what);
1769 irc_write(id->fd, buf, strlen(buf));*/
1770 irc_send_privmsg (gc, who, what);
1771 g_string_free(str, TRUE); 1925 g_string_free(str, TRUE);
1772 return 1; 1926 return 1;
1773 } 1927 }
1774 1928
1775 process_data_init(pdibuf, what + 1, word, word_eol, TRUE); 1929 process_data_init(pdibuf, what + 1, word, word_eol, TRUE);
1776 g_string_free(str, FALSE); 1930 g_string_free(str, FALSE);
1777 if (!g_strcasecmp(pdibuf, "ME")) { 1931 if (!g_strcasecmp(pdibuf, "ME")) {
1778 if (dccchat) { 1932 if (dccchat) {
1779 g_snprintf(buf, sizeof(buf), "\001ACTION %s\001\r\n", word_eol[2]); 1933 intl = irc_send_convert(gc, word_eol[2], sizeof(buf), &len);
1934 g_snprintf(buf, sizeof(buf), "\001ACTION %s\001\r\n", intl);
1935 g_free(intl);
1780 irc_write(dccchat->fd, buf, strlen(buf)); 1936 irc_write(dccchat->fd, buf, strlen(buf));
1781 g_free(what); 1937 g_free(what);
1782 return 1; 1938 return 1;
1783 } 1939 }
1784 /*
1785 g_snprintf(buf, sizeof(buf), "PRIVMSG %s :\001ACTION %s\001\r\n", who, word_eol[2]);
1786 irc_write(id->fd, buf, strlen(buf));*/
1787 g_snprintf(buf, sizeof(buf), "\001ACTION %s\001", word_eol[2]); 1940 g_snprintf(buf, sizeof(buf), "\001ACTION %s\001", word_eol[2]);
1788 irc_send_privmsg (gc, who, buf); 1941 irc_send_privmsg (gc, who, buf, FALSE);
1789 g_free(what); 1942 g_free(what);
1790 return 1; 1943 return 1;
1791 } else if (!g_strcasecmp(pdibuf, "INVITE")) { 1944 } else if (!g_strcasecmp(pdibuf, "INVITE")) {
1792 char buf[IRC_BUF_LEN]; 1945 char buf[IRC_BUF_LEN];
1793 g_snprintf(buf, sizeof(buf), "INVITE %s\r\n", word_eol[2]); 1946 g_snprintf(buf, sizeof(buf), "INVITE %s\r\n", word_eol[2]);
1797 struct conversation *c; 1950 struct conversation *c;
1798 c = irc_find_chat(gc, who); 1951 c = irc_find_chat(gc, who);
1799 g_snprintf(buf, sizeof(buf), _("Topic for %s is %s"), who, c->topic ? c->topic : "(no topic set)"); 1952 g_snprintf(buf, sizeof(buf), _("Topic for %s is %s"), who, c->topic ? c->topic : "(no topic set)");
1800 write_to_conv(c, buf, WFLAG_SYSTEM | WFLAG_NOLOG, NULL, time(NULL), -1); 1953 write_to_conv(c, buf, WFLAG_SYSTEM | WFLAG_NOLOG, NULL, time(NULL), -1);
1801 } else { 1954 } else {
1802 g_snprintf(buf, sizeof(buf), "TOPIC %s :%s\r\n", who, word_eol[2]); 1955 /* This could be too long */
1956 intl = irc_send_convert(gc, word_eol[2], sizeof(buf), &len);
1957 g_snprintf(buf, sizeof(buf), "TOPIC %s :%s\r\n", who, intl);
1958 g_free(intl);
1803 irc_write(id->fd, buf, strlen(buf)); 1959 irc_write(id->fd, buf, strlen(buf));
1804 } 1960 }
1805 } else if (!g_strcasecmp(pdibuf, "NICK")) { 1961 } else if (!g_strcasecmp(pdibuf, "NICK")) {
1806 if (!*word_eol[2]) { 1962 if (!*word_eol[2]) {
1807 g_free(what); 1963 g_free(what);
1830 } else if (!g_strcasecmp(pdibuf, "SAY")) { 1986 } else if (!g_strcasecmp(pdibuf, "SAY")) {
1831 if (!*word_eol[2]) { 1987 if (!*word_eol[2]) {
1832 g_free(what); 1988 g_free(what);
1833 return -EINVAL; 1989 return -EINVAL;
1834 } 1990 }
1835 /*g_snprintf(buf, sizeof(buf), "PRIVMSG %s :%s\r\n", who, word_eol[2]); 1991 irc_send_privmsg (gc, who, word_eol[2], TRUE);
1836 irc_write(id->fd, buf, strlen(buf));*/
1837 irc_send_privmsg (gc, who, word_eol[2]);
1838 return 1; 1992 return 1;
1839 } else if (!g_strcasecmp(pdibuf, "MSG")) { 1993 } else if (!g_strcasecmp(pdibuf, "MSG")) {
1840 if (!*word[2]) { 1994 if (!*word[2]) {
1841 g_free(what); 1995 g_free(what);
1842 return -EINVAL; 1996 return -EINVAL;
1843 } 1997 }
1844 if (!*word_eol[3]) { 1998 if (!*word_eol[3]) {
1845 g_free(what); 1999 g_free(what);
1846 return -EINVAL; 2000 return -EINVAL;
1847 } 2001 }
1848 /* 2002 irc_send_privmsg (gc, word[2], word_eol[3], TRUE);
1849 g_snprintf(buf, sizeof(buf), "PRIVMSG %s :%s\r\n", word[2], word_eol[3]);
1850 irc_write(id->fd, buf, strlen(buf));*/
1851 irc_send_privmsg (gc, word[2], word_eol[3]);
1852 } else if (!g_strcasecmp(pdibuf, "KICK")) { 2003 } else if (!g_strcasecmp(pdibuf, "KICK")) {
1853 if (!*word[2]) { 2004 if (!*word[2]) {
1854 g_free(what); 2005 g_free(what);
1855 return -EINVAL; 2006 return -EINVAL;
1856 } 2007 }
1857 if (*word_eol[3]) 2008 if (*word_eol[3]) {
1858 g_snprintf(buf, sizeof(buf), "KICK %s %s :%s\r\n", who, word[2], word_eol[3]); 2009 intl = irc_send_convert(gc, word_eol[3], sizeof(buf), &len);
1859 else 2010 g_snprintf(buf, sizeof(buf), "KICK %s %s :%s\r\n", who, word[2], intl);
2011 g_free(intl);
2012 } else
1860 g_snprintf(buf, sizeof(buf), "KICK %s %s\r\n", who, word[2]); 2013 g_snprintf(buf, sizeof(buf), "KICK %s %s\r\n", who, word[2]);
1861 irc_write(id->fd, buf, strlen(buf)); 2014 irc_write(id->fd, buf, strlen(buf));
1862 } else if (!g_strcasecmp(pdibuf, "JOIN") || !g_strcasecmp(pdibuf, "J")) { 2015 } else if (!g_strcasecmp(pdibuf, "JOIN") || !g_strcasecmp(pdibuf, "J")) {
1863 if (!*word[2]) { 2016 if (!*word[2]) {
1864 g_free(what); 2017 g_free(what);
1876 if (!is_channel(gc, chan)) { 2029 if (!is_channel(gc, chan)) {
1877 g_free(what); 2030 g_free(what);
1878 return -EINVAL; 2031 return -EINVAL;
1879 } 2032 }
1880 c = irc_find_chat(gc, chan); 2033 c = irc_find_chat(gc, chan);
1881 g_snprintf(buf, sizeof(buf), "PART %s%s%s\r\n", chan, 2034 if (*reason) {
1882 *reason ? " :" : "", 2035 intl = irc_send_convert(gc, reason, sizeof(buf), &len);
1883 *reason ? reason : ""); 2036 g_snprintf(buf, sizeof(buf), "PART %s :%s\r\n", chan, intl);
2037 g_free(intl);
2038 } else
2039 g_snprintf(buf, sizeof(buf), "PART %s\r\n", chan);
1884 irc_write(id->fd, buf, strlen(buf)); 2040 irc_write(id->fd, buf, strlen(buf));
1885 if (c) { 2041 if (c) {
1886 gc->buddy_chats = g_slist_remove(gc->buddy_chats, c); 2042 gc->buddy_chats = g_slist_remove(gc->buddy_chats, c);
1887 c->gc = NULL; 2043 c->gc = NULL;
1888 g_snprintf(buf, sizeof(buf), _("You have left %s"), chan); 2044 g_snprintf(buf, sizeof(buf), _("You have left %s"), chan);
1998 } 2154 }
1999 g_free(what); 2155 g_free(what);
2000 return 0; 2156 return 0;
2001 } 2157 }
2002 2158
2003 static int send_msg(struct gaim_connection *gc, char *who, char *what) 2159 static int
2160 send_msg(struct gaim_connection *gc, char *who, char *what)
2004 { 2161 {
2005 char *cr = strchr(what, '\n'); 2162 char *cr = strchr(what, '\n');
2006 if (cr) { 2163 if (cr) {
2007 int ret = 0; 2164 int ret = 0;
2008 while (TRUE) { 2165 while (TRUE) {
2020 return ret; 2177 return ret;
2021 } else 2178 } else
2022 return handle_command(gc, who, what); 2179 return handle_command(gc, who, what);
2023 } 2180 }
2024 2181
2025 static void irc_chat_invite(struct gaim_connection *gc, int idn, const char *message, const char *name) { 2182 static void
2183 irc_chat_invite(struct gaim_connection *gc, int idn, const char *message, const char *name) {
2026 char buf[IRC_BUF_LEN]; 2184 char buf[IRC_BUF_LEN];
2027 struct irc_data *id = gc->proto_data; 2185 struct irc_data *id = gc->proto_data;
2028 struct conversation *c = irc_find_chat_by_id(gc, idn); 2186 struct conversation *c = irc_find_chat_by_id(gc, idn);
2029 g_snprintf(buf, sizeof(buf), "INVITE %s %s\r\n", name, c->name); 2187 g_snprintf(buf, sizeof(buf), "INVITE %s %s\r\n", name, c->name);
2030 irc_write(id->fd, buf, strlen(buf)); 2188 irc_write(id->fd, buf, strlen(buf));
2031 } 2189 }
2032 2190
2033 static int irc_send_im(struct gaim_connection *gc, char *who, char *what, int len, int flags) 2191 static int
2192 irc_send_im(struct gaim_connection *gc, char *who, char *what, int len, int flags)
2034 { 2193 {
2035 if (*who == '@' || *who == '+') 2194 if (*who == '@' || *who == '+')
2036 return send_msg(gc, who + 1, what); 2195 return send_msg(gc, who + 1, what);
2037 return send_msg(gc, who, what); 2196 return send_msg(gc, who, what);
2038 } 2197 }
2039 2198
2040 /* IRC doesn't have a buddy list, but we can still figure out who's online with ISON */ 2199 /* IRC doesn't have a buddy list, but we can still figure out who's online with ISON */
2041 static void irc_add_buddy(struct gaim_connection *gc, const char *who) {} 2200 static void
2042 static void irc_remove_buddy(struct gaim_connection *gc, char *who, char *group) {} 2201 irc_add_buddy(struct gaim_connection *gc, const char *who) {}
2043 2202 static void
2044 static GList *irc_chat_info(struct gaim_connection *gc) 2203 irc_remove_buddy(struct gaim_connection *gc, char *who, char *group) {}
2204
2205 static GList *
2206 irc_chat_info(struct gaim_connection *gc)
2045 { 2207 {
2046 GList *m = NULL; 2208 GList *m = NULL;
2047 struct proto_chat_entry *pce; 2209 struct proto_chat_entry *pce;
2048 2210
2049 pce = g_new0(struct proto_chat_entry, 1); 2211 pce = g_new0(struct proto_chat_entry, 1);
2055 m = g_list_append(m, pce); 2217 m = g_list_append(m, pce);
2056 2218
2057 return m; 2219 return m;
2058 } 2220 }
2059 2221
2060 static void irc_join_chat(struct gaim_connection *gc, GList *data) 2222 static void
2223 irc_join_chat(struct gaim_connection *gc, GList *data)
2061 { 2224 {
2062 struct irc_data *id = gc->proto_data; 2225 struct irc_data *id = gc->proto_data;
2063 char buf[IRC_BUF_LEN]; 2226 char buf[IRC_BUF_LEN];
2064 char *name, *pass; 2227 char *name, *pass;
2065 2228
2072 } else 2235 } else
2073 g_snprintf(buf, sizeof(buf), "JOIN %s\r\n", name); 2236 g_snprintf(buf, sizeof(buf), "JOIN %s\r\n", name);
2074 irc_write(id->fd, buf, strlen(buf)); 2237 irc_write(id->fd, buf, strlen(buf));
2075 } 2238 }
2076 2239
2077 static void irc_chat_leave(struct gaim_connection *gc, int id) 2240 static void
2241 irc_chat_leave(struct gaim_connection *gc, int id)
2078 { 2242 {
2079 struct irc_data *idata = gc->proto_data; 2243 struct irc_data *idata = gc->proto_data;
2080 struct conversation *c = irc_find_chat_by_id(gc, id); 2244 struct conversation *c = irc_find_chat_by_id(gc, id);
2081 char buf[IRC_BUF_LEN]; 2245 char buf[IRC_BUF_LEN];
2082 2246
2084 2248
2085 g_snprintf(buf, sizeof(buf), "PART %s\r\n", c->name); 2249 g_snprintf(buf, sizeof(buf), "PART %s\r\n", c->name);
2086 irc_write(idata->fd, buf, strlen(buf)); 2250 irc_write(idata->fd, buf, strlen(buf));
2087 } 2251 }
2088 2252
2089 static int irc_chat_send(struct gaim_connection *gc, int id, char *what) 2253 static int
2254 irc_chat_send(struct gaim_connection *gc, int id, char *what)
2090 { 2255 {
2091 struct conversation *c = irc_find_chat_by_id(gc, id); 2256 struct conversation *c = irc_find_chat_by_id(gc, id);
2092 if (!c) 2257 if (!c)
2093 return -EINVAL; 2258 return -EINVAL;
2094 if (send_msg(gc, c->name, what) > 0) 2259 if (send_msg(gc, c->name, what) > 0)
2095 serv_got_chat_in(gc, c->id, gc->displayname, 0, what, time(NULL)); 2260 serv_got_chat_in(gc, c->id, gc->displayname, 0, what, time(NULL));
2096 return 0; 2261 return 0;
2097 } 2262 }
2098 2263
2099 static GList *irc_away_states(struct gaim_connection *gc) 2264 static GList *
2265 irc_away_states(struct gaim_connection *gc)
2100 { 2266 {
2101 return g_list_append(NULL, GAIM_AWAY_CUSTOM); 2267 return g_list_append(NULL, GAIM_AWAY_CUSTOM);
2102 } 2268 }
2103 2269
2104 static void irc_set_away(struct gaim_connection *gc, char *state, char *msg) 2270 static void
2271 irc_set_away(struct gaim_connection *gc, char *state, char *msg)
2105 { 2272 {
2106 struct irc_data *idata = gc->proto_data; 2273 struct irc_data *idata = gc->proto_data;
2107 char buf[IRC_BUF_LEN]; 2274 char buf[IRC_BUF_LEN];
2108 2275
2109 if (gc->away) 2276 if (gc->away)
2115 } else 2282 } else
2116 g_snprintf(buf, sizeof(buf), "AWAY\r\n"); 2283 g_snprintf(buf, sizeof(buf), "AWAY\r\n");
2117 irc_write(idata->fd, buf, strlen(buf)); 2284 irc_write(idata->fd, buf, strlen(buf));
2118 } 2285 }
2119 2286
2120 static char **irc_list_icon(int uc) 2287 static char **
2288 irc_list_icon(int uc)
2121 { 2289 {
2122 return irc_icon_xpm; 2290 return irc_icon_xpm;
2123 } 2291 }
2124 2292
2125 static int getlocalip(char *ip) /* Thanks, libfaim */ 2293 static int
2294 getlocalip(char *ip) /* Thanks, libfaim */
2126 { 2295 {
2127 struct hostent *hptr; 2296 struct hostent *hptr;
2128 char localhost[129]; 2297 char localhost[129];
2129 long unsigned add; 2298 long unsigned add;
2130 2299
2142 g_snprintf(ip, 11, "%lu", add); 2311 g_snprintf(ip, 11, "%lu", add);
2143 2312
2144 return 0; 2313 return 0;
2145 } 2314 }
2146 2315
2147 static void dcc_chat_connected(gpointer data, gint source, GdkInputCondition condition) 2316 static void
2317 dcc_chat_connected(gpointer data, gint source, GdkInputCondition condition)
2148 { 2318 {
2149 struct dcc_chat *chat = data; 2319 struct dcc_chat *chat = data;
2150 struct conversation *convo; 2320 struct conversation *convo;
2151 char buf[128]; 2321 char buf[128];
2152 struct sockaddr_in addr; 2322 struct sockaddr_in addr;
2172 write_to_conv (convo, buf, WFLAG_SYSTEM, NULL, time ((time_t) NULL), -1); 2342 write_to_conv (convo, buf, WFLAG_SYSTEM, NULL, time ((time_t) NULL), -1);
2173 debug_printf ("Chat with %s established\n", chat->nick); 2343 debug_printf ("Chat with %s established\n", chat->nick);
2174 dcc_chat_list = g_slist_append (dcc_chat_list, chat); 2344 dcc_chat_list = g_slist_append (dcc_chat_list, chat);
2175 } 2345 }
2176 #if 0 2346 #if 0
2177 static void irc_ask_send_file(struct gaim_connection *gc, char *destsn) { 2347 static void
2348 irc_ask_send_file(struct gaim_connection *gc, char *destsn) {
2178 struct irc_data *id = (struct irc_data *)gc->proto_data; 2349 struct irc_data *id = (struct irc_data *)gc->proto_data;
2179 struct irc_file_transfer *ift = g_new0(struct irc_file_transfer, 1); 2350 struct irc_file_transfer *ift = g_new0(struct irc_file_transfer, 1);
2180 char *localip = (char *)malloc(12); 2351 char *localip = (char *)malloc(12);
2181 2352
2182 if (getlocalip(localip) == -1) { 2353 if (getlocalip(localip) == -1) {
2191 id->file_transfers = g_slist_append(id->file_transfers, ift); 2362 id->file_transfers = g_slist_append(id->file_transfers, ift);
2192 2363
2193 ift->xfer = transfer_out_add(gc, ift->sn); 2364 ift->xfer = transfer_out_add(gc, ift->sn);
2194 } 2365 }
2195 #endif 2366 #endif
2196 static struct irc_file_transfer *find_ift_by_xfer(struct gaim_connection *gc, 2367 static struct
2368 irc_file_transfer *find_ift_by_xfer(struct gaim_connection *gc,
2197 struct file_transfer *xfer) { 2369 struct file_transfer *xfer) {
2198 2370
2199 GSList *g = ((struct irc_data *)gc->proto_data)->file_transfers; 2371 GSList *g = ((struct irc_data *)gc->proto_data)->file_transfers;
2200 struct irc_file_transfer *f = NULL; 2372 struct irc_file_transfer *f = NULL;
2201 2373
2208 } 2380 }
2209 2381
2210 return f; 2382 return f;
2211 } 2383 }
2212 2384
2213 static void irc_file_transfer_data_chunk(struct gaim_connection *gc, struct file_transfer *xfer, const char *data, int len) { 2385 static void
2386 irc_file_transfer_data_chunk(struct gaim_connection *gc, struct file_transfer *xfer, const char *data, int len) {
2214 struct irc_file_transfer *ift = find_ift_by_xfer(gc, xfer); 2387 struct irc_file_transfer *ift = find_ift_by_xfer(gc, xfer);
2215 guint32 pos; 2388 guint32 pos;
2216 2389
2217 ift->cur += len; 2390 ift->cur += len;
2218 pos = htonl(ift->cur); 2391 pos = htonl(ift->cur);
2220 2393
2221 // FIXME: You should check to verify that they received the data when 2394 // FIXME: You should check to verify that they received the data when
2222 // you are sending a file ... 2395 // you are sending a file ...
2223 } 2396 }
2224 2397
2225 static void irc_file_transfer_cancel (struct gaim_connection *gc, struct file_transfer *xfer) { 2398 static void
2399 irc_file_transfer_cancel (struct gaim_connection *gc, struct file_transfer *xfer) {
2226 struct irc_data *id = (struct irc_data *)gc->proto_data; 2400 struct irc_data *id = (struct irc_data *)gc->proto_data;
2227 struct irc_file_transfer *ift = find_ift_by_xfer(gc, xfer); 2401 struct irc_file_transfer *ift = find_ift_by_xfer(gc, xfer);
2228 2402
2229 printf("Our shit got canceled, yo!\n"); 2403 printf("Our shit got canceled, yo!\n");
2230 2404
2240 g_free(ift->name); 2414 g_free(ift->name);
2241 2415
2242 g_free(ift); 2416 g_free(ift);
2243 } 2417 }
2244 2418
2245 static void irc_file_transfer_done(struct gaim_connection *gc, struct file_transfer *xfer) { 2419 static void
2420 irc_file_transfer_done(struct gaim_connection *gc, struct file_transfer *xfer) {
2246 struct irc_data *id = (struct irc_data *)gc->proto_data; 2421 struct irc_data *id = (struct irc_data *)gc->proto_data;
2247 struct irc_file_transfer *ift = find_ift_by_xfer(gc, xfer); 2422 struct irc_file_transfer *ift = find_ift_by_xfer(gc, xfer);
2248 2423
2249 2424
2250 printf("Our shit be done, yo.\n"); 2425 printf("Our shit be done, yo.\n");
2261 g_free(ift->name); 2436 g_free(ift->name);
2262 2437
2263 g_free(ift); 2438 g_free(ift);
2264 } 2439 }
2265 2440
2266 static void irc_file_transfer_out (struct gaim_connection *gc, struct file_transfer *xfer, const char *name, int totfiles, int totsize) { 2441 static void
2442 irc_file_transfer_out (struct gaim_connection *gc, struct file_transfer *xfer, const char *name, int totfiles, int totsize) {
2267 struct irc_file_transfer *ift = find_ift_by_xfer(gc, xfer); 2443 struct irc_file_transfer *ift = find_ift_by_xfer(gc, xfer);
2268 struct sockaddr_in addr; 2444 struct sockaddr_in addr;
2269 char buf[IRC_BUF_LEN]; 2445 char buf[IRC_BUF_LEN];
2270 int len; 2446 int len;
2271 2447
2288 snprintf(buf, sizeof(buf), "\001DCC SEND %s %s %d %d\001\n", name, ift->ip, ift->port, totsize); 2464 snprintf(buf, sizeof(buf), "\001DCC SEND %s %s %d %d\001\n", name, ift->ip, ift->port, totsize);
2289 printf("Trying: %s\n", buf); 2465 printf("Trying: %s\n", buf);
2290 irc_send_im (gc, ift->sn, buf, -1, 0); 2466 irc_send_im (gc, ift->sn, buf, -1, 0);
2291 } 2467 }
2292 2468
2293 static void irc_file_transfer_in(struct gaim_connection *gc, 2469 static void
2470 irc_file_transfer_in(struct gaim_connection *gc,
2294 struct file_transfer *xfer, int offset) { 2471 struct file_transfer *xfer, int offset) {
2295 2472
2296 struct irc_file_transfer *ift = find_ift_by_xfer(gc, xfer); 2473 struct irc_file_transfer *ift = find_ift_by_xfer(gc, xfer);
2297 2474
2298 ift->xfer = xfer; 2475 ift->xfer = xfer;
2299 proxy_connect(ift->ip, ift->port, dcc_recv_callback, ift); 2476 proxy_connect(ift->ip, ift->port, dcc_recv_callback, ift);
2300 } 2477 }
2301 2478
2302 static void irc_ctcp_clientinfo(struct gaim_connection *gc, char *who) 2479 static void
2480 irc_ctcp_clientinfo(struct gaim_connection *gc, char *who)
2303 { 2481 {
2304 char buf[IRC_BUF_LEN]; 2482 char buf[IRC_BUF_LEN];
2305 2483
2306 snprintf (buf, sizeof buf, "\001CLIENTINFO\001\n"); 2484 snprintf (buf, sizeof buf, "\001CLIENTINFO\001");
2307 irc_send_privmsg(gc, who, buf); 2485 irc_send_privmsg(gc, who, buf, FALSE);
2308 } 2486 }
2309 2487
2310 static void irc_ctcp_userinfo(struct gaim_connection *gc, char *who) 2488 static void
2489 irc_ctcp_userinfo(struct gaim_connection *gc, char *who)
2311 { 2490 {
2312 char buf[IRC_BUF_LEN]; 2491 char buf[IRC_BUF_LEN];
2313 2492
2314 snprintf (buf, sizeof buf, "\001USERINFO\001\n"); 2493 snprintf (buf, sizeof buf, "\001USERINFO\001");
2315 irc_send_privmsg(gc, who, buf); 2494 irc_send_privmsg(gc, who, buf, FALSE);
2316 } 2495 }
2317 2496
2318 static void irc_ctcp_version(struct gaim_connection *gc, char *who) 2497 static void
2498 irc_ctcp_version(struct gaim_connection *gc, char *who)
2319 { 2499 {
2320 char buf[IRC_BUF_LEN]; 2500 char buf[IRC_BUF_LEN];
2321 2501
2322 snprintf (buf, sizeof buf, "\001VERSION\001\n"); 2502 snprintf (buf, sizeof buf, "\001VERSION\001");
2323 irc_send_privmsg(gc, who, buf); 2503 irc_send_privmsg(gc, who, buf, FALSE);
2324 } 2504 }
2325 2505
2326 static void irc_ctcp_ping(struct gaim_connection *gc, char *who) 2506 static void
2507 irc_ctcp_ping(struct gaim_connection *gc, char *who)
2327 { 2508 {
2328 char buf[IRC_BUF_LEN]; 2509 char buf[IRC_BUF_LEN];
2329 2510
2330 g_snprintf (buf, sizeof(buf), "\001PING %ul\001\n", time(NULL)); 2511 g_snprintf (buf, sizeof(buf), "\001PING %ul\001", time(NULL));
2331 irc_send_privmsg(gc, who, buf); 2512 irc_send_privmsg(gc, who, buf, FALSE);
2332 } 2513 }
2333 2514
2334 static void irc_send_notice(struct gaim_connection *gc, char *who, char *what) 2515 static void
2335 { 2516 irc_send_notice(struct gaim_connection *gc, char *who, char *what)
2336 char buf[IRC_BUF_LEN]; 2517 {
2518 char buf[IRC_BUF_LEN], *intl;
2337 struct irc_data *id = gc->proto_data; 2519 struct irc_data *id = gc->proto_data;
2338 2520 int len;
2339 g_snprintf(buf, sizeof(buf), "NOTICE %s :%s\r\n", who, what); 2521
2522 intl = irc_send_convert(gc, what, 501, &len);
2523 g_snprintf(buf, sizeof(buf), "NOTICE %s :%s\r\n", who, intl);
2524 g_free(intl);
2340 irc_write(id->fd, buf, strlen(buf)); 2525 irc_write(id->fd, buf, strlen(buf));
2341 } 2526 }
2342 2527
2343 static void irc_send_privmsg(struct gaim_connection *gc, char *who, char *what) 2528 /* Don't call this guy with fragment = 1 for anything but straight
2344 { 2529 * up privmsgs. (no CTCP/whatever) It's still dangerous for CTCPs
2345 char buf[IRC_BUF_LEN]; 2530 * (it might not include the trailing \001), but I think this behavior
2531 * is generally better than not fragmenting at all on lots of our
2532 * packets. */
2533 /* From RFC2812:
2534 * IRC messages are always lines of characters terminated with a CR-LF
2535 * (Carriage Return - Line Feed) pair, and these messages SHALL NOT
2536 * exceed 512 characters in length, counting all characters including
2537 * the trailing CR-LF. Thus, there are 510 characters maximum allowed
2538 * for the command and its parameters. */
2539 /* So apparently that includes all the inter-server crap, which is up
2540 * to NINETY-THREE chars on dancer, which seems to be a pretty liberal
2541 * ircd. My rough calculation for now is ":<nick>!~<user>@<host> ",
2542 * where <host> is a max of an (uncalculated) 63 chars. Thanks to
2543 * trelane and #freenode for giving a hand here. */
2544 static void
2545 irc_send_privmsg(struct gaim_connection *gc, char *who, char *what, gboolean fragment)
2546 {
2547 char buf[IRC_BUF_LEN], *intl;
2346 struct irc_data *id = gc->proto_data; 2548 struct irc_data *id = gc->proto_data;
2347 2549 /* 512 - 12 (for PRIVMSG" "" :""\r\n") - namelen - nicklen - 68 */
2348 g_snprintf(buf, sizeof(buf), "PRIVMSG %s :%s\r\n", who, what); 2550 int nicklen = (gc->user->alias && strlen(gc->user->alias)) ? strlen(gc->user->alias) : 4;
2349 irc_write(id->fd, buf, strlen(buf)); 2551 int max = 444 - strlen(who) - strlen(g_get_user_name()) - nicklen;
2350 } 2552
2351 2553 int len;
2352 static void irc_start_chat(struct gaim_connection *gc, char *who) { 2554
2555 do {
2556 /* the \001 on CTCPs may cause a problem here for some
2557 * charsets, but probably not ones people use for IRC. */
2558 intl = irc_send_convert(gc, what, max, &len);
2559 g_snprintf(buf, sizeof(buf), "PRIVMSG %s :%s\r\n", who, intl);
2560 g_free(intl);
2561 irc_write(id->fd, buf, strlen(buf));
2562 what += len;
2563 } while (fragment && strlen(what));
2564 }
2565
2566 static void
2567 irc_start_chat(struct gaim_connection *gc, char *who) {
2353 struct dcc_chat *chat; 2568 struct dcc_chat *chat;
2354 int len; 2569 int len;
2355 struct sockaddr_in addr; 2570 struct sockaddr_in addr;
2356 char buf[IRC_BUF_LEN]; 2571 char buf[IRC_BUF_LEN];
2357 2572
2379 g_snprintf (buf, sizeof buf, "\001DCC CHAT chat %s %d\001\n", 2594 g_snprintf (buf, sizeof buf, "\001DCC CHAT chat %s %d\001\n",
2380 chat->ip_address, chat->port); 2595 chat->ip_address, chat->port);
2381 irc_send_im (gc, who, buf, -1, 0); 2596 irc_send_im (gc, who, buf, -1, 0);
2382 } 2597 }
2383 2598
2384 static void irc_get_info(struct gaim_connection *gc, char *who) 2599 static void
2600 irc_get_info(struct gaim_connection *gc, char *who)
2385 { 2601 {
2386 struct irc_data *idata = gc->proto_data; 2602 struct irc_data *idata = gc->proto_data;
2387 char buf[IRC_BUF_LEN]; 2603 char buf[IRC_BUF_LEN];
2388 2604
2389 if (*who == '@') 2605 if (*who == '@')
2393 2609
2394 g_snprintf(buf, sizeof(buf), "WHOIS %s\r\n", who); 2610 g_snprintf(buf, sizeof(buf), "WHOIS %s\r\n", who);
2395 irc_write(idata->fd, buf, strlen(buf)); 2611 irc_write(idata->fd, buf, strlen(buf));
2396 } 2612 }
2397 2613
2398 static GList *irc_buddy_menu(struct gaim_connection *gc, char *who) 2614 static GList *
2615 irc_buddy_menu(struct gaim_connection *gc, char *who)
2399 { 2616 {
2400 GList *m = NULL; 2617 GList *m = NULL;
2401 struct proto_buddy_menu *pbm; 2618 struct proto_buddy_menu *pbm;
2402 2619
2403 pbm = g_new0(struct proto_buddy_menu, 1); 2620 pbm = g_new0(struct proto_buddy_menu, 1);
2446 return m; 2663 return m;
2447 } 2664 }
2448 2665
2449 static struct prpl *my_protocol = NULL; 2666 static struct prpl *my_protocol = NULL;
2450 2667
2451 G_MODULE_EXPORT void irc_init(struct prpl *ret) 2668 G_MODULE_EXPORT void
2669 irc_init(struct prpl *ret)
2452 { 2670 {
2453 struct proto_user_opt *puo; 2671 struct proto_user_opt *puo;
2454 ret->protocol = PROTO_IRC; 2672 ret->protocol = PROTO_IRC;
2455 ret->options = OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD; 2673 ret->options = OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD;
2456 ret->name = g_strdup("IRC"); 2674 ret->name = g_strdup("IRC");
2486 puo->label = g_strdup("Port:"); 2704 puo->label = g_strdup("Port:");
2487 puo->def = g_strdup("6667"); 2705 puo->def = g_strdup("6667");
2488 puo->pos = USEROPT_PORT; 2706 puo->pos = USEROPT_PORT;
2489 ret->user_opts = g_list_append(ret->user_opts, puo); 2707 ret->user_opts = g_list_append(ret->user_opts, puo);
2490 2708
2709 puo = g_new0(struct proto_user_opt, 1);
2710 puo->label = g_strdup("Encoding:");
2711 puo->def = g_strdup("ISO-8859-1");
2712 puo->pos = USEROPT_CHARSET;
2713 ret->user_opts = g_list_append(ret->user_opts, puo);
2714
2491 my_protocol = ret; 2715 my_protocol = ret;
2492 } 2716 }
2493 2717
2494 #ifndef STATIC 2718 #ifndef STATIC
2495 G_MODULE_EXPORT void gaim_prpl_init(struct prpl* prpl) 2719 G_MODULE_EXPORT void
2720 gaim_prpl_init(struct prpl* prpl)
2496 { 2721 {
2497 irc_init(prpl); 2722 irc_init(prpl);
2498 prpl->plug->desc.api_version = PLUGIN_API_VERSION; 2723 prpl->plug->desc.api_version = PLUGIN_API_VERSION;
2499 } 2724 }
2500 2725