Mercurial > pidgin
annotate src/protocols/irc/irc.c @ 2138:cfa83a1b3d49
[gaim-migrate @ 2148]
hopefully fixes any problems we might have with icq. also makes it so we can receive messages from people whose names are longer than 64 characters. this should be arbitrary.
committer: Tailor Script <tailor@pidgin.im>
| author | Eric Warmenhoven <eric@warmenhoven.org> |
|---|---|
| date | Wed, 08 Aug 2001 20:09:57 +0000 |
| parents | 18722ae5b882 |
| children | 134058953a43 |
| rev | line source |
|---|---|
| 2086 | 1 /* |
| 2 * gaim - IRC Protocol Plugin | |
| 3 * | |
| 4 * Copyright (C) 2000-2001, Rob Flynn <rob@tgflinux.com> | |
| 5 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
| 6 * | |
| 7 * This program is free software; you can redistribute it and/or modify | |
| 8 * it under the terms of the GNU General Public License as published by | |
| 9 * the Free Software Foundation; either version 2 of the License, or | |
| 10 * (at your option) any later version. | |
| 11 * | |
| 12 * This program is distributed in the hope that it will be useful, | |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 * GNU General Public License for more details. | |
| 16 * | |
| 17 * You should have received a copy of the GNU General Public License | |
| 18 * along with this program; if not, write to the Free Software | |
| 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 * | |
| 21 */ | |
| 22 | |
|
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
23 #include <config.h> |
| 2086 | 24 |
| 25 | |
| 26 #include <netdb.h> | |
| 27 #include <gtk/gtk.h> | |
| 28 #include <unistd.h> | |
| 29 #include <errno.h> | |
| 30 #include <netinet/in.h> | |
| 31 #include <arpa/inet.h> | |
| 32 #include <fcntl.h> | |
| 33 #include <string.h> | |
| 34 #include <stdlib.h> | |
| 35 #include <stdio.h> | |
| 36 #include <time.h> | |
| 37 #include <sys/socket.h> | |
| 38 #include <sys/stat.h> | |
| 39 #include <ctype.h> | |
| 40 #include "multi.h" | |
| 41 #include "prpl.h" | |
| 42 #include "gaim.h" | |
| 43 #include "proxy.h" | |
| 44 | |
| 45 #include "pixmaps/free_icon.xpm" | |
| 46 | |
| 47 #define IRC_BUF_LEN 4096 | |
| 48 | |
| 49 | |
| 50 #define USEROPT_SERV 0 | |
| 51 #define USEROPT_PORT 1 | |
| 52 | |
| 53 static int chat_id = 0; | |
| 54 | |
| 55 struct irc_channel { | |
| 56 int id; | |
| 57 gchar *name; | |
| 58 }; | |
| 59 | |
| 60 struct irc_data { | |
| 61 int fd; | |
| 62 int inpa; /* used for non-block logins */ | |
| 63 | |
| 64 int timer; | |
| 65 | |
| 66 int totalblocks; | |
| 67 int recblocks; | |
| 68 | |
| 69 GSList *templist; | |
| 70 GList *channels; | |
| 71 }; | |
| 72 | |
| 73 static char *irc_name() | |
| 74 { | |
| 75 return "IRC"; | |
| 76 } | |
| 77 | |
| 78 static void irc_get_info(struct gaim_connection *gc, char *who); | |
| 79 | |
| 80 static void irc_join_chat(struct gaim_connection *gc, int id, char *name) | |
| 81 { | |
| 82 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 83 gchar *buf = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 84 | |
| 85 g_snprintf(buf, IRC_BUF_LEN, "JOIN %s\n", name); | |
| 86 write(idata->fd, buf, strlen(buf)); | |
| 87 write(idata->fd, buf, strlen(buf)); | |
| 88 | |
| 89 g_free(buf); | |
| 90 } | |
| 91 | |
| 92 static void irc_update_user(struct gaim_connection *gc, char *name, int status) | |
| 93 { | |
| 94 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 95 struct irc_channel *u; | |
| 96 GSList *temp = idata->templist; | |
| 97 | |
| 98 /* Loop through our list */ | |
| 99 | |
| 100 while (temp) { | |
| 101 u = (struct irc_channel *)temp->data; | |
| 102 if (g_strcasecmp(u->name, name) == 0) { | |
| 103 u->id = status; | |
| 104 return; | |
| 105 } | |
| 106 | |
| 107 temp = g_slist_next(temp); | |
| 108 } | |
| 109 return; | |
| 110 } | |
| 111 | |
|
2137
18722ae5b882
[gaim-migrate @ 2147]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2131
diff
changeset
|
112 static gboolean irc_request_buddy_update(gpointer data) |
| 2086 | 113 { |
|
2137
18722ae5b882
[gaim-migrate @ 2147]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2131
diff
changeset
|
114 struct gaim_connection *gc = data; |
| 2086 | 115 struct irc_data *idata = (struct irc_data *)gc->proto_data; |
| 116 GSList *grp = gc->groups; | |
| 117 GSList *person; | |
| 118 struct group *g; | |
| 119 struct buddy *b; | |
| 120 struct irc_channel *u; | |
| 121 | |
| 122 if (idata->templist != NULL) | |
|
2137
18722ae5b882
[gaim-migrate @ 2147]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2131
diff
changeset
|
123 return TRUE; |
| 2086 | 124 |
| 125 idata->recblocks = 0; | |
| 126 idata->totalblocks = 1; | |
| 127 | |
| 128 /* First, let's check to see if we have anyone on our buddylist */ | |
| 129 if (!grp) { | |
|
2131
acc11216ec5d
[gaim-migrate @ 2141]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2123
diff
changeset
|
130 return TRUE; |
| 2086 | 131 } |
| 132 | |
| 133 /* Send the first part of our request */ | |
| 134 write(idata->fd, "ISON", 4); | |
| 135 | |
| 136 /* Step through our list of groups */ | |
| 137 while (grp) { | |
| 138 | |
| 139 g = (struct group *)grp->data; | |
| 140 person = g->members; | |
| 141 | |
| 142 while (person) { | |
| 143 b = (struct buddy *)person->data; | |
| 144 | |
| 145 /* We will store our buddy info here. I know, this is cheap | |
| 146 * but hey, its the exact same data structure. Why should we | |
| 147 * bother with making another one */ | |
| 148 | |
| 149 u = g_new0(struct irc_channel, 1); | |
| 150 u->id = 0; /* Assume by default that they're offline */ | |
| 151 u->name = strdup(b->name); | |
| 152 | |
| 153 write(idata->fd, " ", 1); | |
| 154 write(idata->fd, u->name, strlen(u->name)); | |
| 155 idata->templist = g_slist_append(idata->templist, u); | |
| 156 | |
| 157 person = person->next; | |
| 158 } | |
| 159 | |
| 160 grp = g_slist_next(grp); | |
| 161 } | |
| 162 write(idata->fd, "\n", 1); | |
|
2131
acc11216ec5d
[gaim-migrate @ 2141]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2123
diff
changeset
|
163 return TRUE; |
| 2086 | 164 } |
| 165 | |
| 166 | |
|
2123
56c4382f2909
[gaim-migrate @ 2133]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2100
diff
changeset
|
167 static int irc_send_im(struct gaim_connection *gc, char *who, char *message, int away) |
| 2086 | 168 { |
| 169 | |
| 170 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 171 gchar *buf = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 172 | |
| 173 if (who[0] == '@' || who[0] == '+') { | |
| 174 | |
| 175 /* If the user trys to msg an op or a voice from the channel, the convo will try | |
| 176 * to send it to @nick or +nick... needless to say, this is undesirable. | |
| 177 */ | |
| 178 who++; | |
| 179 } | |
| 180 | |
| 181 /* Before we actually send this, we should check to see if they're trying | |
| 182 * To issue a command and handle it properly. */ | |
| 183 | |
| 184 if (message[0] == '/') { | |
| 185 /* I'll change the implementation of this a little later :-) */ | |
| 186 if ((g_strncasecmp(message, "/me ", 4) == 0) && (strlen(message) > 4)) { | |
| 187 /* We have /me!! We have /me!! :-) */ | |
| 188 | |
| 189 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 190 strcpy(temp, message + 4); | |
| 191 g_snprintf(buf, IRC_BUF_LEN, "PRIVMSG %s :%cACTION %s%c\n", who, '\001', temp, | |
| 192 '\001'); | |
| 193 g_free(temp); | |
| 194 } else if (!g_strncasecmp(message, "/whois ", 7) && (strlen(message) > 7)) { | |
| 195 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 196 strcpy(temp, message + 7); | |
| 197 irc_get_info(gc, temp); | |
| 198 g_free(temp); | |
| 199 | |
|
2123
56c4382f2909
[gaim-migrate @ 2133]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2100
diff
changeset
|
200 return 0; |
| 2086 | 201 } |
| 202 | |
| 203 } else { | |
| 204 g_snprintf(buf, IRC_BUF_LEN, "PRIVMSG %s :%s\n", who, message); | |
| 205 } | |
| 206 | |
| 207 write(idata->fd, buf, strlen(buf)); | |
| 208 | |
| 209 g_free(buf); | |
|
2123
56c4382f2909
[gaim-migrate @ 2133]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2100
diff
changeset
|
210 return 0; |
| 2086 | 211 } |
| 212 | |
| 213 static int find_id_by_name(struct gaim_connection *gc, char *name) | |
| 214 { | |
| 215 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 216 GList *templist; | |
| 217 struct irc_channel *channel; | |
| 218 | |
| 219 templist = ((struct irc_data *)gc->proto_data)->channels; | |
| 220 | |
| 221 while (templist) { | |
| 222 channel = (struct irc_channel *)templist->data; | |
| 223 | |
| 224 g_snprintf(temp, IRC_BUF_LEN, "#%s", channel->name); | |
| 225 | |
| 226 if (g_strcasecmp(temp, name) == 0) { | |
| 227 g_free(temp); | |
| 228 return channel->id; | |
| 229 } | |
| 230 | |
| 231 templist = templist->next; | |
| 232 } | |
| 233 | |
| 234 g_free(temp); | |
| 235 | |
| 236 /* Return -1 if we have no ID */ | |
| 237 return -1; | |
| 238 } | |
| 239 | |
| 240 static struct irc_channel *find_channel_by_name(struct gaim_connection *gc, char *name) | |
| 241 { | |
| 242 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 243 GList *templist; | |
| 244 struct irc_channel *channel; | |
| 245 | |
| 246 templist = ((struct irc_data *)gc->proto_data)->channels; | |
| 247 | |
| 248 while (templist) { | |
| 249 channel = (struct irc_channel *)templist->data; | |
| 250 | |
| 251 g_snprintf(temp, IRC_BUF_LEN, "%s", channel->name); | |
| 252 | |
| 253 if (g_strcasecmp(temp, name) == 0) { | |
| 254 g_free(temp); | |
| 255 return channel; | |
| 256 } | |
| 257 | |
| 258 templist = templist->next; | |
| 259 } | |
| 260 | |
| 261 g_free(temp); | |
| 262 | |
| 263 /* If we found nothing, return nothing :-) */ | |
| 264 return NULL; | |
| 265 } | |
| 266 | |
| 267 static struct irc_channel *find_channel_by_id(struct gaim_connection *gc, int id) | |
| 268 { | |
| 269 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 270 struct irc_channel *channel; | |
| 271 | |
| 272 GList *temp; | |
| 273 | |
| 274 temp = idata->channels; | |
| 275 | |
| 276 while (temp) { | |
| 277 channel = (struct irc_channel *)temp->data; | |
| 278 | |
| 279 if (channel->id == id) { | |
| 280 /* We've found our man */ | |
| 281 return channel; | |
| 282 } | |
| 283 | |
| 284 temp = temp->next; | |
| 285 } | |
| 286 | |
| 287 | |
| 288 /* If we didnt find one, return NULL */ | |
| 289 return NULL; | |
| 290 } | |
| 291 | |
| 292 static struct conversation *find_chat(struct gaim_connection *gc, char *name) | |
| 293 { | |
| 294 GSList *bcs = gc->buddy_chats; | |
| 295 struct conversation *b = NULL; | |
| 296 char *chat = g_strdup(normalize(name)); | |
| 297 | |
| 298 while (bcs) { | |
| 299 b = bcs->data; | |
| 300 if (!strcasecmp(normalize(b->name), chat)) | |
| 301 break; | |
| 302 b = NULL; | |
| 303 bcs = bcs->next; | |
| 304 } | |
| 305 | |
| 306 g_free(chat); | |
| 307 return b; | |
| 308 } | |
| 309 | |
| 310 static void irc_chat_leave(struct gaim_connection *gc, int id); | |
| 311 static void irc_chat_send(struct gaim_connection *gc, int id, char *message) | |
| 312 { | |
| 313 | |
| 314 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 315 struct irc_channel *channel = NULL; | |
| 316 gchar *buf = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 317 char **kick; | |
| 318 gboolean is_command = FALSE; | |
| 319 /* First lets get our current channel */ | |
| 320 channel = find_channel_by_id(gc, id); | |
| 321 | |
| 322 | |
| 323 if (!channel) { | |
| 324 /* If for some reason we've lost our channel, let's bolt */ | |
| 325 g_free(buf); | |
| 326 return; | |
| 327 } | |
| 328 | |
| 329 | |
| 330 /* Before we actually send this, we should check to see if they're trying | |
| 331 * To issue a command and handle it properly. */ | |
| 332 | |
| 333 if (message[0] == '/') { | |
| 334 | |
| 335 if ((g_strncasecmp(message, "/me ", 4) == 0) && (strlen(message) > 4)) { | |
| 336 /* We have /me!! We have /me!! :-) */ | |
| 337 | |
| 338 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 339 strcpy(temp, message + 4); | |
| 340 | |
| 341 g_snprintf(buf, IRC_BUF_LEN, "PRIVMSG #%s :%cACTION %s%c\n", channel->name, | |
| 342 '\001', temp, '\001'); | |
| 343 g_free(temp); | |
| 344 } else if ((g_strncasecmp(message, "/op ", 4) == 0) && (strlen(message) > 4)) { | |
| 345 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 346 strcpy(temp, message + 4); | |
| 347 | |
| 348 g_snprintf(buf, IRC_BUF_LEN, "MODE #%s +o %s\n", channel->name, temp); | |
| 349 | |
| 350 g_free(temp); | |
| 351 is_command = TRUE; | |
| 352 | |
| 353 } else if ((g_strncasecmp(message, "/deop ", 6) == 0) && (strlen(message) > 6)) { | |
| 354 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 355 strcpy(temp, message + 6); | |
| 356 g_snprintf(buf, IRC_BUF_LEN, "MODE #%s -o %s\n", channel->name, temp); | |
| 357 | |
| 358 g_free(temp); | |
| 359 is_command = TRUE; | |
| 360 } | |
| 361 | |
| 362 else if ((g_strncasecmp(message, "/voice ", 7) == 0) && (strlen(message) > 7)) { | |
| 363 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 364 strcpy(temp, message + 7); | |
| 365 | |
| 366 g_snprintf(buf, IRC_BUF_LEN, "MODE #%s +v %s\n", channel->name, temp); | |
| 367 | |
| 368 g_free(temp); | |
| 369 is_command = TRUE; | |
| 370 | |
| 371 } else if ((g_strncasecmp(message, "/devoice ", 9) == 0) && (strlen(message) > 9)) { | |
| 372 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 373 strcpy(temp, message + 6); | |
| 374 g_snprintf(buf, IRC_BUF_LEN, "MODE #%s -v %s\n", channel->name, temp); | |
| 375 | |
| 376 g_free(temp); | |
| 377 is_command = TRUE; | |
| 378 } else if ((g_strncasecmp(message, "/mode ", 6) == 0) && (strlen(message) > 6)) { | |
| 379 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 380 strcpy(temp, message + 6); | |
| 381 g_snprintf(buf, IRC_BUF_LEN, "MODE #%s %s\n", channel->name, temp); | |
| 382 g_free(temp); | |
| 383 is_command = TRUE; | |
| 384 } | |
| 385 | |
| 386 else if (!g_strncasecmp(message, "/whois ", 7) && (strlen(message) > 7)) { | |
| 387 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 388 | |
| 389 strcpy(temp, message + 7); | |
| 390 irc_get_info(gc, temp); | |
| 391 g_free(temp); | |
| 392 is_command = TRUE; | |
| 393 | |
| 394 } | |
| 395 | |
| 396 else if (!g_strncasecmp(message, "/topic ", 7) && (strlen(message) > 7)) { | |
| 397 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 398 strcpy(temp, message + 7); | |
| 399 | |
| 400 /* Send the chat topic change request */ | |
| 401 serv_chat_set_topic(gc, id, temp); | |
| 402 | |
| 403 g_free(temp); | |
| 404 is_command = TRUE; | |
| 405 } | |
| 406 | |
| 407 else if (!g_strncasecmp(message, "/part", 5) && (strlen(message) == 5)) { | |
| 408 | |
| 409 /* If I'm not mistaken, the chat_leave command was coded under the | |
| 410 * pretense that it would only occur when someone closed the window. | |
| 411 * For this reason, the /part command will not close the window. Nor | |
| 412 * will the window close when the user is /kicked. I'll let you decide | |
| 413 * the best way to fix it--I'd imagine it'd just be a little line like | |
| 414 * if (convo) close (convo), but I'll let you decide where to put it. | |
| 415 */ | |
| 416 | |
| 417 irc_chat_leave(gc, id); | |
| 418 is_command = TRUE; | |
| 419 return; | |
| 420 | |
| 421 | |
| 422 } | |
| 423 | |
| 424 else if (!g_strncasecmp(message, "/join ", 6) && (strlen(message) > 6)) { | |
| 425 | |
| 426 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 427 | |
| 428 strcpy(temp, message + 6); | |
| 429 | |
| 430 | |
| 431 irc_join_chat(gc, 0, temp); | |
| 432 g_free(temp); | |
| 433 is_command = TRUE; | |
| 434 return; | |
| 435 } | |
| 436 | |
| 437 else if (!g_strncasecmp(message, "/raw ", 5) && (strlen(message) > 5)) { | |
| 438 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 439 strcpy(temp, message + 5); | |
| 440 g_snprintf(buf, IRC_BUF_LEN, "%s\r\n", temp); | |
| 441 g_free(temp); | |
| 442 is_command = TRUE; | |
| 443 } | |
| 444 | |
| 445 else if (!g_strncasecmp(message, "/quote ", 7) && (strlen(message) > 7)) { | |
| 446 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 447 strcpy(temp, message + 7); | |
| 448 g_snprintf(buf, IRC_BUF_LEN, "%s\r\n", temp); | |
| 449 g_free(temp); | |
| 450 is_command = TRUE; | |
| 451 } | |
| 452 | |
| 453 else if (!g_strncasecmp(message, "/kick ", 6) && (strlen(message) > 6)) { | |
| 454 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 455 strcpy(temp, message + 6); | |
| 456 kick = g_strsplit(temp, " ", 2); | |
| 457 g_snprintf(buf, IRC_BUF_LEN, "KICK #%s %s :%s\r\n", channel->name, kick[0], | |
| 458 kick[1]); | |
| 459 g_free(temp); | |
| 460 is_command = TRUE; | |
| 461 } | |
| 462 | |
| 463 /* FIXME: I'll go back in and grab this later. -- Rob */ | |
| 464 /* | |
| 465 I THOUGHT THIS WOULD WORK, BUT I WAS WRONG. WOULD SOMEONE KINDLY FIX IT? | |
| 466 | |
| 467 | |
| 468 else if (!g_strncasecmp(message, "/help", 5)) { | |
| 469 gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 470 strcpy(temp, message + 5); | |
| 471 if (temp == "") { | |
| 472 | |
| 473 serv_got_chat_in(gc, id, "gAIM", 0, "Available Commands:"); | |
| 474 serv_got_chat_in(gc, id, "gAIM", 0, " "); | |
| 475 serv_got_chat_in(gc, id, "gAIM", 0, "<b>op voice kick </b>"); | |
| 476 serv_got_chat_in(gc, id, "gAIM", 0, "<b>deop devoice whois</b>"); | |
| 477 serv_got_chat_in(gc, id, "gAIM", 0, "<b>me raw quote</b>"); | |
| 478 serv_got_chat_in(gc, id, "gAIM", 0, "<b>mode</b>"); | |
| 479 } | |
| 480 else { | |
| 481 serv_got_chat_in(gc, id, "gAIM", 0, "Usage: "); | |
| 482 if (temp == "op") | |
| 483 serv_got_chat_in(gc, id, "gAIM", 0, "<b>/op <nick></b> - Gives operator status to user."); | |
| 484 else if (temp == "deop") | |
| 485 serv_got_chat_in(gc, id, "gAIM", 0, "<b>/deop <nick></b> - Removes operator status from user."); | |
| 486 else if (temp == "me") | |
| 487 serv_got_chat_in(gc, id, "gAIM", 0, "<b>/me <action></b> - Sends an action to the channel."); | |
| 488 else if (temp == "mode") | |
| 489 serv_got_chat_in(gc, id, "gAIM", 0, "<b>/mode {[+|-}|o|p|s|i|t|n|b|v} [<limit][<nick>][<ban mask]</b> - Changes channel and user modes."); | |
| 490 else if (temp == "voice") | |
| 491 serv_got_chat_in(gc, id, "gAIM", 0, "<b>/voice <nick></b> - Gives voice status to user."); | |
| 492 else if (temp == "devoice") | |
| 493 serv_got_chat_in(gc, id, "gAIM", 0, "<b>/devoice <nick></b> - Removes voice status from user."); | |
| 494 else if (temp == "raw") | |
| 495 serv_got_chat_in(gc, id, "gAIM", 0, "<b>/raw <text></b> - Sends raw text to the server."); | |
| 496 else if (temp == "kick") | |
| 497 serv_got_chat_in(gc, id, "gAIM", 0, "<b>/kick [<comment>]</b> - Kicks a user out of the channel."); | |
| 498 else if (temp == "whois") | |
| 499 serv_got_chat_in(gc, id, "gAIM", 0, "<b>/whois <nick></b> - Gets information about user."); | |
| 500 else if (temp == "quote") | |
| 501 serv_got_chat_in(gc, id, "gAIM", 0, "<b>/raw <text></b> - Sends raw text to the server."); | |
| 502 else | |
| 503 serv_got_chat_in(gc, id, "gAIM", 0, "No such command."); | |
| 504 } | |
| 505 | |
| 506 g_free(temp); | |
| 507 is_command = TRUE; | |
| 508 } | |
| 509 */ | |
| 510 | |
| 511 } | |
| 512 | |
| 513 else { | |
| 514 g_snprintf(buf, IRC_BUF_LEN, "PRIVMSG #%s :%s\n", channel->name, message); | |
| 515 | |
| 516 } | |
| 517 | |
| 518 | |
| 519 write(idata->fd, buf, strlen(buf)); | |
| 520 | |
| 521 /* Since AIM expects us to receive the message we send, we gotta fake it */ | |
| 522 if (is_command == FALSE) | |
| 523 serv_got_chat_in(gc, id, gc->username, 0, message, time((time_t) NULL)); | |
| 524 | |
| 525 g_free(buf); | |
| 526 | |
| 527 | |
| 528 } | |
| 529 static struct conversation *find_conversation_by_id(struct gaim_connection *gc, int id) | |
| 530 { | |
| 531 GSList *bc = gc->buddy_chats; | |
| 532 struct conversation *b = NULL; | |
| 533 | |
| 534 while (bc) { | |
| 535 b = (struct conversation *)bc->data; | |
| 536 if (id == b->id) { | |
| 537 break; | |
| 538 } | |
| 539 bc = bc->next; | |
| 540 b = NULL; | |
| 541 } | |
| 542 | |
| 543 if (!b) { | |
| 544 return NULL; | |
| 545 } | |
| 546 | |
| 547 return b; | |
| 548 } | |
| 549 | |
| 550 static struct conversation *find_conversation_by_name(struct gaim_connection *gc, char *name) | |
| 551 { | |
| 552 GSList *bc = gc->buddy_chats; | |
| 553 struct conversation *b = NULL; | |
| 554 | |
| 555 while (bc) { | |
| 556 b = (struct conversation *)bc->data; | |
| 557 | |
| 558 if (g_strcasecmp(name, b->name) == 0) { | |
| 559 break; | |
| 560 } | |
| 561 bc = bc->next; | |
| 562 b = NULL; | |
| 563 } | |
| 564 | |
| 565 if (!b) { | |
| 566 return NULL; | |
| 567 } | |
| 568 | |
| 569 return b; | |
| 570 } | |
| 571 | |
| 572 | |
| 573 | |
|
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
574 static void irc_callback(gpointer data, gint source, GaimInputCondition condition) |
| 2086 | 575 { |
| 576 struct gaim_connection *gc = data; | |
| 577 int i = 0; | |
| 578 gchar buf[4096]; | |
| 579 gchar **buf2; | |
| 580 struct irc_data *idata; | |
| 581 | |
| 582 idata = (struct irc_data *)gc->proto_data; | |
| 583 | |
| 584 | |
| 585 do { | |
| 586 if (read(idata->fd, buf + i, 1) < 0) { | |
| 587 hide_login_progress(gc, "Read error"); | |
| 588 signoff(gc); | |
| 589 return; | |
| 590 } | |
| 591 } while (buf[i++] != '\n'); | |
| 592 | |
| 593 buf[--i] = '\0'; | |
| 594 g_strchomp(buf); | |
| 595 g_print("%s\n", buf); | |
| 596 | |
| 597 /* Check for errors */ | |
| 598 | |
| 599 if (((strstr(buf, "ERROR :") && (!strstr(buf, "PRIVMSG ")) && | |
| 600 (!strstr(buf, "NOTICE ")) && (strlen(buf) > 7)))) { | |
| 601 | |
| 602 gchar *u_errormsg; | |
| 603 | |
| 604 /* Let's get our error message */ | |
| 605 u_errormsg = g_strdup(buf + 7); | |
| 606 | |
| 607 /* We got our error message. Now, let's reaise an | |
| 608 * error dialog */ | |
| 609 | |
| 610 do_error_dialog(u_errormsg, "Gaim: IRC Error"); | |
| 611 | |
| 612 /* And our necessary garbage collection */ | |
| 613 g_free(u_errormsg); | |
| 614 return; | |
| 615 } | |
| 616 | |
| 617 /* This should be a whois response. I only care about the first (311) one. I might do | |
| 618 * the other's later. They're boring. */ | |
| 619 | |
| 620 if (((strstr(buf, " 311 ")) && (!strstr(buf, "PRIVMSG")) && (!strstr(buf, "NOTICE")))) { | |
| 621 char **res; | |
| 622 | |
| 623 res = g_strsplit(buf, " ", 7); | |
| 624 | |
| 625 if (!strcmp(res[1], "311")) { | |
| 626 char buf[8192]; | |
| 627 | |
| 628 g_snprintf(buf, 4096, "<b>Nick:</b> %s<br>" | |
| 629 "<b>Host:</b> %s@%s<br>" | |
| 630 "<b>Name:</b> %s<br>", res[3], res[4], res[5], res[7] + 1); | |
| 631 | |
|
2137
18722ae5b882
[gaim-migrate @ 2147]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2131
diff
changeset
|
632 g_show_info_text(buf, NULL); |
| 2086 | 633 } |
| 634 | |
| 635 g_strfreev(res); | |
| 636 return; | |
| 637 } | |
| 638 | |
| 639 /* Autoresponse to an away message */ | |
| 640 if (((strstr(buf, " 301 ")) && (!strstr(buf, "PRIVMSG")) && (!strstr(buf, "NOTICE")))) { | |
| 641 char **res; | |
| 642 | |
| 643 res = g_strsplit(buf, " ", 5); | |
| 644 | |
| 645 if (!strcmp(res[1], "301")) | |
| 646 serv_got_im(gc, res[3], res[4] + 1, 1, time((time_t) NULL)); | |
| 647 | |
| 648 g_strfreev(res); | |
| 649 return; | |
| 650 } | |
| 651 | |
| 652 /* Parse the list of names that we receive when we first sign on to | |
| 653 * a channel */ | |
| 654 | |
| 655 if (((strstr(buf, " 353 ")) && (!strstr(buf, "PRIVMSG")) && (!strstr(buf, "NOTICE")))) { | |
| 656 gchar u_host[255]; | |
| 657 gchar u_command[32]; | |
| 658 gchar u_channel[128]; | |
| 659 gchar u_names[IRC_BUF_LEN + 1]; | |
| 660 struct conversation *convo = NULL; | |
| 661 int j; | |
| 662 | |
| 663 for (j = 0, i = 0; buf[i] != ' '; j++, i++) { | |
| 664 u_host[j] = buf[i]; | |
| 665 } | |
| 666 | |
| 667 u_host[j] = '\0'; | |
| 668 i++; | |
| 669 | |
| 670 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 671 u_command[j] = buf[i]; | |
| 672 } | |
| 673 | |
| 674 u_command[j] = '\0'; | |
| 675 i++; | |
| 676 | |
| 677 for (j = 0; buf[i] != '#'; j++, i++) { | |
| 678 } | |
| 679 i++; | |
| 680 | |
| 681 for (j = 0; buf[i] != ':'; j++, i++) { | |
| 682 u_channel[j] = buf[i]; | |
| 683 } | |
| 684 | |
| 685 u_channel[j - 1] = '\0'; | |
| 686 i++; | |
| 687 | |
| 688 while ((buf[i] == ' ') || (buf[i] == ':')) { | |
| 689 i++; | |
| 690 } | |
| 691 | |
| 692 strcpy(u_names, buf + i); | |
| 693 | |
| 694 buf2 = g_strsplit(u_names, " ", 0); | |
| 695 | |
| 696 /* Let's get our conversation window */ | |
| 697 convo = find_conversation_by_name(gc, u_channel); | |
| 698 | |
| 699 if (!convo) { | |
| 700 return; | |
| 701 } | |
| 702 | |
| 703 /* Now that we've parsed the hell out of this big | |
| 704 * mess, let's try to split up the names properly */ | |
| 705 | |
| 706 for (i = 0; buf2[i] != NULL; i++) | |
| 707 add_chat_buddy(convo, buf2[i]); | |
| 708 | |
| 709 /* And free our pointers */ | |
| 710 g_strfreev(buf2); | |
| 711 | |
| 712 return; | |
| 713 | |
| 714 } | |
| 715 | |
| 716 /* Receive a list of users that are currently online */ | |
| 717 | |
| 718 if (((strstr(buf, " 303 ")) && (!strstr(buf, "PRIVMSG")) && (!strstr(buf, "NOTICE")))) { | |
| 719 gchar u_host[255]; | |
| 720 gchar u_command[32]; | |
| 721 gchar u_names[IRC_BUF_LEN + 1]; | |
| 722 int j; | |
| 723 | |
| 724 for (j = 0, i = 0; buf[i] != ' '; j++, i++) { | |
| 725 u_host[j] = buf[i]; | |
| 726 } | |
| 727 | |
| 728 u_host[j] = '\0'; | |
| 729 i++; | |
| 730 | |
| 731 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 732 u_command[j] = buf[i]; | |
| 733 } | |
| 734 | |
| 735 u_command[j] = '\0'; | |
| 736 i++; | |
| 737 | |
| 738 for (j = 0; buf[i] != ':'; j++, i++) { | |
| 739 /* My Nick */ | |
| 740 } | |
| 741 i++; | |
| 742 | |
| 743 strcpy(u_names, buf + i); | |
| 744 | |
| 745 buf2 = g_strsplit(u_names, " ", 0); | |
| 746 | |
| 747 /* Now that we've parsed the hell out of this big | |
| 748 * mess, let's try to split up the names properly */ | |
| 749 | |
| 750 for (i = 0; buf2[i] != NULL; i++) { | |
| 751 /* If we have a name here then our buddy is online. We should | |
| 752 * update our temporary gslist accordingly. When we achieve our maximum | |
| 753 * list of names then we should force an update */ | |
| 754 | |
| 755 irc_update_user(gc, buf2[i], 1); | |
| 756 } | |
| 757 | |
| 758 /* Increase our received blocks counter */ | |
| 759 idata->recblocks++; | |
| 760 | |
| 761 /* If we have our total number of blocks */ | |
| 762 if (idata->recblocks == idata->totalblocks) { | |
| 763 GSList *temp; | |
| 764 struct irc_channel *u; | |
| 765 | |
| 766 /* Let's grab our list of people and bring them all on or off line */ | |
| 767 temp = idata->templist; | |
| 768 | |
| 769 /* Loop */ | |
| 770 while (temp) { | |
| 771 | |
| 772 u = temp->data; | |
| 773 | |
| 774 /* Tell Gaim to bring the person on or off line */ | |
| 775 serv_got_update(gc, u->name, u->id, 0, 0, 0, 0, 0); | |
| 776 | |
| 777 /* Grab the next entry */ | |
| 778 temp = g_slist_next(temp); | |
| 779 } | |
| 780 | |
| 781 /* And now, let's delete all of our entries */ | |
| 782 temp = idata->templist; | |
| 783 while (temp) { | |
| 784 u = temp->data; | |
| 785 g_free(u->name); | |
| 786 temp = g_slist_remove(temp, u); | |
| 787 } | |
| 788 | |
| 789 /* Reset our list */ | |
| 790 idata->totalblocks = 0; | |
| 791 idata->recblocks = 0; | |
| 792 | |
| 793 idata->templist = NULL; | |
| 794 | |
| 795 return; | |
| 796 } | |
| 797 | |
| 798 /* And free our pointers */ | |
| 799 g_strfreev(buf2); | |
| 800 | |
| 801 return; | |
| 802 | |
| 803 } | |
| 804 | |
| 805 | |
| 806 if ((strstr(buf, " MODE ")) && (strstr(buf, "!")) | |
| 807 && (strstr(buf, "+v") || strstr(buf, "-v") || strstr(buf, "-o") || strstr(buf, "+o")) | |
| 808 && (buf[0] == ':') && (!strstr(buf, " NOTICE "))) { | |
| 809 | |
| 810 gchar u_channel[128]; | |
| 811 gchar u_nick[128]; | |
| 812 | |
| 813 gchar u_mode[5]; | |
| 814 char **people; | |
| 815 gchar *temp, *temp_new; | |
| 816 | |
| 817 | |
| 818 struct irc_channel *channel; | |
| 819 int j; | |
| 820 temp = NULL; | |
| 821 temp_new = NULL; | |
| 822 | |
| 823 | |
| 824 for (j = 0, i = 1; buf[i] != '!'; j++, i++) { | |
| 825 u_nick[j] = buf[i]; | |
| 826 } | |
| 827 u_nick[j] = '\0'; | |
| 828 i++; | |
| 829 | |
| 830 for (j = 0; buf[i] != '#'; j++, i++) { | |
| 831 } | |
| 832 i++; | |
| 833 | |
| 834 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 835 u_channel[j] = buf[i]; | |
| 836 } | |
| 837 | |
| 838 u_channel[j] = '\0'; | |
| 839 i++; | |
| 840 | |
| 841 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 842 u_mode[j] = buf[i]; | |
| 843 } | |
| 844 u_mode[j] = '\0'; | |
| 845 i++; | |
| 846 | |
| 847 | |
| 848 | |
| 849 | |
| 850 people = g_strsplit(buf + i, " ", 3); | |
| 851 | |
| 852 | |
| 853 | |
| 854 channel = find_channel_by_name(gc, u_channel); | |
| 855 | |
| 856 if (!channel) { | |
| 857 return; | |
| 858 } | |
| 859 | |
| 860 for (j = 0; j < strlen(u_mode) - 1; j++) { | |
| 861 | |
| 862 | |
| 863 struct conversation *convo = NULL; | |
| 864 convo = find_conversation_by_id(gc, channel->id); | |
| 865 | |
| 866 | |
| 867 | |
| 868 temp = (gchar *) g_malloc(strlen(people[j]) + 3); | |
| 869 temp_new = (gchar *) g_malloc(strlen(people[j]) + 3); | |
| 870 g_snprintf(temp, strlen(people[j]) + 2, "@%s", people[j]); | |
| 871 | |
| 872 if (u_mode[1] == 'v' && u_mode[0] == '+') { | |
| 873 g_snprintf(temp_new, strlen(people[j]) + 2, "+%s", people[j]); | |
| 874 } else if (u_mode[1] == 'o' && u_mode[0] == '+') { | |
| 875 g_snprintf(temp_new, strlen(people[j]) + 2, "@%s", people[j]); | |
| 876 } | |
| 877 | |
| 878 else if (u_mode[0] == '-') { | |
| 879 g_snprintf(temp_new, strlen(people[j]) + 1, "%s", people[j]); | |
| 880 } | |
| 881 | |
| 882 | |
| 883 | |
| 884 rename_chat_buddy(convo, temp, temp_new); | |
| 885 g_snprintf(temp, strlen(people[j]) + 2, "+%s", people[j]); | |
| 886 rename_chat_buddy(convo, temp, temp_new); | |
| 887 | |
| 888 rename_chat_buddy(convo, people[j], temp_new); | |
| 889 | |
| 890 | |
| 891 | |
| 892 | |
| 893 | |
| 894 } | |
| 895 if (temp) | |
| 896 g_free(temp); | |
| 897 if (temp_new) | |
| 898 g_free(temp_new); | |
| 899 | |
| 900 return; | |
| 901 } | |
| 902 | |
| 903 | |
| 904 if ((strstr(buf, " KICK ")) && (strstr(buf, "!")) && (buf[0] == ':') | |
| 905 && (!strstr(buf, " NOTICE "))) { | |
| 906 gchar u_channel[128]; | |
| 907 gchar u_nick[128]; | |
| 908 gchar u_comment[128]; | |
| 909 gchar u_who[128]; | |
| 910 | |
| 911 int id; | |
| 912 | |
| 913 gchar *temp; | |
| 914 | |
| 915 | |
| 916 | |
| 917 struct irc_channel *channel; | |
| 918 int j; | |
| 919 | |
| 920 temp = NULL; | |
| 921 | |
| 922 for (j = 0, i = 1; buf[i] != '!'; j++, i++) { | |
| 923 u_nick[j] = buf[i]; | |
| 924 } | |
| 925 u_nick[j] = '\0'; | |
| 926 i++; | |
| 927 | |
| 928 for (j = 0; buf[i] != '#'; j++, i++) { | |
| 929 } | |
| 930 i++; | |
| 931 | |
| 932 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 933 u_channel[j] = buf[i]; | |
| 934 } | |
| 935 | |
| 936 u_channel[j] = '\0'; | |
| 937 i++; | |
| 938 | |
| 939 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 940 u_who[j] = buf[i]; | |
| 941 } | |
| 942 u_who[j] = '\0'; | |
| 943 i++; | |
| 944 i++; | |
| 945 strcpy(u_comment, buf + i); | |
| 946 g_strchomp(u_comment); | |
| 947 | |
| 948 channel = find_channel_by_name(gc, u_channel); | |
| 949 | |
| 950 if (!channel) { | |
| 951 return; | |
| 952 } | |
| 953 | |
| 954 | |
| 955 id = find_id_by_name(gc, u_channel); | |
| 956 | |
| 957 | |
| 958 if (g_strcasecmp(u_nick, gc->username) == 0) { | |
| 959 | |
| 960 /* It looks like you've been naughty! */ | |
| 961 | |
| 962 serv_got_chat_left(gc, channel->id); | |
| 963 | |
| 964 idata->channels = g_list_remove(idata->channels, channel); | |
| 965 } else { | |
| 966 struct conversation *convo = NULL; | |
| 967 | |
| 968 /* Find their conversation window */ | |
| 969 convo = find_conversation_by_id(gc, channel->id); | |
| 970 | |
| 971 if (!convo) { | |
| 972 /* Some how the window doesn't exist. | |
| 973 * Let's get out of here */ | |
| 974 return; | |
| 975 } | |
| 976 | |
| 977 /* And remove their name */ | |
| 978 /* If the person is an op or voice, this won't work. | |
| 979 * so we'll just do a nice hack and remove nick and | |
| 980 * @nick and +nick. Truly wasteful. | |
| 981 */ | |
| 982 | |
| 983 temp = (gchar *) g_malloc(strlen(u_who) + 3); | |
| 984 g_snprintf(temp, strlen(u_who) + 2, "@%s", u_who); | |
| 985 remove_chat_buddy(convo, temp); | |
| 986 g_free(temp); | |
| 987 temp = (gchar *) g_malloc(strlen(u_who) + 3); | |
| 988 g_snprintf(temp, strlen(u_who) + 2, "+%s", u_who); | |
| 989 remove_chat_buddy(convo, temp); | |
| 990 remove_chat_buddy(convo, u_who); | |
| 991 | |
| 992 g_free(temp); | |
| 993 | |
| 994 } | |
| 995 | |
| 996 /* Go Home! */ | |
| 997 return; | |
| 998 } | |
| 999 | |
| 1000 if ((strstr(buf, " TOPIC ")) && (buf[0] == ':') && (!strstr(buf, " NOTICE "))) { | |
| 1001 | |
| 1002 gchar u_channel[128]; | |
| 1003 gchar u_nick[128]; | |
| 1004 gchar u_topic[128]; | |
| 1005 int j; | |
| 1006 struct conversation *chatroom = NULL; | |
| 1007 | |
| 1008 for (j = 0, i = 1; buf[i] != '!'; j++, i++) { | |
| 1009 u_nick[j] = buf[i]; | |
| 1010 } | |
| 1011 u_nick[j] = 0; | |
| 1012 i++; | |
| 1013 | |
| 1014 for (j = 0; buf[i] != '#'; j++, i++) { | |
| 1015 } | |
| 1016 i++; | |
| 1017 | |
| 1018 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 1019 if (buf[i] == '\0') | |
| 1020 break; | |
| 1021 | |
| 1022 u_channel[j] = buf[i]; | |
| 1023 } | |
| 1024 | |
| 1025 for (j = 0; buf[i] != ':'; j++, i++) { | |
| 1026 } | |
| 1027 i++; | |
| 1028 | |
| 1029 strcpy(u_topic, buf + i); | |
| 1030 g_strchomp(u_topic); | |
| 1031 | |
| 1032 chatroom = find_chat(gc, u_channel); | |
| 1033 | |
| 1034 if (!chatroom) | |
| 1035 return; | |
| 1036 | |
| 1037 chat_set_topic(chatroom, u_nick, u_topic); | |
| 1038 | |
| 1039 return; | |
| 1040 } | |
| 1041 | |
| 1042 | |
| 1043 if ((strstr(buf, " JOIN ")) && (strstr(buf, "!")) && (buf[0] == ':') | |
| 1044 && (!strstr(buf, " NOTICE "))) { | |
| 1045 | |
| 1046 gchar u_channel[128]; | |
| 1047 gchar u_nick[128]; | |
| 1048 | |
| 1049 struct irc_channel *channel; | |
| 1050 int j; | |
| 1051 | |
| 1052 for (j = 0, i = 1; buf[i] != '!'; j++, i++) { | |
| 1053 u_nick[j] = buf[i]; | |
| 1054 } | |
| 1055 | |
| 1056 u_nick[j] = '\0'; | |
| 1057 i++; | |
| 1058 | |
| 1059 for (j = 0; buf[i] != '#'; j++, i++) { | |
| 1060 } | |
| 1061 | |
| 1062 i++; | |
| 1063 | |
| 1064 strcpy(u_channel, buf + i); | |
| 1065 | |
| 1066 g_strchomp(u_channel); | |
| 1067 | |
| 1068 /* Looks like we're going to join the channel for real | |
| 1069 * now. Let's create a valid channel structure and add | |
| 1070 * it to our list. Let's make sure that | |
| 1071 * we are not already in a channel first */ | |
| 1072 | |
| 1073 channel = find_channel_by_name(gc, u_channel); | |
| 1074 | |
| 1075 if (!channel) { | |
| 1076 | |
| 1077 chat_id++; | |
| 1078 | |
| 1079 channel = g_new0(struct irc_channel, 1); | |
| 1080 | |
| 1081 channel->id = chat_id; | |
| 1082 channel->name = strdup(u_channel); | |
| 1083 | |
| 1084 idata->channels = g_list_append(idata->channels, channel); | |
| 1085 | |
| 1086 serv_got_joined_chat(gc, chat_id, u_channel); | |
| 1087 } else { | |
| 1088 struct conversation *convo = NULL; | |
| 1089 | |
| 1090 /* Someone else joined. Find their conversation | |
| 1091 * window */ | |
| 1092 convo = find_conversation_by_id(gc, channel->id); | |
| 1093 | |
| 1094 /* And add their name to it */ | |
| 1095 add_chat_buddy(convo, u_nick); | |
| 1096 | |
| 1097 } | |
| 1098 | |
| 1099 return; | |
| 1100 } | |
| 1101 | |
| 1102 if ((strstr(buf, " NICK ")) && (strstr(buf, "!")) && (buf[0] == ':') | |
| 1103 && (!strstr(buf, " NOTICE "))) { | |
| 1104 | |
| 1105 gchar old[128]; | |
| 1106 gchar new[128]; | |
| 1107 | |
| 1108 GList *templist; | |
| 1109 gchar *temp, *temp_new; | |
| 1110 struct irc_channel *channel; | |
| 1111 int j; | |
| 1112 temp = temp_new = NULL; | |
| 1113 for (j = 0, i = 1; buf[i] != '!'; j++, i++) { | |
| 1114 old[j] = buf[i]; | |
| 1115 } | |
| 1116 | |
| 1117 old[j] = '\0'; | |
| 1118 i++; | |
| 1119 | |
| 1120 for (j = 0; buf[i] != ':'; j++, i++) { | |
| 1121 } | |
| 1122 | |
| 1123 i++; | |
| 1124 strcpy(new, buf + i); | |
| 1125 | |
| 1126 g_strchomp(new); | |
| 1127 | |
| 1128 templist = ((struct irc_data *)gc->proto_data)->channels; | |
| 1129 | |
| 1130 while (templist) { | |
| 1131 struct conversation *convo = NULL; | |
| 1132 channel = templist->data; | |
| 1133 | |
| 1134 convo = find_conversation_by_id(gc, channel->id); | |
| 1135 | |
| 1136 /* If the person is an op or voice, this won't work. | |
| 1137 * so we'll just do a nice hack and rename nick and | |
| 1138 * @nick and +nick. Truly wasteful. | |
| 1139 */ | |
| 1140 | |
| 1141 temp = (gchar *) g_malloc(strlen(old) + 5); | |
| 1142 temp_new = (gchar *) g_malloc(strlen(new) + 5); | |
| 1143 g_snprintf(temp_new, strlen(new) + 2, "@%s", new); | |
| 1144 g_snprintf(temp, strlen(old) + 2, "@%s", old); | |
| 1145 rename_chat_buddy(convo, temp, temp_new); | |
| 1146 g_snprintf(temp, strlen(old) + 2, "+%s", old); | |
| 1147 g_snprintf(temp_new, strlen(new) + 2, "+%s", new); | |
| 1148 rename_chat_buddy(convo, temp, temp_new); | |
| 1149 rename_chat_buddy(convo, old, new); | |
| 1150 if (temp) | |
| 1151 g_free(temp); | |
| 1152 if (temp_new) | |
| 1153 g_free(temp_new); | |
| 1154 | |
| 1155 templist = templist->next; | |
| 1156 } | |
| 1157 return; | |
| 1158 } | |
| 1159 | |
| 1160 | |
| 1161 if ((strstr(buf, "QUIT ")) && (buf[0] == ':') && (strstr(buf, "!")) | |
| 1162 && (!strstr(buf, " NOTICE "))) { | |
| 1163 | |
| 1164 gchar u_nick[128]; | |
| 1165 gchar *temp; | |
| 1166 GList *templist; | |
| 1167 | |
| 1168 struct irc_channel *channel; | |
| 1169 int j; | |
| 1170 | |
| 1171 | |
| 1172 temp = NULL; | |
| 1173 for (j = 0, i = 1; buf[i] != '!'; j++, i++) { | |
| 1174 u_nick[j] = buf[i]; | |
| 1175 } | |
| 1176 | |
| 1177 u_nick[j] = '\0'; | |
| 1178 | |
| 1179 templist = ((struct irc_data *)gc->proto_data)->channels; | |
| 1180 | |
| 1181 while (templist) { | |
| 1182 struct conversation *convo = NULL; | |
| 1183 channel = templist->data; | |
| 1184 | |
| 1185 convo = find_conversation_by_id(gc, channel->id); | |
| 1186 | |
| 1187 /* If the person is an op or voice, this won't work. | |
| 1188 * so we'll just do a nice hack and remove nick and | |
| 1189 * @nick and +nick. Truly wasteful. | |
| 1190 */ | |
| 1191 | |
| 1192 temp = (gchar *) g_malloc(strlen(u_nick) + 2); | |
| 1193 g_snprintf(temp, strlen(u_nick) + 2, "@%s", u_nick); | |
| 1194 remove_chat_buddy(convo, temp); | |
| 1195 g_free(temp); | |
| 1196 temp = (gchar *) g_malloc(strlen(u_nick) + 2); | |
| 1197 g_snprintf(temp, strlen(u_nick) + 2, "+%s", u_nick); | |
| 1198 remove_chat_buddy(convo, temp); | |
| 1199 remove_chat_buddy(convo, u_nick); | |
| 1200 | |
| 1201 | |
| 1202 | |
| 1203 templist = templist->next; | |
| 1204 } | |
| 1205 | |
| 1206 g_free(temp); | |
| 1207 | |
| 1208 return; | |
| 1209 } | |
| 1210 | |
| 1211 | |
| 1212 | |
| 1213 if ((strstr(buf, " PART ")) && (strstr(buf, "!")) && (buf[0] == ':') | |
| 1214 && (!strstr(buf, " NOTICE "))) { | |
| 1215 | |
| 1216 gchar u_channel[128]; | |
| 1217 gchar u_nick[128]; | |
| 1218 gchar *temp; | |
| 1219 struct irc_channel *channel; | |
| 1220 int j; | |
| 1221 temp = NULL; | |
| 1222 for (j = 0, i = 1; buf[i] != '!'; j++, i++) { | |
| 1223 u_nick[j] = buf[i]; | |
| 1224 } | |
| 1225 u_nick[j] = '\0'; | |
| 1226 | |
| 1227 i++; | |
| 1228 | |
| 1229 for (j = 0; buf[i] != '#'; j++, i++) { | |
| 1230 } | |
| 1231 | |
| 1232 i++; | |
| 1233 | |
| 1234 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 1235 if (buf[i] == '\0') { | |
| 1236 break; | |
| 1237 } | |
| 1238 u_channel[j] = buf[i]; | |
| 1239 } | |
| 1240 u_channel[j] = '\0'; | |
| 1241 | |
| 1242 /* Now, lets check to see if it was US that was leaving. | |
| 1243 * If so, do the correct thing by closing up all of our | |
| 1244 * old channel stuff. Otherwise, | |
| 1245 * we should just print that someone left */ | |
| 1246 | |
| 1247 channel = find_channel_by_name(gc, u_channel); | |
| 1248 | |
| 1249 if (!channel) { | |
| 1250 return; | |
| 1251 } | |
| 1252 | |
| 1253 if (g_strcasecmp(u_nick, gc->username) == 0) { | |
| 1254 | |
| 1255 /* Looks like we're going to leave the channel for | |
| 1256 * real now. Let's create a valid channel structure | |
| 1257 * and add it to our list */ | |
| 1258 | |
| 1259 serv_got_chat_left(gc, channel->id); | |
| 1260 | |
| 1261 idata->channels = g_list_remove(idata->channels, channel); | |
| 1262 } else { | |
| 1263 struct conversation *convo = NULL; | |
| 1264 | |
| 1265 /* Find their conversation window */ | |
| 1266 convo = find_conversation_by_id(gc, channel->id); | |
| 1267 | |
| 1268 if (!convo) { | |
| 1269 /* Some how the window doesn't exist. | |
| 1270 * Let's get out of here */ | |
| 1271 return; | |
| 1272 } | |
| 1273 | |
| 1274 /* And remove their name */ | |
| 1275 /* If the person is an op or voice, this won't work. | |
| 1276 * so we'll just do a nice hack and remove nick and | |
| 1277 * @nick and +nick. Truly wasteful. | |
| 1278 */ | |
| 1279 | |
| 1280 temp = (gchar *) g_malloc(strlen(u_nick) + 3); | |
| 1281 g_snprintf(temp, strlen(u_nick) + 2, "@%s", u_nick); | |
| 1282 remove_chat_buddy(convo, temp); | |
| 1283 g_free(temp); | |
| 1284 temp = (gchar *) g_malloc(strlen(u_nick) + 3); | |
| 1285 g_snprintf(temp, strlen(u_nick) + 2, "+%s", u_nick); | |
| 1286 remove_chat_buddy(convo, temp); | |
| 1287 g_free(temp); | |
| 1288 remove_chat_buddy(convo, u_nick); | |
| 1289 | |
| 1290 | |
| 1291 } | |
| 1292 | |
| 1293 /* Go Home! */ | |
| 1294 return; | |
| 1295 } | |
| 1296 | |
| 1297 if ((strstr(buf, " NOTICE ")) && (buf[0] == ':')) { | |
| 1298 gchar u_nick[128]; | |
| 1299 gchar u_host[255]; | |
| 1300 gchar u_command[32]; | |
| 1301 gchar u_channel[128]; | |
| 1302 gchar u_message[IRC_BUF_LEN]; | |
| 1303 int j; | |
| 1304 | |
| 1305 for (j = 0, i = 1; buf[i] != '!'; j++, i++) { | |
| 1306 u_nick[j] = buf[i]; | |
| 1307 } | |
| 1308 | |
| 1309 u_nick[j] = '\0'; | |
| 1310 i++; | |
| 1311 | |
| 1312 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 1313 u_host[j] = buf[i]; | |
| 1314 } | |
| 1315 | |
| 1316 u_host[j] = '\0'; | |
| 1317 i++; | |
| 1318 | |
| 1319 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 1320 u_command[j] = buf[i]; | |
| 1321 } | |
| 1322 | |
| 1323 u_command[j] = '\0'; | |
| 1324 i++; | |
| 1325 | |
| 1326 for (j = 0; buf[i] != ':'; j++, i++) { | |
| 1327 u_channel[j] = buf[i]; | |
| 1328 } | |
| 1329 | |
| 1330 u_channel[j - 1] = '\0'; | |
| 1331 i++; | |
| 1332 | |
| 1333 | |
| 1334 /* Now that everything is parsed, the rest of this baby must be our message */ | |
| 1335 strncpy(u_message, buf + i, IRC_BUF_LEN); | |
| 1336 | |
| 1337 /* Now, lets check the message to see if there's anything special in it */ | |
| 1338 if (u_message[0] == '\001') { | |
| 1339 if ((g_strncasecmp(u_message, "\001PING ", 6) == 0) && (strlen(u_message) > 6)) { | |
| 1340 /* Someone's triyng to ping us. Let's respond */ | |
| 1341 gchar u_arg[24]; | |
| 1342 gchar u_buf[200]; | |
| 1343 unsigned long tend = time((time_t *) NULL); | |
| 1344 unsigned long tstart; | |
| 1345 | |
| 1346 printf("LA: %s\n", buf); | |
| 1347 | |
| 1348 strcpy(u_arg, u_message + 6); | |
| 1349 u_arg[strlen(u_arg) - 1] = '\0'; | |
| 1350 | |
| 1351 tstart = atol(u_arg); | |
| 1352 | |
| 1353 g_snprintf(u_buf, sizeof(u_buf), "Ping Reply From %s: [%ld seconds]", | |
| 1354 u_nick, tend - tstart); | |
| 1355 | |
| 1356 do_error_dialog(u_buf, "Gaim IRC - Ping Reply"); | |
| 1357 | |
| 1358 return; | |
| 1359 } | |
| 1360 } | |
| 1361 | |
| 1362 } | |
| 1363 | |
| 1364 | |
| 1365 if ((strstr(buf, " PRIVMSG ")) && (buf[0] == ':')) { | |
| 1366 gchar u_nick[128]; | |
| 1367 gchar u_host[255]; | |
| 1368 gchar u_command[32]; | |
| 1369 gchar u_channel[128]; | |
| 1370 gchar u_message[IRC_BUF_LEN]; | |
| 1371 gboolean is_closing; | |
| 1372 | |
| 1373 int j; | |
| 1374 | |
| 1375 | |
| 1376 for (j = 0, i = 1; buf[i] != '!'; j++, i++) { | |
| 1377 u_nick[j] = buf[i]; | |
| 1378 } | |
| 1379 | |
| 1380 u_nick[j] = '\0'; | |
| 1381 i++; | |
| 1382 | |
| 1383 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 1384 u_host[j] = buf[i]; | |
| 1385 } | |
| 1386 | |
| 1387 u_host[j] = '\0'; | |
| 1388 i++; | |
| 1389 | |
| 1390 for (j = 0; buf[i] != ' '; j++, i++) { | |
| 1391 u_command[j] = buf[i]; | |
| 1392 } | |
| 1393 | |
| 1394 u_command[j] = '\0'; | |
| 1395 i++; | |
| 1396 | |
| 1397 for (j = 0; buf[i] != ':'; j++, i++) { | |
| 1398 u_channel[j] = buf[i]; | |
| 1399 } | |
| 1400 | |
| 1401 u_channel[j - 1] = '\0'; | |
| 1402 i++; | |
| 1403 | |
| 1404 | |
| 1405 /* Now that everything is parsed, the rest of this baby must be our message */ | |
| 1406 strncpy(u_message, buf + i, IRC_BUF_LEN); | |
| 1407 | |
| 1408 /* Now, lets check the message to see if there's anything special in it */ | |
| 1409 if (u_message[0] == '\001') { | |
| 1410 if (g_strncasecmp(u_message, "\001VERSION", 8) == 0) { | |
| 1411 /* Looks like we have a version request. Let | |
| 1412 * us handle it thusly */ | |
| 1413 | |
| 1414 g_snprintf(buf, IRC_BUF_LEN, | |
| 1415 "NOTICE %s :%cVERSION GAIM %s:The Pimpin Penguin AIM Clone:%s%c\n", | |
| 1416 u_nick, '\001', VERSION, WEBSITE, '\001'); | |
| 1417 | |
| 1418 write(idata->fd, buf, strlen(buf)); | |
| 1419 | |
| 1420 /* And get the heck out of dodge */ | |
| 1421 return; | |
| 1422 } | |
| 1423 | |
| 1424 if ((g_strncasecmp(u_message, "\001PING ", 6) == 0) && (strlen(u_message) > 6)) { | |
| 1425 /* Someone's triyng to ping us. Let's respond */ | |
| 1426 gchar u_arg[24]; | |
| 1427 | |
| 1428 strcpy(u_arg, u_message + 6); | |
| 1429 u_arg[strlen(u_arg) - 1] = '\0'; | |
| 1430 | |
| 1431 g_snprintf(buf, IRC_BUF_LEN, "NOTICE %s :%cPING %s%c\n", u_nick, '\001', | |
| 1432 u_arg, '\001'); | |
| 1433 | |
| 1434 write(idata->fd, buf, strlen(buf)); | |
| 1435 | |
| 1436 /* And get the heck out of dodge */ | |
| 1437 return; | |
| 1438 } | |
| 1439 | |
| 1440 if (g_strncasecmp(u_message, "\001ACTION ", 8) == 0) { | |
| 1441 /* Looks like we have an action. Let's parse it a little */ | |
| 1442 strcpy(buf, u_message); | |
| 1443 | |
| 1444 strcpy(u_message, "/me "); | |
| 1445 for (j = 4, i = 8; buf[i] != '\001'; i++, j++) { | |
| 1446 u_message[j] = buf[i]; | |
| 1447 } | |
| 1448 u_message[j] = '\0'; | |
| 1449 } | |
| 1450 } | |
| 1451 | |
| 1452 | |
| 1453 /* OK, It is a chat or IM message. Here, let's translate the IRC formatting into | |
| 1454 * good ol' fashioned gtkimhtml style hypertext markup. */ | |
| 1455 | |
| 1456 | |
| 1457 is_closing = FALSE; | |
| 1458 | |
| 1459 while (strchr(u_message, '\002')) { /* \002 = ^B */ | |
| 1460 gchar *current; | |
| 1461 gchar *temp, *free_here; | |
| 1462 | |
| 1463 | |
| 1464 temp = g_strdup(strchr(u_message, '\002')); | |
| 1465 free_here = temp; | |
| 1466 temp++; | |
| 1467 | |
| 1468 current = strchr(u_message, '\002'); | |
| 1469 *current = '<'; | |
| 1470 current++; | |
| 1471 if (is_closing) { | |
| 1472 *current = '/'; | |
| 1473 current++; | |
| 1474 } | |
| 1475 *current = 'b'; | |
| 1476 current++; | |
| 1477 *current = '>'; | |
| 1478 current++; | |
| 1479 | |
| 1480 | |
| 1481 while (*temp != '\0') { | |
| 1482 *current = *temp; | |
| 1483 current++; | |
| 1484 temp++; | |
| 1485 } | |
| 1486 *current = '\0'; | |
| 1487 g_free(free_here); | |
| 1488 | |
| 1489 is_closing = !is_closing; | |
| 1490 } | |
| 1491 | |
| 1492 is_closing = FALSE; | |
| 1493 while (strchr(u_message, '\037')) { /* \037 = ^_ */ | |
| 1494 gchar *current; | |
| 1495 gchar *temp, *free_here; | |
| 1496 | |
| 1497 | |
| 1498 temp = g_strdup(strchr(u_message, '\037')); | |
| 1499 free_here = temp; | |
| 1500 temp++; | |
| 1501 | |
| 1502 current = strchr(u_message, '\037'); | |
| 1503 *current = '<'; | |
| 1504 current++; | |
| 1505 if (is_closing) { | |
| 1506 *current = '/'; | |
| 1507 current++; | |
| 1508 } | |
| 1509 *current = 'u'; | |
| 1510 current++; | |
| 1511 *current = '>'; | |
| 1512 current++; | |
| 1513 | |
| 1514 | |
| 1515 while (*temp != '\0') { | |
| 1516 *current = *temp; | |
| 1517 current++; | |
| 1518 temp++; | |
| 1519 } | |
| 1520 *current = '\0'; | |
| 1521 g_free(free_here); | |
| 1522 is_closing = !is_closing; | |
| 1523 | |
| 1524 } | |
| 1525 | |
| 1526 while (strchr(u_message, '\003')) { /* \003 = ^C */ | |
| 1527 | |
| 1528 /* This is color formatting. IRC uses its own weird little system | |
| 1529 * that we must translate to HTML. */ | |
| 1530 | |
| 1531 | |
| 1532 /* The format is something like this: | |
| 1533 * ^C5 or ^C5,3 | |
| 1534 * The number before the comma is the foreground color, after is the | |
| 1535 * background color. Either number can be 1 or two digits. | |
| 1536 */ | |
| 1537 | |
| 1538 gchar *current; | |
| 1539 gchar *temp, *free_here; | |
| 1540 gchar *font_tag, *body_tag; | |
| 1541 int fg_color, bg_color; | |
| 1542 | |
| 1543 temp = g_strdup(strchr(u_message, '\003')); | |
| 1544 free_here = temp; | |
| 1545 temp++; | |
| 1546 | |
| 1547 fg_color = bg_color = -1; | |
| 1548 body_tag = font_tag = ""; | |
| 1549 | |
| 1550 /* Parsing the color information: */ | |
| 1551 do { | |
| 1552 if (!isdigit(*temp)) | |
| 1553 break; /* This translates to </font> */ | |
| 1554 fg_color = (int)(*temp - 48); | |
| 1555 temp++; | |
| 1556 if (isdigit(*temp)) { | |
| 1557 fg_color = (fg_color * 10) + (int)(*temp - 48); | |
| 1558 temp++; | |
| 1559 } | |
| 1560 if (*temp != ',') | |
| 1561 break; | |
| 1562 temp++; | |
| 1563 if (!isdigit(*temp)) | |
| 1564 break; /* This translates to </font> */ | |
| 1565 bg_color = (int)(*temp - 48); | |
| 1566 temp++; | |
| 1567 if (isdigit(*temp)) { | |
| 1568 bg_color = (bg_color * 10) + (int)(*temp - 48); | |
| 1569 temp++; | |
| 1570 } | |
| 1571 } while (FALSE); | |
| 1572 | |
| 1573 if (fg_color > 15) | |
| 1574 fg_color = fg_color % 16; | |
| 1575 if (bg_color > 15) | |
| 1576 bg_color = bg_color % 16; | |
| 1577 | |
| 1578 switch (fg_color) { | |
| 1579 case -1: | |
| 1580 font_tag = "</font></body>"; | |
| 1581 break; | |
| 1582 case 0: /* WHITE */ | |
| 1583 font_tag = "<font color=\"#ffffff\">"; | |
| 1584 /* If no background color is specified, we're going to make it black anyway. | |
| 1585 * That's probably what the sender anticipated the background color to be. | |
| 1586 * White on white would be illegible. | |
| 1587 */ | |
| 1588 if (bg_color == -1) { | |
| 1589 body_tag = "<body bgcolor=\"#000000\">"; | |
| 1590 } | |
| 1591 break; | |
| 1592 case 1: /* BLACK */ | |
| 1593 font_tag = "<font color=\"#000000\">"; | |
| 1594 break; | |
| 1595 case 2: /* NAVY BLUE */ | |
| 1596 font_tag = "<font color=\"#000066\">"; | |
| 1597 break; | |
| 1598 case 3: /* GREEN */ | |
| 1599 font_tag = "<font color=\"#006600\">"; | |
| 1600 break; | |
| 1601 case 4: /* RED */ | |
| 1602 font_tag = "<font color=\"#ff0000\">"; | |
| 1603 break; | |
| 1604 case 5: /* MAROON */ | |
| 1605 font_tag = "<font color=\"#660000\">"; | |
| 1606 break; | |
| 1607 case 6: /* PURPLE */ | |
| 1608 font_tag = "<font color=\"#660066\">"; | |
| 1609 break; | |
| 1610 case 7: /* DISGUSTING PUKE COLOR */ | |
| 1611 font_tag = "<font color=\"#666600\">"; | |
| 1612 break; | |
| 1613 case 8: /* YELLOW */ | |
| 1614 font_tag = "<font color=\"#cccc00\">"; | |
| 1615 break; | |
| 1616 case 9: /* LIGHT GREEN */ | |
| 1617 font_tag = "<font color=\"#33cc33\">"; | |
| 1618 break; | |
| 1619 case 10: /* TEAL */ | |
| 1620 font_tag = "<font color=\"#00acac\">"; | |
| 1621 break; | |
| 1622 case 11: /* CYAN */ | |
| 1623 font_tag = "<font color=\"#00ccac\">"; | |
| 1624 break; | |
| 1625 case 12: /* BLUE */ | |
| 1626 font_tag = "<font color=\"#0000ff\">"; | |
| 1627 break; | |
| 1628 case 13: /* PINK */ | |
| 1629 font_tag = "<font color=\"#cc00cc\">"; | |
| 1630 break; | |
| 1631 case 14: /* GREY */ | |
| 1632 font_tag = "<font color=\"#666666\">"; | |
| 1633 break; | |
| 1634 case 15: /* SILVER */ | |
| 1635 font_tag = "<font color=\"#00ccac\">"; | |
| 1636 break; | |
| 1637 } | |
| 1638 | |
| 1639 switch (bg_color) { | |
| 1640 case 0: /* WHITE */ | |
| 1641 body_tag = "<body bgcolor=\"#ffffff\">"; | |
| 1642 break; | |
| 1643 case 1: /* BLACK */ | |
| 1644 body_tag = "<body bgcolor=\"#000000\">"; | |
| 1645 break; | |
| 1646 case 2: /* NAVY BLUE */ | |
| 1647 body_tag = "<body bgcolor=\"#000066\">"; | |
| 1648 break; | |
| 1649 case 3: /* GREEN */ | |
| 1650 body_tag = "<body bgcolor=\"#006600\">"; | |
| 1651 break; | |
| 1652 case 4: /* RED */ | |
| 1653 body_tag = "<body bgcolor=\"#ff0000\">"; | |
| 1654 break; | |
| 1655 case 5: /* MAROON */ | |
| 1656 body_tag = "<body bgcolor=\"#660000\">"; | |
| 1657 break; | |
| 1658 case 6: /* PURPLE */ | |
| 1659 body_tag = "<body bgcolor=\"#660066\">"; | |
| 1660 break; | |
| 1661 case 7: /* DISGUSTING PUKE COLOR */ | |
| 1662 body_tag = "<body bgcolor=\"#666600\">"; | |
| 1663 break; | |
| 1664 case 8: /* YELLOW */ | |
| 1665 body_tag = "<body bgcolor=\"#cccc00\">"; | |
| 1666 break; | |
| 1667 case 9: /* LIGHT GREEN */ | |
| 1668 body_tag = "<body bgcolor=\"#33cc33\">"; | |
| 1669 break; | |
| 1670 case 10: /* TEAL */ | |
| 1671 body_tag = "<body bgcolor=\"#00acac\">"; | |
| 1672 break; | |
| 1673 case 11: /* CYAN */ | |
| 1674 body_tag = "<body bgcolor=\"#00ccac\">"; | |
| 1675 break; | |
| 1676 case 12: /* BLUE */ | |
| 1677 body_tag = "<body bgcolor=\"#0000ff\">"; | |
| 1678 break; | |
| 1679 case 13: /* PINK */ | |
| 1680 body_tag = "<body bgcolor=\"#cc00cc\">"; | |
| 1681 break; | |
| 1682 case 14: /* GREY */ | |
| 1683 body_tag = "<body bgcolor=\"#666666\">"; | |
| 1684 break; | |
| 1685 case 15: /* SILVER */ | |
| 1686 body_tag = "<body bgcolor=\"#00ccac\">"; | |
| 1687 break; | |
| 1688 } | |
| 1689 | |
| 1690 current = strchr(u_message, '\003'); | |
| 1691 | |
| 1692 while (*body_tag != '\0') { | |
| 1693 *current = *body_tag; | |
| 1694 current++; | |
| 1695 body_tag++; | |
| 1696 } | |
| 1697 | |
| 1698 while (*font_tag != '\0') { | |
| 1699 *current = *font_tag; | |
| 1700 current++; | |
| 1701 font_tag++; | |
| 1702 } | |
| 1703 | |
| 1704 while (*temp != '\0') { | |
| 1705 *current = *temp; | |
| 1706 current++; | |
| 1707 temp++; | |
| 1708 } | |
| 1709 *current = '\0'; | |
| 1710 g_free(free_here); | |
| 1711 is_closing = !is_closing; | |
| 1712 | |
| 1713 } | |
| 1714 | |
| 1715 while (strchr(u_message, '\017')) { /* \017 = ^O */ | |
| 1716 gchar *current; | |
| 1717 gchar *temp, *free_here; | |
| 1718 | |
| 1719 | |
| 1720 temp = g_strdup(strchr(u_message, '\017')); | |
| 1721 free_here = temp; | |
| 1722 temp++; | |
| 1723 | |
| 1724 current = strchr(u_message, '\017'); | |
| 1725 *current = '<'; | |
| 1726 current++; | |
| 1727 *current = '/'; | |
| 1728 current++; | |
| 1729 *current = 'b'; | |
| 1730 current++; | |
| 1731 *current = '>'; | |
| 1732 current++; | |
| 1733 *current = '<'; | |
| 1734 current++; | |
| 1735 *current = '/'; | |
| 1736 current++; | |
| 1737 *current = 'u'; | |
| 1738 current++; | |
| 1739 *current = '>'; | |
| 1740 current++; | |
| 1741 | |
| 1742 while (*temp != '\0') { | |
| 1743 *current = *temp; | |
| 1744 current++; | |
| 1745 temp++; | |
| 1746 } | |
| 1747 *current = '\0'; | |
| 1748 g_free(free_here); | |
| 1749 } | |
| 1750 | |
| 1751 /* Let's check to see if we have a channel on our hands */ | |
| 1752 if (u_channel[0] == '#') { | |
| 1753 /* Yup. We have a channel */ | |
| 1754 int id; | |
| 1755 | |
| 1756 id = find_id_by_name(gc, u_channel); | |
| 1757 if (id != -1) { | |
| 1758 serv_got_chat_in(gc, id, u_nick, 0, u_message, time((time_t) NULL)); | |
| 1759 | |
| 1760 } | |
| 1761 | |
| 1762 } else { | |
| 1763 /* Nope. Let's treat it as a private message */ | |
| 1764 | |
| 1765 gchar *temp; | |
| 1766 temp = NULL; | |
| 1767 | |
| 1768 temp = (gchar *) g_malloc(strlen(u_nick) + 5); | |
| 1769 g_snprintf(temp, strlen(u_nick) + 2, "@%s", u_nick); | |
| 1770 | |
| 1771 | |
| 1772 /* If I get a message from SeanEgn, and I already have a window | |
| 1773 * open for him as @SeanEgn or +SeanEgn, this will keep it in the | |
| 1774 * same window. Unfortunately, if SeanEgn loses his op status | |
| 1775 * (a sad thing indeed), the messages will still appear to come from | |
| 1776 * @SeanEgn, until that convo is closed. | |
| 1777 */ | |
| 1778 | |
| 1779 if (find_conversation(temp)) { | |
| 1780 serv_got_im(gc, temp, u_message, 0, time((time_t) NULL)); | |
| 1781 g_free(temp); | |
| 1782 return; | |
| 1783 } else { | |
| 1784 g_snprintf(temp, strlen(u_nick) + 2, "+%s", u_nick); | |
| 1785 if (find_conversation(temp)) { | |
| 1786 serv_got_im(gc, temp, u_message, 0, time((time_t) NULL)); | |
| 1787 g_free(temp); | |
| 1788 return; | |
| 1789 } else { | |
| 1790 g_free(temp); | |
| 1791 serv_got_im(gc, u_nick, u_message, 0, time((time_t) NULL)); | |
| 1792 return; | |
| 1793 } | |
| 1794 } | |
| 1795 } | |
| 1796 | |
| 1797 return; | |
| 1798 } | |
| 1799 | |
| 1800 /* Let's parse PING requests so that we wont get booted for inactivity */ | |
| 1801 | |
| 1802 if (strncmp(buf, "PING :", 6) == 0) { | |
| 1803 buf2 = g_strsplit(buf, ":", 1); | |
| 1804 | |
| 1805 /* Let's build a new response */ | |
| 1806 g_snprintf(buf, IRC_BUF_LEN, "PONG :%s\n", buf2[1]); | |
| 1807 write(idata->fd, buf, strlen(buf)); | |
| 1808 | |
| 1809 /* And clean up after ourselves */ | |
| 1810 g_strfreev(buf2); | |
| 1811 | |
| 1812 return; | |
| 1813 } | |
| 1814 | |
| 1815 } | |
| 1816 | |
| 1817 static void irc_close(struct gaim_connection *gc) | |
| 1818 { | |
| 1819 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 1820 GList *chats = idata->channels; | |
| 1821 struct irc_channel *cc; | |
| 1822 | |
| 1823 gchar *buf = (gchar *) g_malloc(IRC_BUF_LEN); | |
| 1824 | |
| 1825 g_snprintf(buf, IRC_BUF_LEN, "QUIT :Download GAIM [%s]\n", WEBSITE); | |
| 1826 write(idata->fd, buf, strlen(buf)); | |
| 1827 | |
| 1828 g_free(buf); | |
| 1829 | |
| 1830 if (idata->timer) | |
|
2131
acc11216ec5d
[gaim-migrate @ 2141]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2123
diff
changeset
|
1831 g_source_remove(idata->timer); |
| 2086 | 1832 |
| 1833 while (chats) { | |
| 1834 cc = (struct irc_channel *)chats->data; | |
| 1835 g_free(cc->name); | |
| 1836 chats = g_list_remove(chats, cc); | |
| 1837 g_free(cc); | |
| 1838 } | |
| 1839 | |
| 1840 if (gc->inpa) | |
|
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
1841 gaim_input_remove(gc->inpa); |
| 2086 | 1842 |
| 1843 if (idata->inpa) | |
|
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
1844 gaim_input_remove(idata->inpa); |
| 2086 | 1845 |
| 1846 close(idata->fd); | |
| 1847 g_free(gc->proto_data); | |
| 1848 } | |
| 1849 | |
| 1850 static void irc_chat_leave(struct gaim_connection *gc, int id) | |
| 1851 { | |
| 1852 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 1853 struct irc_channel *channel; | |
| 1854 gchar *buf = (gchar *) g_malloc(IRC_BUF_LEN + 1); | |
| 1855 | |
| 1856 channel = find_channel_by_id(gc, id); | |
| 1857 | |
| 1858 if (!channel) { | |
| 1859 return; | |
| 1860 } | |
| 1861 | |
| 1862 g_snprintf(buf, IRC_BUF_LEN, "PART #%s\n", channel->name); | |
| 1863 write(idata->fd, buf, strlen(buf)); | |
| 1864 | |
| 1865 g_free(buf); | |
| 1866 } | |
| 1867 | |
|
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
1868 static void irc_login_callback(gpointer data, gint source, GaimInputCondition condition) |
| 2086 | 1869 { |
| 1870 struct gaim_connection *gc = data; | |
| 1871 struct irc_data *idata; | |
| 1872 char buf[4096]; | |
| 1873 | |
| 1874 if (!g_slist_find(connections, gc)) { | |
| 1875 close(source); | |
| 1876 return; | |
| 1877 } | |
| 1878 | |
| 1879 idata = gc->proto_data; | |
| 1880 | |
| 1881 if (source == -1) { | |
| 1882 hide_login_progress(gc, "Write error"); | |
| 1883 signoff(gc); | |
| 1884 return; | |
| 1885 } | |
| 1886 | |
| 1887 if (idata->fd != source) | |
| 1888 idata->fd = source; | |
| 1889 | |
| 1890 g_snprintf(buf, 4096, "NICK %s\n USER %s localhost %s :GAIM (%s)\n", | |
| 1891 gc->username, g_get_user_name(), gc->user->proto_opt[USEROPT_SERV], WEBSITE); | |
| 1892 | |
| 1893 if (write(idata->fd, buf, strlen(buf)) < 0) { | |
| 1894 hide_login_progress(gc, "Write error"); | |
| 1895 signoff(gc); | |
| 1896 return; | |
| 1897 } | |
| 1898 | |
|
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
1899 idata->inpa = gaim_input_add(idata->fd, GAIM_INPUT_READ, irc_callback, gc); |
| 2086 | 1900 idata->inpa = 0; |
| 1901 | |
| 1902 /* Now lets sign ourselves on */ | |
| 1903 account_online(gc); | |
| 1904 serv_finish_login(gc); | |
| 1905 | |
| 1906 if (bud_list_cache_exists(gc)) | |
| 1907 do_import(NULL, gc); | |
| 1908 | |
| 1909 /* we don't call this now because otherwise some IRC servers might not like us */ | |
|
2131
acc11216ec5d
[gaim-migrate @ 2141]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2123
diff
changeset
|
1910 idata->timer = g_timeout_add(20000, irc_request_buddy_update, gc); |
| 2086 | 1911 } |
| 1912 | |
| 1913 static void irc_login(struct aim_user *user) | |
| 1914 { | |
| 1915 char buf[4096]; | |
| 1916 | |
| 1917 struct gaim_connection *gc = new_gaim_conn(user); | |
| 1918 struct irc_data *idata = gc->proto_data = g_new0(struct irc_data, 1); | |
| 1919 | |
| 1920 g_snprintf(buf, sizeof(buf), "Signon: %s", gc->username); | |
| 1921 set_login_progress(gc, 2, buf); | |
| 1922 | |
| 1923 idata->fd = proxy_connect(user->proto_opt[USEROPT_SERV], | |
| 1924 user->proto_opt[USEROPT_PORT][0] ? atoi(user-> | |
| 1925 proto_opt[USEROPT_PORT]) : | |
| 1926 6667, irc_login_callback, gc); | |
| 1927 if (!user->gc || (idata->fd < 0)) { | |
| 1928 hide_login_progress(gc, "Unable to create socket"); | |
| 1929 signoff(gc); | |
| 1930 return; | |
| 1931 } | |
| 1932 } | |
| 1933 | |
| 1934 static void irc_print_option(GtkEntry *entry, struct aim_user *user) | |
| 1935 { | |
| 1936 int entrynum; | |
| 1937 | |
| 1938 entrynum = (int)gtk_object_get_user_data(GTK_OBJECT(entry)); | |
| 1939 | |
| 1940 if (entrynum == USEROPT_SERV) { | |
| 1941 g_snprintf(user->proto_opt[USEROPT_SERV], | |
| 1942 sizeof(user->proto_opt[USEROPT_SERV]), "%s", gtk_entry_get_text(entry)); | |
| 1943 } else if (entrynum == USEROPT_PORT) { | |
| 1944 g_snprintf(user->proto_opt[USEROPT_PORT], | |
| 1945 sizeof(user->proto_opt[USEROPT_PORT]), "%s", gtk_entry_get_text(entry)); | |
| 1946 } | |
| 1947 } | |
| 1948 | |
| 1949 static void irc_user_opts(GtkWidget *book, struct aim_user *user) | |
| 1950 { | |
| 1951 /* so here, we create the new notebook page */ | |
| 1952 GtkWidget *vbox; | |
| 1953 GtkWidget *hbox; | |
| 1954 GtkWidget *label; | |
| 1955 GtkWidget *entry; | |
| 1956 | |
| 1957 vbox = gtk_vbox_new(FALSE, 5); | |
| 1958 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); | |
| 1959 gtk_notebook_append_page(GTK_NOTEBOOK(book), vbox, gtk_label_new("IRC Options")); | |
| 1960 gtk_widget_show(vbox); | |
| 1961 | |
| 1962 hbox = gtk_hbox_new(FALSE, 5); | |
| 1963 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
| 1964 gtk_widget_show(hbox); | |
| 1965 | |
| 1966 label = gtk_label_new("Server:"); | |
| 1967 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
| 1968 gtk_widget_show(label); | |
| 1969 | |
| 1970 entry = gtk_entry_new(); | |
| 1971 gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0); | |
| 1972 gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_SERV); | |
| 1973 gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(irc_print_option), user); | |
| 1974 if (user->proto_opt[USEROPT_SERV][0]) { | |
| 1975 debug_printf("setting text %s\n", user->proto_opt[USEROPT_SERV]); | |
| 1976 gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_SERV]); | |
| 1977 } | |
| 1978 gtk_widget_show(entry); | |
| 1979 | |
| 1980 hbox = gtk_hbox_new(FALSE, 0); | |
| 1981 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
| 1982 gtk_widget_show(hbox); | |
| 1983 | |
| 1984 label = gtk_label_new("Port:"); | |
| 1985 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
| 1986 gtk_widget_show(label); | |
| 1987 | |
| 1988 entry = gtk_entry_new(); | |
| 1989 gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0); | |
| 1990 gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_PORT); | |
| 1991 gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(irc_print_option), user); | |
| 1992 if (user->proto_opt[USEROPT_PORT][0]) { | |
| 1993 debug_printf("setting text %s\n", user->proto_opt[USEROPT_PORT]); | |
| 1994 gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_PORT]); | |
| 1995 } else | |
| 1996 gtk_entry_set_text(GTK_ENTRY(entry), "6667"); | |
| 1997 | |
| 1998 gtk_widget_show(entry); | |
| 1999 } | |
| 2000 | |
| 2001 static char **irc_list_icon(int uc) | |
| 2002 { | |
| 2003 return free_icon_xpm; | |
| 2004 } | |
| 2005 | |
| 2006 /* Send out a ping request to the specified user */ | |
| 2007 static void irc_send_ping(GtkObject *w, char *who) | |
| 2008 { | |
| 2009 struct gaim_connection *gc = (struct gaim_connection *)gtk_object_get_user_data(w); | |
| 2010 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 2011 char buf[BUF_LEN]; | |
| 2012 | |
| 2013 g_snprintf(buf, BUF_LEN, "PRIVMSG %s :%cPING %ld%c\n", who, '\001', time((time_t *) NULL), | |
| 2014 '\001'); | |
| 2015 | |
| 2016 write(idata->fd, buf, strlen(buf)); | |
| 2017 } | |
| 2018 | |
| 2019 /* Do a whois check on someone :-) */ | |
| 2020 static void irc_get_info(struct gaim_connection *gc, char *who) | |
| 2021 { | |
| 2022 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 2023 char buf[BUF_LEN]; | |
| 2024 | |
| 2025 if (((who[0] == '@') || (who[0] == '+')) && (strlen(who) > 1)) | |
| 2026 g_snprintf(buf, BUF_LEN, "WHOIS %s\n", who + 1); | |
| 2027 else | |
| 2028 g_snprintf(buf, BUF_LEN, "WHOIS %s\n", who); | |
| 2029 write(idata->fd, buf, strlen(buf)); | |
| 2030 } | |
| 2031 | |
| 2032 static void irc_send_whois(GtkObject *w, char *who) | |
| 2033 { | |
| 2034 struct gaim_connection *gc = (struct gaim_connection *)gtk_object_get_user_data(w); | |
| 2035 irc_get_info(gc, who); | |
| 2036 } | |
| 2037 | |
| 2038 static void irc_buddy_menu(GtkWidget *menu, struct gaim_connection *gc, char *who) | |
| 2039 { | |
| 2040 GtkWidget *button; | |
| 2041 | |
| 2042 button = gtk_menu_item_new_with_label("Ping"); | |
| 2043 gtk_signal_connect(GTK_OBJECT(button), "activate", GTK_SIGNAL_FUNC(irc_send_ping), who); | |
| 2044 gtk_object_set_user_data(GTK_OBJECT(button), gc); | |
| 2045 gtk_menu_append(GTK_MENU(menu), button); | |
| 2046 gtk_widget_show(button); | |
| 2047 | |
| 2048 button = gtk_menu_item_new_with_label("Whois"); | |
| 2049 gtk_signal_connect(GTK_OBJECT(button), "activate", GTK_SIGNAL_FUNC(irc_send_whois), who); | |
| 2050 gtk_object_set_user_data(GTK_OBJECT(button), gc); | |
| 2051 gtk_menu_append(GTK_MENU(menu), button); | |
| 2052 gtk_widget_show(button); | |
| 2053 } | |
| 2054 | |
| 2055 | |
| 2056 static void irc_set_away(struct gaim_connection *gc, char *state, char *msg) | |
| 2057 { | |
| 2058 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 2059 char buf[BUF_LEN]; | |
| 2060 | |
| 2061 if (msg) | |
| 2062 g_snprintf(buf, BUF_LEN, "AWAY :%s\n", msg); | |
| 2063 else | |
| 2064 g_snprintf(buf, BUF_LEN, "AWAY\n"); | |
| 2065 | |
| 2066 write(idata->fd, buf, strlen(buf)); | |
| 2067 } | |
| 2068 | |
| 2069 static void irc_fake_buddy(struct gaim_connection *gc, char *who) | |
| 2070 { | |
| 2071 /* Heh, there is no buddy list. We fake it. | |
| 2072 * I just need this here so the add and remove buttons will | |
| 2073 * show up */ | |
| 2074 } | |
| 2075 | |
| 2076 static void irc_chat_set_topic(struct gaim_connection *gc, int id, char *topic) | |
| 2077 { | |
| 2078 struct irc_channel *ic = NULL; | |
| 2079 struct irc_data *idata = (struct irc_data *)gc->proto_data; | |
| 2080 char buf[BUF_LEN]; | |
| 2081 | |
| 2082 ic = find_channel_by_id(gc, id); | |
| 2083 | |
| 2084 /* If we ain't in no channel, foo, gets outta da kitchen beeyotch */ | |
| 2085 if (!ic) | |
| 2086 return; | |
| 2087 | |
| 2088 /* Prepare our command */ | |
| 2089 g_snprintf(buf, BUF_LEN, "TOPIC #%s :%s\n", ic->name, topic); | |
| 2090 | |
| 2091 /* And send it */ | |
| 2092 write(idata->fd, buf, strlen(buf)); | |
| 2093 } | |
| 2094 | |
| 2095 static struct prpl *my_protocol = NULL; | |
| 2096 | |
| 2097 void irc_init(struct prpl *ret) | |
| 2098 { | |
| 2099 ret->protocol = PROTO_IRC; | |
|
2100
a93aeb6f813d
[gaim-migrate @ 2110]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2090
diff
changeset
|
2100 ret->options = OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD; |
| 2086 | 2101 ret->name = irc_name; |
| 2102 ret->list_icon = irc_list_icon; | |
| 2103 ret->buddy_menu = irc_buddy_menu; | |
| 2104 ret->user_opts = irc_user_opts; | |
| 2105 ret->login = irc_login; | |
| 2106 ret->close = irc_close; | |
| 2107 ret->send_im = irc_send_im; | |
| 2108 ret->join_chat = irc_join_chat; | |
| 2109 ret->chat_leave = irc_chat_leave; | |
| 2110 ret->chat_send = irc_chat_send; | |
| 2111 ret->get_info = irc_get_info; | |
| 2112 ret->set_away = irc_set_away; | |
| 2113 ret->add_buddy = irc_fake_buddy; | |
| 2114 ret->remove_buddy = irc_fake_buddy; | |
| 2115 ret->chat_set_topic = irc_chat_set_topic; | |
| 2116 my_protocol = ret; | |
| 2117 } | |
| 2118 | |
| 2119 #ifndef STATIC | |
| 2120 | |
| 2121 char *gaim_plugin_init(GModule *handle) | |
| 2122 { | |
| 2123 load_protocol(irc_init, sizeof(struct prpl)); | |
| 2124 return NULL; | |
| 2125 } | |
| 2126 | |
| 2127 void gaim_plugin_remove() | |
| 2128 { | |
| 2129 struct prpl *p = find_prpl(PROTO_IRC); | |
| 2130 if (p == my_protocol) | |
| 2131 unload_protocol(p); | |
| 2132 } | |
| 2133 | |
| 2134 char *name() | |
| 2135 { | |
| 2136 return "IRC"; | |
| 2137 } | |
| 2138 | |
| 2139 char *description() | |
| 2140 { | |
| 2141 return "Allows gaim to use the IRC protocol"; | |
| 2142 } | |
| 2143 | |
| 2144 #endif |
