comparison plugins/irc.c @ 1011:4867280dbdc7

[gaim-migrate @ 1021] The IRC pluggin is getting a little better. It is functional now. It can send and receive messages. It can chat in a channel. That's about all right now. committer: Tailor Script <tailor@pidgin.im>
author Rob Flynn <gaim@robflynn.com>
date Fri, 20 Oct 2000 07:51:03 +0000
parents 1b99caffcd98
children 7e8dcc609b30
comparison
equal deleted inserted replaced
1010:4dca3277ea15 1011:4867280dbdc7
44 #include "gnome_applet_mgr.h" 44 #include "gnome_applet_mgr.h"
45 45
46 #include "pixmaps/cancel.xpm" 46 #include "pixmaps/cancel.xpm"
47 #include "pixmaps/ok.xpm" 47 #include "pixmaps/ok.xpm"
48 48
49 /* FIXME: We shouldn't have hard coded servers and ports :-) */
50 #define IRC_SERVER "irc.mozilla.org"
51 #define IRC_PORT 6667
52
53 #define IRC_BUF_LEN 4096
54
55 static int chat_id = 0;
56
57 struct irc_channel {
58 int id;
59 gchar *name;
60 };
61
62 struct irc_data {
63 int fd;
64
65 GList *channels;
66 };
67
49 static char *irc_name() { 68 static char *irc_name() {
50 return "IRC"; 69 return "IRC";
51 } 70 }
52 71
53 char *name() { 72 char *name() {
56 75
57 char *description() { 76 char *description() {
58 return "Allows gaim to use the IRC protocol"; 77 return "Allows gaim to use the IRC protocol";
59 } 78 }
60 79
80 void irc_join_chat( struct gaim_connection *gc, int id, char *name) {
81 struct irc_data *idata = (struct irc_data *)gc->proto_data;
82 gchar *buf = (gchar *)g_malloc(IRC_BUF_LEN+1);
83
84 g_snprintf(buf, IRC_BUF_LEN, "JOIN %s\n", name);
85 write(idata->fd, buf, strlen(buf));
86
87 g_free(buf);
88 }
89
90 void irc_send_im( struct gaim_connection *gc, char *who, char *message, int away) {
91
92 struct irc_data *idata = (struct irc_data *)gc->proto_data;
93 gchar *buf = (gchar *)g_malloc(IRC_BUF_LEN + 1);
94
95 /* Before we actually send this, we should check to see if they're trying
96 * To issue a /me command and handle it properly. */
97
98 if ( (g_strncasecmp(message, "/me ", 4) == 0) && (strlen(message)>4)) {
99 /* We have /me!! We have /me!! :-) */
100
101 gchar *temp = (gchar *)g_malloc(IRC_BUF_LEN+1);
102 strcpy(temp, message+4);
103 g_snprintf(buf, IRC_BUF_LEN, "PRIVMSG %s :%cACTION %s%c\n", who, '\001', temp, '\001');
104 g_free(temp);
105 }
106 else
107 {
108 g_snprintf(buf, IRC_BUF_LEN, "PRIVMSG %s :%s\n", who, message);
109 }
110
111 write(idata->fd, buf, strlen(buf));
112
113 g_free(buf);
114 }
115
116 int find_id_by_name(struct gaim_connection *gc, char *name) {
117 gchar *temp = (gchar *)g_malloc(IRC_BUF_LEN + 1);
118 GList *templist;
119 struct irc_channel *channel;
120
121 templist = ((struct irc_data *)gc->proto_data)->channels;
122
123 while (templist) {
124 channel = (struct irc_channel *)templist->data;
125
126 g_snprintf(temp, IRC_BUF_LEN, "#%s", channel->name);
127
128 if (g_strcasecmp(temp, name) == 0) {
129 g_free(temp);
130 return channel->id;
131 }
132
133 templist = templist -> next;
134 }
135
136 g_free(temp);
137
138 /* Return -1 if we have no ID */
139 return -1;
140 }
141
142 struct irc_channel * find_channel_by_name(struct gaim_connection *gc, char *name) {
143 gchar *temp = (gchar *)g_malloc(IRC_BUF_LEN + 1);
144 GList *templist;
145 struct irc_channel *channel;
146
147 templist = ((struct irc_data *)gc->proto_data)->channels;
148
149 while (templist) {
150 channel = (struct irc_channel *)templist->data;
151
152 g_snprintf(temp, IRC_BUF_LEN, "%s", channel->name);
153
154 if (g_strcasecmp(temp, name) == 0) {
155 g_free(temp);
156 return channel;
157 }
158
159 templist = templist -> next;
160 }
161
162 g_free(temp);
163
164 /* If we found nothing, return nothing :-) */
165 return NULL;
166 }
167
168 struct irc_channel * find_channel_by_id (struct gaim_connection *gc, int id) {
169 struct irc_data *idata = (struct irc_data *)gc->proto_data;
170 struct irc_channel *channel;
171
172 GList *temp;
173
174 temp = idata->channels;
175
176 while (temp) {
177 channel = (struct irc_channel *)temp->data;
178
179 if (channel->id == id) {
180 /* We've found our man */
181 return channel;
182 }
183
184 temp = temp->next;
185 }
186
187
188 /* If we didnt find one, return NULL */
189 return NULL;
190 }
191
192 void irc_chat_send( struct gaim_connection *gc, int id, char *message) {
193
194 struct irc_data *idata = (struct irc_data *)gc->proto_data;
195 struct irc_channel *channel = g_new0(struct irc_channel, 1);
196 gchar *buf = (gchar *)g_malloc(IRC_BUF_LEN + 1);
197
198 /* First lets get our current channel */
199 channel = find_channel_by_id(gc, id);
200
201
202 if (!channel) {
203 /* If for some reason we've lost our channel, let's bolt */
204 return;
205 }
206
207
208 /* Before we actually send this, we should check to see if they're trying
209 * To issue a /me command and handle it properly. */
210
211 if ( (g_strncasecmp(message, "/me ", 4) == 0) && (strlen(message)>4)) {
212 /* We have /me!! We have /me!! :-) */
213
214 gchar *temp = (gchar *)g_malloc(IRC_BUF_LEN+1);
215 strcpy(temp, message+4);
216 g_snprintf(buf, IRC_BUF_LEN, "PRIVMSG #%s :%cACTION %s%c\n", channel->name, '\001', temp, '\001');
217 g_free(temp);
218 }
219 else
220 {
221 g_snprintf(buf, IRC_BUF_LEN, "PRIVMSG #%s :%s\n", channel->name, message);
222 }
223
224 write(idata->fd, buf, strlen(buf));
225
226 /* Since AIM expects us to receive the message we send, we gotta fake it */
227 serv_got_chat_in(gc, id, gc->username, 0, message);
228
229 g_free(buf);
230 }
231
232 void irc_callback ( struct gaim_connection * gc ) {
233
234 int i = 0;
235 char c;
236 gchar buf[4096];
237 gchar **buf2;
238 int status;
239 struct irc_data *idata;
240
241 idata = (struct irc_data *)gc->proto_data;
242
243 do {
244 status = recv(idata->fd, &c, 1, 0);
245
246 if (!status)
247 {
248 exit(1);
249 }
250 buf[i] = c;
251 i++;
252 } while (c != '\n');
253
254 buf[i] = '\0';
255
256 /* And remove that damned trailing \n */
257 g_strchomp(buf);
258
259 /* For now, lets display everything to the console too. Im such a bitch */
260 printf("IRC:'%'s\n", buf);
261
262 if ( (strstr(buf, " JOIN ")) && (buf[0] == ':') && (!strstr(buf, " NOTICE "))) {
263
264 gchar u_channel[128];
265 struct irc_channel *channel;
266 int id;
267 int j;
268
269 for (j = 0, i = 1; buf[i] != '#'; j++, i++) {
270 }
271
272 i++;
273
274 strcpy(u_channel, buf+i);
275
276 /* Looks like we're going to join the channel for real now. Let's create
277 * a valid channel structure and add it to our list. Let's make sure that
278 * we are not already in a channel first */
279
280 channel = find_channel_by_name(gc, u_channel);
281
282 if (!channel) {
283 chat_id++;
284
285 channel = g_new0(struct irc_channel, 1);
286
287 channel->id = chat_id;
288 channel->name = strdup(u_channel);
289
290 idata->channels = g_list_append(idata->channels, channel);
291
292 serv_got_joined_chat(gc, chat_id, u_channel);
293 printf("IIII: I joined '%s' with a strlen() of '%d'\n", u_channel, strlen(u_channel));
294 } else {
295 /* Someone else joined. */
296 }
297
298 return;
299 }
300
301 if ( (strstr(buf, " PART ")) && (buf[0] == ':') && (!strstr(buf, " NOTICE "))) {
302
303 gchar u_channel[128];
304 gchar u_nick[128];
305
306 struct irc_channel *channel = g_new0(struct irc_channel, 1);
307 int id;
308 int j;
309 GList *test = NULL;
310
311 for (j = 0, i = 1; buf[i] != '!'; j++, i++) {
312 u_nick[j] = buf[i];
313 }
314 u_nick[j] = '\0';
315
316 i++;
317
318 for (j = 0; buf[i] != '#'; j++, i++) {
319 }
320
321 i++;
322
323 strcpy(u_channel, buf+i);
324
325
326 /* Now, lets check to see if it was US that was leaving. If so, do the
327 * correct thing by closing up all of our old channel stuff. Otherwise,
328 * we should just print that someone left */
329
330 if (g_strcasecmp(u_nick, gc->username) == 0) {
331
332 /* Looks like we're going to join the channel for real now. Let's create
333 * a valid channel structure and add it to our list */
334
335 channel = find_channel_by_name(gc, u_channel);
336
337 if (!channel) {
338 return;
339 }
340
341 serv_got_chat_left(gc, channel->id);
342
343 idata->channels = g_list_remove(idata->channels, channel);
344 g_free(channel);
345 return;
346 }
347
348 /* Otherwise, lets just say someone left */
349 printf("%s has left #%s\n", u_nick, u_channel);
350
351 return;
352 }
353
354 if ( (strstr(buf, "PRIVMSG ")) && (buf[0] == ':')) {
355 gchar u_nick[128];
356 gchar u_host[255];
357 gchar u_command[32];
358 gchar u_channel[128];
359 gchar u_message[IRC_BUF_LEN];
360 int j;
361 int msgcode = 0;
362
363 for (j = 0, i = 1; buf[i] != '!'; j++, i++) {
364 u_nick[j] = buf[i];
365 }
366
367 u_nick[j] = '\0'; i++;
368
369 for (j = 0; buf[i] != ' '; j++, i++) {
370 u_host[j] = buf[i];
371 }
372
373 u_host[j] = '\0'; i++;
374
375 for (j = 0; buf[i] != ' '; j++, i++) {
376 u_command[j] = buf[i];
377 }
378
379 u_command[j] = '\0'; i++;
380
381 for (j = 0; buf[i] != ':'; j++, i++) {
382 u_channel[j] = buf[i];
383 }
384
385 u_channel[j-1] = '\0'; i++;
386
387
388 /* Now that everything is parsed, the rest of this baby must be our message */
389 strncpy(u_message, buf + i, IRC_BUF_LEN);
390
391 /* Now, lets check the message to see if there's anything special in it */
392 if (u_message[0] == '\001') {
393 if (g_strncasecmp(u_message, "\001ACTION ", 8) == 0) {
394 /* Looks like we have an action. Let's parse it a little */
395 strcpy(buf, u_message);
396
397 strcpy(u_message, "/me ");
398 for (j = 4, i = 8; buf[i] != '\001'; i++, j++) {
399 u_message[j] = buf[i];
400 }
401 u_message[j] = '\0';
402 }
403 }
404
405
406 /* Let's check to see if we have a channel on our hands */
407 if (u_channel[0] == '#') {
408 /* Yup. We have a channel */
409 int id;
410
411 id = find_id_by_name(gc, u_channel);
412 if (id != -1) {
413 serv_got_chat_in(gc, id, u_nick, 0, u_message);
414 }
415 }
416 else {
417 /* Nope. Let's treat it as a private message */
418 printf("JUST GOT AN IM!!\n");
419 serv_got_im(gc, u_nick, u_message, 0);
420 }
421
422 return;
423 }
424
425 /* Let's parse PING requests so that we wont get booted for inactivity */
426
427 if (strncmp(buf, "PING :", 6) == 0) {
428 buf2 = g_strsplit(buf, ":", 1);
429
430 /* Let's build a new response */
431 g_snprintf(buf, IRC_BUF_LEN, "PONG :%s\n", buf2[1]);
432 write(idata->fd, buf, strlen(buf));
433
434 /* And clean up after ourselves */
435 g_strfreev(buf2);
436
437 return;
438 }
439
440 }
441
442 void irc_handler(gpointer data, gint source, GdkInputCondition condition) {
443 irc_callback(data);
444 }
445
446 void irc_close(struct gaim_connection *gc) {
447 struct irc_data *idata = (struct irc_data *)gc->proto_data;
448 gchar *buf = (gchar *)g_malloc(IRC_BUF_LEN);
449
450 g_snprintf(buf, IRC_BUF_LEN, "QUIT :GAIM [www.marko.net/gaim]\n");
451 write(idata->fd, buf, strlen(buf));
452
453 g_free(buf);
454 close(idata->fd);
455 g_free(gc->proto_data);
456 }
457
458 void irc_chat_leave(struct gaim_connection *gc, int id) {
459 struct irc_data *idata = (struct irc_data *)gc->proto_data;
460 struct irc_channel *channel;
461 gchar *buf = (gchar *)g_malloc(IRC_BUF_LEN+1);
462
463 channel = find_channel_by_id(gc, id);
464
465 if (!channel) {
466 return;
467 }
468
469 g_snprintf(buf, IRC_BUF_LEN, "PART #%s\n", channel->name);
470 write(idata->fd, buf, strlen(buf));
471
472 g_free(buf);
473 }
474
61 void irc_login(struct aim_user *user) { 475 void irc_login(struct aim_user *user) {
62 476 int fd;
63 } 477 struct hostent *host;
64 478 struct sockaddr_in site;
479 char buf[4096];
480
481 struct gaim_connection *gc = new_gaim_conn(PROTO_IRC, user->username, user->password);
482 struct irc_data *idata = gc->proto_data = g_new0(struct irc_data, 1);
483 char c;
484 int i;
485 int status;
486
487 set_login_progress(gc, 1, buf);
488
489 while (gtk_events_pending())
490 gtk_main_iteration();
491
492 host = gethostbyname(IRC_SERVER);
493 if (!host) {
494 hide_login_progress(gc, "Unable to resolve hostname");
495 destroy_gaim_conn(gc);
496 return;
497 }
498
499 site.sin_family = AF_INET;
500 site.sin_addr.s_addr = *(long *)(host->h_addr);
501 site.sin_port = htons(IRC_PORT);
502
503 fd = socket(AF_INET, SOCK_STREAM, 0);
504 if (fd < 0) {
505 hide_login_progress(gc, "Unable to create socket");
506 destroy_gaim_conn(gc);
507 return;
508 }
509
510 if (connect(fd, (struct sockaddr *)&site, sizeof(site)) < 0) {
511 hide_login_progress(gc, "Unable to connect.");
512 destroy_gaim_conn(gc);
513 return;
514 }
515
516 idata->fd = fd;
517
518 g_snprintf(buf, sizeof(buf), "Signon: %s", gc->username);
519 set_login_progress(gc, 2, buf);
520
521 /* This is where we will attempt to sign on */
522
523 /* FIXME: This should be their servername, not their username. im just lazy right now */
524
525 g_snprintf(buf, 4096, "NICK %s\nUSER %s localhost %s :GAIM (www.marko.net/gaim)\n", gc->username, gc->username, gc->username);
526 write(idata->fd, buf, strlen(buf));
527
528
529 /* Now lets sign ourselves on */
530 account_online(gc);
531
532 if (mainwindow)
533 gtk_widget_hide(mainwindow);
534
535 show_buddy_list();
536 refresh_buddy_window();
537
538 serv_finish_login(gc);
539 gaim_setup(gc);
540
541 gc->inpa = gdk_input_add(idata->fd, GDK_INPUT_READ, irc_handler, gc);
542 }
65 543
66 struct prpl *irc_init() { 544 struct prpl *irc_init() {
67 struct prpl *ret = g_new0(struct prpl, 1); 545 struct prpl *ret = g_new0(struct prpl, 1);
68 546
69 ret->protocol = PROTO_IRC; 547 ret->protocol = PROTO_IRC;
70 ret->name = irc_name; 548 ret->name = irc_name;
71 ret->login = irc_login; 549 ret->login = irc_login;
72 ret->close = NULL; 550 ret->close = irc_close;
73 ret->send_im = NULL; 551 ret->send_im = irc_send_im;
74 ret->set_info = NULL; 552 ret->set_info = NULL;
75 ret->get_info = NULL; 553 ret->get_info = NULL;
76 ret->set_away = NULL; 554 ret->set_away = NULL;
77 ret->get_away_msg = NULL; 555 ret->get_away_msg = NULL;
78 ret->set_dir = NULL; 556 ret->set_dir = NULL;
85 ret->remove_buddy = NULL; 563 ret->remove_buddy = NULL;
86 ret->add_permit = NULL; 564 ret->add_permit = NULL;
87 ret->add_deny = NULL; 565 ret->add_deny = NULL;
88 ret->warn = NULL; 566 ret->warn = NULL;
89 ret->accept_chat = NULL; 567 ret->accept_chat = NULL;
90 ret->join_chat = NULL; 568 ret->join_chat = irc_join_chat;
91 ret->chat_invite = NULL; 569 ret->chat_invite = NULL;
92 ret->chat_leave = NULL; 570 ret->chat_leave = irc_chat_leave;
93 ret->chat_whisper = NULL; 571 ret->chat_whisper = NULL;
94 ret->chat_send = NULL; 572 ret->chat_send = irc_chat_send;
95 ret->keepalive = NULL; 573 ret->keepalive = NULL;
96 574
97 return ret; 575 return ret;
98 } 576 }
99 577