Mercurial > pidgin
annotate plugins/msn/msn.c @ 1717:1c8e109f8934
[gaim-migrate @ 1727]
Laddy Daa
committer: Tailor Script <tailor@pidgin.im>
| author | Rob Flynn <gaim@robflynn.com> |
|---|---|
| date | Sat, 14 Apr 2001 07:51:55 +0000 |
| parents | 5f3027fbce4c |
| children | 7fc4b9fe295a |
| rev | line source |
|---|---|
| 1259 | 1 /* |
| 2 * gaim - MSN Protocol Plugin | |
| 3 * | |
| 4 * Copyright (C) 2000, Rob Flynn <rob@tgflinux.com> | |
| 5 * | |
| 6 * This program is free software; you can redistribute it and/or modify | |
| 7 * it under the terms of the GNU General Public License as published by | |
| 8 * the Free Software Foundation; either version 2 of the License, or | |
| 9 * (at your option) any later version. | |
| 10 * | |
| 11 * This program is distributed in the hope that it will be useful, | |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 * GNU General Public License for more details. | |
| 15 * | |
| 16 * You should have received a copy of the GNU General Public License | |
| 17 * along with this program; if not, write to the Free Software | |
| 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 * | |
| 20 */ | |
| 21 | |
|
1514
0dd012166152
[gaim-migrate @ 1524]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1499
diff
changeset
|
22 #include "config.h" |
| 1259 | 23 |
| 24 #include <netdb.h> | |
| 25 #include <gtk/gtk.h> | |
| 26 #include <unistd.h> | |
| 27 #include <errno.h> | |
| 28 #include <netinet/in.h> | |
| 29 #include <arpa/inet.h> | |
| 30 #include <string.h> | |
| 31 #include <stdlib.h> | |
| 32 #include <stdio.h> | |
| 33 #include <time.h> | |
| 1567 | 34 #include <fcntl.h> |
| 1259 | 35 #include <sys/socket.h> |
| 36 #include <sys/stat.h> | |
| 1567 | 37 #include <sys/types.h> |
| 1259 | 38 #include "multi.h" |
| 39 #include "prpl.h" | |
| 40 #include "gaim.h" | |
| 41 #include "md5.h" | |
| 42 | |
| 1284 | 43 #include "pixmaps/msn_online.xpm" |
| 1285 | 44 #include "pixmaps/msn_away.xpm" |
| 1717 | 45 #include "pixmaps/ok.xpm" |
| 1284 | 46 |
| 1567 | 47 #define MIME_HEADER "MIME-Version: 1.0\r\nContent-Type: text/plain; charset=UTF-8\r\nX-MMS-IM-Format: FN=MS%20Sans%20Serif; EF=; CO=0; CS=0; PF=0\r\n\r\n" |
| 1259 | 48 |
| 1567 | 49 #define MSN_BUF_LEN 8192 |
| 1259 | 50 |
| 51 #define MSN_ONLINE 1 | |
| 52 #define MSN_BUSY 2 | |
| 53 #define MSN_IDLE 3 | |
| 54 #define MSN_BRB 4 | |
| 55 #define MSN_AWAY 5 | |
| 56 #define MSN_PHONE 6 | |
| 57 #define MSN_LUNCH 7 | |
| 58 #define MSN_OFFLINE 8 | |
| 59 #define MSN_HIDDEN 9 | |
| 60 | |
| 1567 | 61 #define MSN_SIGNON_GOT_XFR 0x0001 |
| 62 #define MSN_SIGNON_SENT_USR 0x0002 | |
| 1259 | 63 |
| 1717 | 64 #define USEROPT_HOTMAIL 0 |
| 65 | |
| 66 struct mod_usr_opt { | |
| 67 struct aim_user *user; | |
| 68 int opt; | |
| 69 }; | |
| 70 | |
| 1598 | 71 struct msn_ask_add_permit { |
| 72 struct gaim_connection *gc; | |
| 73 char *user; | |
| 74 char *friendly; | |
| 75 }; | |
| 76 | |
| 1259 | 77 struct msn_data { |
| 78 int fd; | |
| 79 | |
| 80 char protocol[6]; | |
| 81 char *friendly; | |
| 82 gchar *policy; | |
| 1567 | 83 int inpa; |
| 84 int status; | |
| 1631 | 85 int away; |
| 1567 | 86 time_t last_trid; |
| 1259 | 87 }; |
| 88 | |
| 89 struct msn_conn { | |
| 90 gchar *user; | |
| 91 int inpa; | |
| 92 int fd; | |
| 1572 | 93 struct gaim_connection *gc; |
| 94 char *secret; | |
| 95 char *session; | |
| 1584 | 96 time_t last_trid; |
| 97 char *txqueue; | |
| 1259 | 98 }; |
| 99 | |
| 1567 | 100 GSList *msn_connections = NULL; |
| 1259 | 101 |
| 1567 | 102 unsigned long long globalc = 0; |
| 1572 | 103 static void msn_callback(gpointer data, gint source, GdkInputCondition condition); |
| 1598 | 104 static void msn_add_permit(struct gaim_connection *gc, char *who); |
| 1717 | 105 static void process_hotmail_msg(struct gaim_connection *gc, gchar *msgdata); |
| 1598 | 106 |
| 107 void msn_accept_add_permit(gpointer w, struct msn_ask_add_permit *ap) | |
| 108 { | |
| 109 msn_add_permit(ap->gc, ap->user); | |
| 110 } | |
| 111 | |
| 112 void msn_cancel_add_permit(gpointer w, struct msn_ask_add_permit *ap) | |
| 113 { | |
| 114 g_free(ap->user); | |
| 115 g_free(ap->friendly); | |
| 116 g_free(ap); | |
| 117 } | |
| 1259 | 118 |
| 1588 | 119 void free_msn_conn(struct msn_conn *mc) |
| 120 { | |
| 121 if (mc->user) | |
| 122 free(mc->user); | |
| 123 | |
| 124 if (mc->secret) | |
| 125 free(mc->secret); | |
| 126 | |
| 127 if (mc->session) | |
| 128 free(mc->session); | |
| 129 | |
| 130 if (mc->txqueue) | |
| 131 free(mc->txqueue); | |
| 132 | |
| 133 gdk_input_remove(mc->inpa); | |
| 134 close(mc->fd); | |
| 135 | |
| 136 msn_connections = g_slist_remove(msn_connections, mc); | |
| 137 | |
| 138 g_free(mc); | |
| 139 } | |
| 140 | |
| 141 | |
| 1584 | 142 struct msn_conn *find_msn_conn_by_user(gchar * user) |
| 143 { | |
| 144 struct msn_conn *mc; | |
| 145 GSList *conns = msn_connections; | |
| 146 | |
| 147 while (conns) { | |
| 148 mc = (struct msn_conn *)conns->data; | |
| 149 | |
| 150 if (mc != NULL) { | |
| 151 if (strcasecmp(mc->user, user) == 0) { | |
| 152 return mc; | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 conns = g_slist_next(conns); | |
| 157 } | |
| 158 | |
| 159 return NULL; | |
| 160 } | |
| 161 | |
| 162 struct msn_conn *find_msn_conn_by_trid(time_t trid) | |
| 163 { | |
| 164 struct msn_conn *mc; | |
| 165 GSList *conns = msn_connections; | |
| 166 | |
| 167 while (conns) { | |
| 168 mc = (struct msn_conn *)conns->data; | |
| 169 | |
| 170 if (mc != NULL) { | |
| 171 | |
| 172 printf("Comparing: %d <==> %d\n", mc->last_trid, trid); | |
| 173 if (mc->last_trid == trid) { | |
| 174 return mc; | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 conns = g_slist_next(conns); | |
| 179 } | |
| 180 | |
| 181 return NULL; | |
| 182 } | |
| 183 | |
| 1717 | 184 void msn_des_win(GtkWidget *a, GtkWidget *b); |
| 185 void msn_newmail_dialog(const char *text); | |
| 186 | |
| 1282 | 187 static char *msn_name() |
| 188 { | |
| 1259 | 189 return "MSN"; |
| 190 } | |
| 191 | |
| 1282 | 192 char *name() |
| 193 { | |
| 1259 | 194 return "MSN"; |
| 195 } | |
| 196 | |
| 1282 | 197 char *description() |
| 198 { | |
| 1259 | 199 return "Allows gaim to use the MSN protocol. For some reason, this frightens me."; |
| 200 } | |
| 201 | |
| 1567 | 202 time_t trId(struct msn_data *md) |
| 1282 | 203 { |
| 1567 | 204 md->last_trid = time((time_t *)NULL) + globalc++; |
| 205 return md->last_trid; | |
| 206 } | |
| 207 | |
| 208 void msn_write(int fd, char *buf) | |
| 209 { | |
| 210 write(fd, buf, strlen(buf)); | |
| 1585 | 211 printf("MSN(%d) <== %s", fd, buf); |
| 1567 | 212 } |
| 1259 | 213 |
| 1572 | 214 static void msn_answer_callback(gpointer data, gint source, GdkInputCondition condition) |
| 215 { | |
| 216 struct msn_conn *mc = data; | |
| 217 char buf[MSN_BUF_LEN]; | |
| 218 | |
| 219 fcntl(source, F_SETFL, 0); | |
| 220 | |
| 221 g_snprintf(buf, MSN_BUF_LEN, "ANS 1 %s %s %s\n", mc->gc->username, mc->secret, mc->session); | |
| 222 msn_write(mc->fd, buf); | |
| 223 | |
| 224 gdk_input_remove(mc->inpa); | |
| 225 mc->inpa = gdk_input_add(mc->fd, GDK_INPUT_READ, msn_callback, mc->gc); | |
| 226 | |
| 227 /* Append our connection */ | |
| 228 msn_connections = g_slist_append(msn_connections, mc); | |
| 229 } | |
| 230 | |
| 1584 | 231 static void msn_invite_callback(gpointer data, gint source, GdkInputCondition condition) |
| 232 { | |
| 233 struct msn_conn *mc = data; | |
| 234 struct msn_data *md = (struct msn_data *)mc->gc->proto_data; | |
| 235 char buf[MSN_BUF_LEN]; | |
| 236 struct gaim_connection *gc = mc->gc; | |
| 237 int i = 0; | |
| 1585 | 238 |
| 239 fcntl(source, F_SETFL, 0); | |
| 1584 | 240 |
| 241 if (condition == GDK_INPUT_WRITE) | |
| 242 { | |
| 243 /* We just got in here */ | |
| 244 gdk_input_remove(mc->inpa); | |
| 245 mc->inpa = gdk_input_add(mc->fd, GDK_INPUT_READ, msn_invite_callback, mc); | |
| 246 | |
| 247 /* Write our signon request */ | |
| 248 g_snprintf(buf, MSN_BUF_LEN, "USR %d %s %s\n", mc->last_trid, mc->gc->username, mc->secret); | |
| 1585 | 249 msn_write(mc->fd, buf); |
| 1584 | 250 return; |
| 251 } | |
| 252 | |
| 253 bzero(buf, MSN_BUF_LEN); | |
| 254 do | |
| 255 { | |
| 1588 | 256 if (!read(source, buf + i, 1)) |
| 1584 | 257 { |
| 1588 | 258 free_msn_conn(mc); |
| 1584 | 259 return; |
| 260 } | |
| 261 | |
| 262 } while (buf[i++] != '\n'); | |
| 263 | |
| 264 g_strchomp(buf); | |
| 265 | |
| 1628 | 266 printf("MSN(%d) ==> %s\n", source, buf); |
| 1584 | 267 |
| 268 if (!strncmp("USR ", buf, 4)) | |
| 269 { | |
| 270 char **res; | |
| 271 | |
| 272 res = g_strsplit(buf, " ", 0); | |
| 1585 | 273 printf("%s\n",res[2]); |
| 1584 | 274 if (strcasecmp("OK", res[2])) |
| 275 { | |
| 276 g_strfreev(res); | |
| 277 close(mc->fd); | |
| 278 return; | |
| 279 } | |
| 280 | |
| 281 /* We've authorized. Let's send an invite request */ | |
| 282 g_snprintf(buf, MSN_BUF_LEN, "CAL %d %s\n", trId(md), mc->user); | |
| 283 msn_write(source, buf); | |
| 284 return; | |
| 285 } | |
| 286 | |
| 287 else if (!strncmp("JOI ", buf, 4)) | |
| 288 { | |
| 289 /* Looks like they just joined! Write their queued message */ | |
| 290 g_snprintf(buf, MSN_BUF_LEN, "MSG %d N %d\r\n%s%s", trId(md), strlen(mc->txqueue) + strlen(MIME_HEADER), MIME_HEADER, mc->txqueue); | |
| 291 | |
| 292 msn_write(source, buf); | |
| 293 | |
| 294 gdk_input_remove(mc->inpa); | |
| 295 mc->inpa = gdk_input_add(mc->fd, GDK_INPUT_READ, msn_callback, mc->gc); | |
| 296 | |
| 297 return; | |
| 298 | |
| 299 } | |
| 300 } | |
| 301 | |
| 1567 | 302 static void msn_callback(gpointer data, gint source, GdkInputCondition condition) |
| 303 { | |
| 304 struct gaim_connection *gc = data; | |
| 305 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 306 char buf[MSN_BUF_LEN]; | |
| 307 int i = 0; | |
| 1572 | 308 int num; |
| 1259 | 309 |
| 1567 | 310 bzero(buf, MSN_BUF_LEN); |
| 311 | |
| 312 do | |
| 313 { | |
| 1588 | 314 if (!read(source, buf + i, 1)) |
| 1567 | 315 { |
| 1588 | 316 if (md->fd == source) |
| 317 { | |
| 318 hide_login_progress(gc, "Read error"); | |
| 319 signoff(gc); | |
| 320 } | |
| 321 | |
| 322 close(source); | |
| 323 | |
| 1567 | 324 return; |
| 1259 | 325 } |
| 326 | |
| 1567 | 327 } while (buf[i++] != '\n'); |
| 328 | |
| 329 g_strchomp(buf); | |
| 330 | |
| 1572 | 331 printf("MSN(%d) ==> %s\n", source, buf); |
| 1567 | 332 |
| 1569 | 333 if (!strncmp("NLN ", buf, 4) || !strncmp("ILN ", buf, 4)) |
| 334 { | |
| 335 int status; | |
| 336 int query; | |
| 337 char **res; | |
| 338 | |
| 339 res = g_strsplit(buf, " ", 0); | |
| 340 | |
| 341 if (!strcmp(res[0], "NLN")) | |
| 342 query = 1; | |
| 343 else | |
| 344 query = 2; | |
| 345 | |
| 346 if (!strcasecmp(res[query], "NLN")) | |
| 347 status = UC_NORMAL; | |
| 348 else if (!strcasecmp(res[query], "BSY")) | |
| 349 status = UC_NORMAL | (MSN_BUSY << 5); | |
| 350 else if (!strcasecmp(res[query], "IDL")) | |
| 351 status = UC_NORMAL | (MSN_IDLE << 5); | |
| 352 else if (!strcasecmp(res[query], "BRB")) | |
| 353 status = UC_NORMAL | (MSN_BRB << 5); | |
| 354 else if (!strcasecmp(res[query], "AWY")) | |
| 355 status = UC_UNAVAILABLE; | |
| 356 else if (!strcasecmp(res[query], "PHN")) | |
| 357 status = UC_NORMAL | (MSN_PHONE << 5); | |
| 358 else if (!strcasecmp(res[query], "LUN")) | |
| 359 status = UC_NORMAL | (MSN_LUNCH << 5); | |
| 360 else | |
| 361 status = UC_NORMAL; | |
| 362 | |
| 363 serv_got_update(gc, res[query+1], 1, 0, 0, 0, status, 0); | |
| 364 | |
| 365 g_strfreev(res); | |
| 366 | |
| 367 return; | |
| 368 | |
| 369 } | |
| 1628 | 370 else if (!strncmp("BYE ", buf, 4)) |
| 371 { | |
| 372 char **res; | |
| 373 struct msn_conn *mc; | |
| 374 | |
| 375 res = g_strsplit(buf, " ", 0); | |
| 376 | |
| 377 mc = find_msn_conn_by_user(res[1]); | |
| 378 | |
| 379 if (mc) | |
| 380 { | |
| 381 /* Looks like we need to close up some stuff :-) */ | |
| 382 free_msn_conn(mc); | |
| 383 } | |
| 384 | |
| 385 g_strfreev(res); | |
| 386 return; | |
| 387 } | |
| 1572 | 388 else if (!strncmp("MSG ", buf, 4)) |
| 389 { | |
| 390 /* We are receiving an incoming message */ | |
| 391 gchar **res; | |
| 392 gchar *user; | |
| 393 gchar *msgdata; | |
| 394 int size; | |
| 395 | |
| 396 res = g_strsplit(buf, " ", 0); | |
| 397 | |
| 398 user = g_strdup(res[1]); | |
| 399 size = atoi(res[3]); | |
| 400 | |
| 401 /* Ok, we know who we're receiving a message from as well as | |
| 402 * how big the message is */ | |
| 403 | |
| 404 msgdata = (gchar *)g_malloc(sizeof(gchar) *(size + 1)); | |
| 405 num = recv(source, msgdata, size, 0); | |
| 406 msgdata[size] = 0; | |
| 407 | |
| 408 if (num < size) | |
| 409 printf("MSN: Uhh .. we gots a problem!. Expected %d but got %d.\n", size, num); | |
| 410 | |
| 411 /* We should ignore messages from the user Hotmail */ | |
| 412 if (!strcasecmp("hotmail", res[1])) | |
| 413 { | |
| 1717 | 414 process_hotmail_msg(gc,msgdata); |
| 1572 | 415 g_strfreev(res); |
| 416 g_free(msgdata); | |
| 417 return; | |
| 418 } | |
| 419 | |
| 420 /* Check to see if any body is in the message */ | |
| 421 if (!strcmp(strstr(msgdata, "\r\n\r\n") + 4, "\r\n")) | |
| 422 { | |
| 423 g_strfreev(res); | |
| 424 g_free(msgdata); | |
| 425 return; | |
| 426 } | |
| 427 | |
| 428 /* Otherwise, everything is ok. Let's show the message. Skipping, | |
| 429 * of course, the header. */ | |
| 430 | |
| 431 serv_got_im(gc, res[1], strstr(msgdata, "\r\n\r\n") + 4, 0); | |
| 432 | |
| 433 g_strfreev(res); | |
| 434 g_free(msgdata); | |
| 435 | |
| 436 return; | |
| 437 } | |
| 438 else if (!strncmp("RNG ", buf, 4)) | |
| 439 { | |
| 440 /* Ok, someone wants to talk to us. Ring ring? Hi!!! */ | |
| 441 gchar **address; | |
| 442 gchar **res; | |
| 443 struct msn_conn *mc = g_new0(struct msn_conn, 1); | |
| 444 | |
| 445 res = g_strsplit(buf, " ", 0); | |
| 446 address = g_strsplit(res[2], ":", 0); | |
| 447 | |
| 448 if (!(mc->fd = msn_connect(address[0], atoi(address[1])))) | |
| 449 { | |
| 450 /* Looks like we had an error connecting. */ | |
| 451 g_strfreev(address); | |
| 452 g_strfreev(res); | |
| 453 g_free(mc); | |
| 454 return; | |
| 455 } | |
| 456 | |
| 457 /* Set up our struct with user and input watcher */ | |
| 458 mc->user = g_strdup(res[5]); | |
| 459 mc->secret = g_strdup(res[4]); | |
| 460 mc->session = g_strdup(res[1]); | |
| 461 mc->gc = gc; | |
| 462 | |
| 463 mc->inpa = gdk_input_add(mc->fd, GDK_INPUT_WRITE, msn_answer_callback, mc); | |
| 464 | |
| 465 g_strfreev(address); | |
| 466 g_strfreev(res); | |
| 467 | |
| 468 return; | |
| 469 } | |
| 1584 | 470 else if (!strncmp("XFR ", buf, 4)) |
| 471 { | |
| 472 char **res; | |
| 473 char *host; | |
| 474 char *port; | |
| 475 struct msn_conn *mc; | |
| 476 | |
| 477 res = g_strsplit(buf, " ", 0); | |
| 478 | |
| 479 printf("Last trid is: %d\n", md->last_trid); | |
| 480 printf("This TrId is: %d\n", atoi(res[1])); | |
| 481 | |
| 482 mc = find_msn_conn_by_trid(atoi(res[1])); | |
| 483 | |
| 484 if (!mc) | |
| 485 { | |
| 486 g_strfreev(res); | |
| 487 return; | |
| 488 } | |
| 489 | |
| 490 strcpy(buf, res[3]); | |
| 491 | |
| 492 mc->secret = g_strdup(res[5]); | |
| 493 mc->session = g_strdup(res[1]); | |
| 494 | |
| 495 g_strfreev(res); | |
| 496 | |
| 497 res = g_strsplit(buf, ":", 0); | |
| 498 | |
| 499 /* Now we have the host and port */ | |
| 1585 | 500 if (!(mc->fd = msn_connect(res[0], atoi(res[1])))) |
| 1584 | 501 return; |
| 502 | |
| 503 printf("Connected to: %s:%s\n", res[0], res[1]); | |
| 504 | |
| 1585 | 505 if (mc->inpa) |
| 506 gdk_input_remove(mc->inpa); | |
| 507 | |
| 1584 | 508 mc->inpa = gdk_input_add(mc->fd, GDK_INPUT_WRITE, msn_invite_callback, mc); |
| 509 | |
| 510 g_strfreev(res); | |
| 511 | |
| 512 return; | |
| 513 } | |
| 1569 | 514 else if (!strncmp("LST ", buf, 4)) |
| 1567 | 515 { |
| 516 char **res; | |
| 517 | |
| 518 res = g_strsplit(buf, " ", 0); | |
| 519 | |
| 1568 | 520 /* If we have zero buddies, abort */ |
| 521 if (atoi(res[5]) == 0) | |
| 522 { | |
| 523 g_strfreev(res); | |
| 524 return; | |
| 525 } | |
| 526 | |
| 1567 | 527 /* First, let's check the list type */ |
| 528 if (!strcmp("FL", res[2])) | |
| 529 { | |
| 530 /* We're dealing with a forward list. Add them | |
| 531 * to our buddylist and continue along our | |
| 532 * merry little way */ | |
| 533 | |
| 534 struct buddy *b; | |
| 535 | |
| 536 b = find_buddy(gc, res[6]); | |
| 537 | |
| 538 if (!b) | |
| 539 add_buddy(gc, "Buddies", res[6], res[7]); | |
| 540 } | |
| 541 | |
| 542 g_strfreev(res); | |
| 543 | |
| 544 return; | |
| 1259 | 545 } |
| 1628 | 546 else if (!strncmp("FLN ", buf, 4)) |
| 547 { | |
| 548 /* Someone signed off */ | |
| 549 char **res; | |
| 550 | |
| 551 res = g_strsplit(buf, " ", 0); | |
| 552 | |
| 553 serv_got_update(gc, res[1], 0, 0, 0, 0, 0, 0); | |
| 554 | |
| 555 g_strfreev(res); | |
| 556 | |
| 557 return; | |
| 558 } | |
| 559 if ( (!strncmp("NLN ", buf, 4)) || (!strncmp("ILN ", buf, 4))) | |
| 560 { | |
| 561 int status; | |
| 562 int query; | |
| 563 char **res; | |
| 564 | |
| 565 res = g_strsplit(buf, " ", 0); | |
| 566 | |
| 567 if (strcasecmp(res[0], "NLN") == 0) | |
| 568 query = 1; | |
| 569 else | |
| 570 query = 2; | |
| 571 | |
| 572 if (!strcasecmp(res[query], "NLN")) | |
| 573 status = UC_NORMAL; | |
| 574 else if (!strcasecmp(res[query], "BSY")) | |
| 575 status = UC_NORMAL | (MSN_BUSY << 5); | |
| 576 else if (!strcasecmp(res[query], "IDL")) | |
| 577 status = UC_NORMAL | (MSN_IDLE << 5); | |
| 578 else if (!strcasecmp(res[query], "BRB")) | |
| 579 status = UC_NORMAL | (MSN_BRB << 5); | |
| 580 else if (!strcasecmp(res[query], "AWY")) | |
| 581 status = UC_UNAVAILABLE; | |
| 582 else if (!strcasecmp(res[query], "PHN")) | |
| 583 status = UC_NORMAL | (MSN_PHONE << 5); | |
| 584 else if (!strcasecmp(res[query], "LUN")) | |
| 585 status = UC_NORMAL | (MSN_LUNCH << 5); | |
| 586 else | |
| 587 status = UC_NORMAL; | |
| 588 | |
| 589 serv_got_update(gc, res[query+1], 1, 0, 0, 0, status, 0); | |
| 590 | |
| 591 g_strfreev(res); | |
| 592 return; | |
| 593 } | |
| 1259 | 594 |
| 595 } | |
| 596 | |
| 1567 | 597 static void msn_login_callback(gpointer data, gint source, GdkInputCondition condition) |
| 1282 | 598 { |
| 1567 | 599 struct gaim_connection *gc = data; |
| 600 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 601 char buf[MSN_BUF_LEN]; | |
| 1259 | 602 int i = 0; |
| 1282 | 603 |
| 1567 | 604 if (!gc->inpa) |
| 605 { | |
| 606 fcntl(source, F_SETFL, 0); | |
| 607 | |
| 608 gdk_input_remove(md->inpa); | |
| 609 md->inpa = 0; | |
| 610 | |
| 611 gc->inpa = gdk_input_add(md->fd, GDK_INPUT_READ, msn_login_callback, gc); | |
| 1307 | 612 |
| 1567 | 613 if (md->status & MSN_SIGNON_GOT_XFR) |
| 614 { | |
| 615 /* Looks like we were transfered here. Just send a sign on */ | |
| 616 set_login_progress(gc, 3, "Signing On"); | |
| 617 g_snprintf(buf, MSN_BUF_LEN, "USR %d %s I %s\n", md->last_trid, md->policy, gc->username); | |
| 618 msn_write(md->fd, buf); | |
| 619 | |
| 620 /* Reset this bit */ | |
| 621 md->status ^= MSN_SIGNON_GOT_XFR; | |
| 622 } | |
| 623 else | |
| 624 { | |
| 625 /* Otherwise, send an initial request */ | |
| 626 set_login_progress(gc, 2, "Verifiying"); | |
| 1259 | 627 |
| 1567 | 628 g_snprintf(md->protocol, 6, "MSNP2"); |
| 629 | |
| 630 g_snprintf(buf, MSN_BUF_LEN, "VER %d %s\n", trId(md), md->protocol); | |
| 631 msn_write(md->fd, buf); | |
| 632 } | |
| 633 | |
| 634 return; | |
| 635 } | |
| 636 | |
| 637 bzero(buf, MSN_BUF_LEN); | |
| 638 | |
| 639 do | |
| 640 { | |
| 1588 | 641 if (!read(source, buf + i, 1)) |
| 1567 | 642 { |
| 643 hide_login_progress(gc, "Read error"); | |
| 644 signoff(gc); | |
| 1259 | 645 return; |
| 1567 | 646 } |
| 1259 | 647 |
| 1567 | 648 } while (buf[i++] != '\n'); |
| 1259 | 649 |
| 650 g_strchomp(buf); | |
| 651 | |
| 1567 | 652 printf("MSN ==> %s\n", buf); |
| 653 | |
| 654 /* Check to see what was just sent back to us. We should be seeing a VER tag. */ | |
| 655 if (!strncmp("VER ", buf, 4) && (!strstr("MSNP2", buf))) | |
| 656 { | |
| 657 /* Now that we got our ver, we shoudl send a policy request */ | |
| 658 g_snprintf(buf, MSN_BUF_LEN, "INF %d\n", trId(md)); | |
| 659 msn_write(md->fd, buf); | |
| 660 | |
| 661 return; | |
| 662 } | |
| 663 else if (!strncmp("INF ", buf, 4)) | |
| 664 { | |
| 665 char **res; | |
| 666 | |
| 667 /* Make a copy of our resulting policy */ | |
| 668 res = g_strsplit(buf, " ", 0); | |
| 669 md->policy = g_strdup(res[2]); | |
| 670 | |
| 671 /* And send our signon packet */ | |
| 672 set_login_progress(gc, 3, "Signing On"); | |
| 673 | |
| 674 g_snprintf(buf, MSN_BUF_LEN, "USR %d %s I %s\n", trId(md), md->policy, gc->username); | |
| 675 msn_write(md->fd, buf); | |
| 676 | |
| 677 g_strfreev(res); | |
| 678 | |
| 679 return; | |
| 680 } | |
| 1598 | 681 else if (!strncmp("ADD ", buf, 4)) |
| 682 { | |
| 683 char **res; | |
| 684 | |
| 685 res = g_strsplit(buf, " ", 0); | |
| 686 | |
| 687 if (!strcasecmp(res[2], "RL")) | |
| 688 { | |
| 689 struct msn_ask_add_permit *ap = g_new0(struct msn_ask_add_permit, 1); | |
| 690 | |
| 691 snprintf(buf, MSN_BUF_LEN, "The user %s (%s) wants to add you to their buddylist.", res[4], res[5]); | |
| 692 | |
| 693 ap->user = g_strdup(res[4]); | |
| 694 ap->friendly = g_strdup(res[5]); | |
| 695 ap->gc = gc; | |
| 696 | |
| 697 do_ask_dialog(buf, ap, (GtkFunction) msn_accept_add_permit, (GtkFunction) msn_cancel_add_permit); | |
| 698 } | |
| 699 | |
| 700 g_strfreev(res); | |
| 701 return; | |
| 702 } | |
| 1589 | 703 |
| 1567 | 704 else if (!strncmp("XFR ", buf, 4)) |
| 705 { | |
| 706 char **res; | |
| 707 char *host; | |
| 708 char *port; | |
| 709 | |
| 710 res = g_strsplit(buf, " ", 0); | |
| 711 | |
| 712 strcpy(buf, res[3]); | |
| 713 | |
| 714 g_strfreev(res); | |
| 715 | |
| 716 res = g_strsplit(buf, ":", 0); | |
| 717 | |
| 718 close(md->fd); | |
| 719 | |
| 1603 | 720 set_login_progress(gc, 3, "Connecting to Auth"); |
| 1567 | 721 |
| 722 /* Now we have the host and port */ | |
| 723 if (!(md->fd = msn_connect(res[0], atoi(res[1])))) | |
| 724 { | |
| 725 hide_login_progress(gc, "Error connecting to server"); | |
| 726 signoff(gc); | |
| 727 return; | |
| 728 } | |
| 729 | |
| 730 g_strfreev(res); | |
| 731 | |
| 732 md->status |= MSN_SIGNON_GOT_XFR; | |
| 733 | |
| 734 gdk_input_remove(gc->inpa); | |
| 735 gc->inpa = 0; | |
| 736 | |
| 737 md->inpa = gdk_input_add(md->fd, GDK_INPUT_WRITE, msn_login_callback, gc); | |
| 738 | |
| 739 return; | |
| 740 } | |
| 741 else if (!strncmp("USR ", buf, 4)) | |
| 742 { | |
| 743 if (md->status & MSN_SIGNON_SENT_USR) | |
| 744 { | |
| 745 char **res; | |
| 746 | |
| 747 res = g_strsplit(buf, " ", 0); | |
| 748 | |
| 749 if (strcasecmp("OK", res[2])) | |
| 750 { | |
| 751 hide_login_progress(gc, "Error signing on"); | |
| 752 signoff(gc); | |
| 753 } | |
| 754 else | |
| 755 { | |
| 756 md->friendly = g_strdup(res[4]); | |
| 757 | |
| 758 /* Ok, ok. Your account is FINALLY online. Ya think Microsoft | |
| 759 * could have had any more steps involved? */ | |
| 760 | |
| 761 set_login_progress(gc, 4, "Fetching config"); | |
| 762 | |
| 763 /* Sync our buddylist */ | |
| 764 g_snprintf(buf, MSN_BUF_LEN, "SYN %d 0\n", trId(md)); | |
| 765 msn_write(md->fd, buf); | |
| 766 | |
| 767 /* And set ourselves online */ | |
| 768 g_snprintf(buf, MSN_BUF_LEN, "CHG %d NLN\n", trId(md)); | |
| 769 msn_write(md->fd, buf); | |
| 770 | |
| 771 account_online(gc); | |
| 772 serv_finish_login(gc); | |
| 773 | |
| 774 if (bud_list_cache_exists(gc)) | |
| 775 do_import(NULL, gc); | |
| 776 | |
| 777 gdk_input_remove(gc->inpa); | |
| 778 gc->inpa = gdk_input_add(md->fd, GDK_INPUT_READ, msn_callback, gc); | |
| 779 } | |
| 780 | |
| 781 g_strfreev(res); | |
| 782 } | |
| 783 else | |
| 784 { | |
| 785 char **res; | |
| 786 char buf2[MSN_BUF_LEN]; | |
| 787 int j; | |
| 788 md5_state_t st; | |
| 789 md5_byte_t di[16]; | |
| 790 | |
| 791 res = g_strsplit(buf, " ", 0); | |
| 792 | |
| 793 /* Make a copy of our MD5 Hash key */ | |
| 794 strcpy(buf, res[4]); | |
| 795 | |
| 796 /* Generate our secret with our key and password */ | |
| 797 snprintf(buf2, MSN_BUF_LEN, "%s%s", buf, gc->password); | |
| 798 | |
| 799 md5_init(&st); | |
| 800 md5_append(&st, (const md5_byte_t *)buf2, strlen(buf2)); | |
| 801 md5_finish(&st, di); | |
| 802 | |
| 803 /* Now that we have the MD5 Hash, lets' hex encode this bad boy. I smoke bad crack. */ | |
| 804 sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", | |
| 805 di[0],di[1],di[2],di[3],di[4],di[5],di[6],di[7],di[8],di[9],di[10],di[11],di[12], | |
| 806 di[13],di[14],di[15]); | |
| 807 | |
| 808 /* And now, send our final sign on packet */ | |
| 809 g_snprintf(buf2, MSN_BUF_LEN, "USR %s %s S %s\n", res[1], md->policy, buf); | |
| 810 msn_write(md->fd, buf2); | |
| 811 | |
| 812 md->status |= MSN_SIGNON_SENT_USR; | |
| 813 | |
| 814 g_strfreev(res); | |
| 815 } | |
| 816 | |
| 817 return; | |
| 818 } | |
| 1259 | 819 } |
| 820 | |
| 1282 | 821 int msn_connect(char *server, int port) |
| 822 { | |
| 1259 | 823 int fd; |
| 824 struct hostent *host; | |
| 825 struct sockaddr_in site; | |
| 826 | |
| 1567 | 827 if (!(host = gethostbyname(server))) |
| 828 { | |
| 829 printf("Could not resolve host name: %s\n", server); | |
| 1259 | 830 return -1; |
| 831 } | |
| 832 | |
| 1567 | 833 bzero(&site, sizeof(struct sockaddr_in)); |
| 834 site.sin_port = htons(port); | |
| 835 memcpy(&site.sin_addr, host->h_addr, host->h_length); | |
| 836 site.sin_family = host->h_addrtype; | |
| 1259 | 837 |
| 1567 | 838 fd = socket(host->h_addrtype, SOCK_STREAM, 0); |
| 1259 | 839 |
| 1567 | 840 fcntl(fd, F_SETFL, O_NONBLOCK); |
| 1259 | 841 |
| 1567 | 842 if (connect(fd, (struct sockaddr *)&site, sizeof(struct sockaddr_in)) < 0) |
| 843 { | |
| 844 if ((errno == EINPROGRESS) || (errno == EINTR)) | |
| 845 { | |
| 846 printf("Connection would block\n"); | |
| 847 return fd; | |
| 1259 | 848 } |
| 849 | |
| 1567 | 850 close(fd); |
| 851 fd = -1; | |
| 1259 | 852 } |
| 1567 | 853 |
| 854 return fd; | |
| 1259 | 855 } |
| 856 | |
| 1282 | 857 void msn_login(struct aim_user *user) |
| 858 { | |
| 1567 | 859 struct gaim_connection *gc = new_gaim_conn(user); |
| 860 struct msn_data *md = gc->proto_data = g_new0(struct msn_data, 1); | |
| 1282 | 861 |
| 1567 | 862 gc->inpa = 0; |
| 1282 | 863 |
| 864 set_login_progress(gc, 1, "Connecting"); | |
| 1259 | 865 |
| 866 while (gtk_events_pending()) | |
| 867 gtk_main_iteration(); | |
| 1567 | 868 |
| 1259 | 869 if (!g_slist_find(connections, gc)) |
| 870 return; | |
| 871 | |
| 1567 | 872 md->status = 0; |
| 1282 | 873 |
| 1567 | 874 if (!(md->fd = msn_connect("messenger.hotmail.com", 1863))) |
| 875 { | |
| 876 hide_login_progress(gc, "Error connecting to server"); | |
| 1259 | 877 signoff(gc); |
| 878 return; | |
| 879 } | |
| 880 | |
| 1567 | 881 md->inpa = gdk_input_add(md->fd, GDK_INPUT_WRITE, msn_login_callback, gc); |
| 1259 | 882 |
| 1567 | 883 printf("Connected.\n"); |
| 1284 | 884 } |
| 885 | |
| 1584 | 886 void msn_send_im(struct gaim_connection *gc, char *who, char *message, int away) |
| 887 { | |
| 888 struct msn_conn *mc; | |
| 889 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 890 char buf[MSN_BUF_LEN]; | |
| 891 | |
| 892 if (!g_strcasecmp(who, gc->username)) | |
| 893 { | |
| 894 do_error_dialog("You can not send a message to yourself!", "Gaim: MSN Error"); | |
| 895 return; | |
| 896 } | |
| 897 | |
| 898 mc = find_msn_conn_by_user(who); | |
| 899 | |
| 900 /* If we're not already in a conversation with | |
| 901 * this person then we have to do some tricky things. */ | |
| 902 | |
| 903 if (!mc) | |
| 904 { | |
| 905 gchar buf2[MSN_BUF_LEN]; | |
| 906 gchar *address; | |
| 907 gchar *auth; | |
| 908 gchar **res; | |
| 909 | |
| 910 /* Request a new switchboard connection */ | |
| 911 g_snprintf(buf, MSN_BUF_LEN, "XFR %d SB\n", trId(md)); | |
| 912 msn_write(md->fd, buf); | |
| 913 | |
| 914 mc = g_new0(struct msn_conn, 1); | |
| 915 | |
| 916 mc->user = g_strdup(who); | |
| 917 mc->gc = gc; | |
| 918 mc->last_trid = md->last_trid; | |
| 919 mc->txqueue = g_strdup(message); | |
| 920 | |
| 921 /* Append our connection */ | |
| 922 msn_connections = g_slist_append(msn_connections, mc); | |
| 923 } | |
| 1585 | 924 else |
| 925 { | |
| 1598 | 926 g_snprintf(buf, MSN_BUF_LEN, "MSG %d N %d\r\n%s%s", trId(md), |
| 927 strlen(message) + strlen(MIME_HEADER), MIME_HEADER, message); | |
| 1585 | 928 |
| 929 msn_write(mc->fd, buf); | |
| 930 } | |
| 1584 | 931 |
| 932 } | |
| 933 | |
| 1598 | 934 static void msn_add_buddy(struct gaim_connection *gc, char *who) |
| 935 { | |
| 936 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 937 char buf[MSN_BUF_LEN - 1]; | |
| 938 | |
| 939 snprintf(buf, MSN_BUF_LEN, "ADD %d FL %s %s\n", trId(md), who, who); | |
| 940 msn_write(md->fd, buf); | |
| 941 } | |
| 942 | |
| 943 static void msn_remove_buddy(struct gaim_connection *gc, char *who) | |
| 944 { | |
| 945 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 946 char buf[MSN_BUF_LEN - 1]; | |
| 947 | |
| 948 snprintf(buf, MSN_BUF_LEN, "REM %d FL %s\n", trId(md), who); | |
| 949 msn_write(md->fd, buf); | |
| 950 } | |
| 951 | |
| 952 static void msn_rem_permit(struct gaim_connection *gc, char *who) | |
| 953 { | |
| 954 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 955 char buf[MSN_BUF_LEN - 1]; | |
| 956 | |
| 957 snprintf(buf, MSN_BUF_LEN, "REM %d AL %s\n", trId(md), who); | |
| 958 msn_write(md->fd, buf); | |
| 959 } | |
| 960 | |
| 961 static void msn_add_permit(struct gaim_connection *gc, char *who) | |
| 962 { | |
| 963 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 964 char buf[MSN_BUF_LEN - 1]; | |
| 965 | |
| 966 snprintf(buf, MSN_BUF_LEN, "ADD %d AL %s %s\n", trId(md), who, who); | |
| 967 msn_write(md->fd, buf); | |
| 968 } | |
| 969 | |
| 970 static void msn_rem_deny(struct gaim_connection *gc, char *who) | |
| 971 { | |
| 972 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 973 char buf[MSN_BUF_LEN - 1]; | |
| 974 | |
| 975 snprintf(buf, MSN_BUF_LEN, "REM %d BL %s\n", trId(md), who); | |
| 976 msn_write(md->fd, buf); | |
| 977 } | |
| 978 | |
| 979 static void msn_add_deny(struct gaim_connection *gc, char *who) | |
| 980 { | |
| 981 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 982 char buf[MSN_BUF_LEN - 1]; | |
| 983 | |
| 984 snprintf(buf, MSN_BUF_LEN, "ADD %d BL %s %s\n", trId(md), who, who); | |
| 985 msn_write(md->fd, buf); | |
| 986 } | |
| 987 | |
| 1630 | 988 static GList *msn_away_states() |
| 989 { | |
| 990 GList *m = NULL; | |
| 991 | |
| 992 m = g_list_append(m, "Available"); | |
| 993 m = g_list_append(m, "Away From Computer"); | |
| 994 m = g_list_append(m, "Be Right Back"); | |
| 995 m = g_list_append(m, "Busy"); | |
| 996 m = g_list_append(m, "On The Phone"); | |
| 997 m = g_list_append(m, "Out To Lunch"); | |
| 998 | |
| 999 return m; | |
| 1000 } | |
| 1001 | |
| 1600 | 1002 static void msn_set_away(struct gaim_connection *gc, char *state, char *msg) |
| 1003 { | |
| 1004 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 1005 char buf[MSN_BUF_LEN - 1]; | |
| 1006 | |
| 1630 | 1007 |
| 1008 gc->away = NULL; | |
| 1009 | |
| 1600 | 1010 if (msg) |
| 1630 | 1011 { |
| 1012 gc->away = ""; | |
| 1600 | 1013 snprintf(buf, MSN_BUF_LEN, "CHG %d AWY\n", trId(md)); |
| 1630 | 1014 } |
| 1015 | |
| 1016 else if (state) | |
| 1017 { | |
| 1018 char away[4]; | |
| 1019 | |
| 1020 gc->away = ""; | |
| 1021 | |
| 1022 if (!strcmp(state, "Available")) | |
| 1023 sprintf(away, "NLN"); | |
| 1024 else if (!strcmp(state, "Away From Computer")) | |
| 1025 sprintf(away, "AWY"); | |
| 1026 else if (!strcmp(state, "Be Right Back")) | |
| 1027 sprintf(away, "BRB"); | |
| 1028 else if (!strcmp(state, "Busy")) | |
| 1029 sprintf(away, "BSY"); | |
| 1030 else if (!strcmp(state, "On The Phone")) | |
| 1031 sprintf(away, "PHN"); | |
| 1032 else if (!strcmp(state, "Out To Lunch")) | |
| 1033 sprintf(away, "LUN"); | |
| 1034 else | |
| 1035 sprintf(away, "NLN"); | |
| 1036 | |
| 1037 snprintf(buf, MSN_BUF_LEN, "CHG %d %s\n", trId(md), away); | |
| 1038 } | |
| 1600 | 1039 else if (gc->is_idle) |
| 1040 snprintf(buf, MSN_BUF_LEN, "CHG %d IDL\n", trId(md)); | |
| 1041 else | |
| 1042 snprintf(buf, MSN_BUF_LEN, "CHG %d NLN\n", trId(md)); | |
| 1043 | |
| 1044 msn_write(md->fd, buf); | |
| 1045 } | |
| 1046 | |
| 1047 | |
| 1048 static void msn_set_idle(struct gaim_connection *gc, int idle) | |
| 1049 { | |
| 1050 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 1051 char buf[MSN_BUF_LEN - 1]; | |
| 1052 | |
| 1053 if (idle) | |
| 1054 snprintf(buf, MSN_BUF_LEN, "CHG %d IDL\n", trId(md)); | |
| 1055 else | |
| 1056 snprintf(buf, MSN_BUF_LEN, "CHG %d NLN\n", trId(md)); | |
| 1057 | |
| 1058 msn_write(md->fd, buf); | |
| 1059 } | |
| 1060 | |
| 1061 static void msn_close(struct gaim_connection *gc) | |
| 1062 { | |
| 1063 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
| 1064 char buf[MSN_BUF_LEN - 1]; | |
| 1065 struct msn_conn *mc = NULL; | |
| 1066 | |
| 1067 while (msn_connections) | |
| 1068 { | |
| 1069 mc = (struct msn_conn *)msn_connections->data; | |
| 1070 | |
| 1071 free_msn_conn(mc); | |
| 1072 } | |
| 1073 | |
| 1074 if (md->fd) | |
| 1075 { | |
| 1076 snprintf(buf, MSN_BUF_LEN, "OUT\n"); | |
| 1077 msn_write(md->fd, buf); | |
| 1078 close(md->fd); | |
| 1079 } | |
| 1080 | |
| 1081 if (gc->inpa) | |
| 1082 gdk_input_remove(gc->inpa); | |
| 1083 | |
| 1084 if (md->friendly) | |
| 1085 free(md->friendly); | |
| 1086 | |
| 1087 g_free(gc->proto_data); | |
| 1088 } | |
| 1089 | |
| 1639 | 1090 static char *msn_get_away_text(int s) |
| 1091 { | |
| 1092 switch (s) | |
| 1093 { | |
| 1094 case MSN_BUSY : | |
| 1095 return "Busy"; | |
| 1096 case MSN_BRB : | |
| 1097 return "Be right back"; | |
| 1098 case MSN_AWAY : | |
| 1099 return "Away from the computer"; | |
| 1100 case MSN_PHONE : | |
| 1101 return "On the phone"; | |
| 1102 case MSN_LUNCH : | |
| 1103 return "Out to lunch"; | |
| 1640 | 1104 case MSN_IDLE : |
| 1105 return "Idle"; | |
| 1639 | 1106 default: |
| 1107 return NULL; | |
| 1108 } | |
| 1109 } | |
| 1110 | |
| 1111 static void msn_buddy_menu(GtkWidget *menu, struct gaim_connection *gc, char *who) | |
| 1112 { | |
| 1113 struct buddy *b = find_buddy(gc, who); | |
| 1114 char buf[MSN_BUF_LEN]; | |
| 1115 GtkWidget *button; | |
| 1116 | |
| 1117 if (!(b->uc >> 5)) | |
| 1118 return; | |
| 1119 | |
| 1120 g_snprintf(buf, MSN_BUF_LEN, "Status: %s", msn_get_away_text(b->uc >> 5)); | |
| 1121 | |
| 1122 button = gtk_menu_item_new_with_label(buf); | |
| 1123 gtk_menu_append(GTK_MENU(menu), button); | |
| 1124 gtk_widget_show(button); | |
| 1125 } | |
| 1126 | |
| 1717 | 1127 void msn_newmail_dialog(const char *text) |
| 1128 { | |
| 1129 GtkWidget *window; | |
| 1130 GtkWidget *vbox; | |
| 1131 GtkWidget *label; | |
| 1132 GtkWidget *hbox; | |
| 1133 GtkWidget *button; | |
| 1134 | |
| 1135 window = gtk_window_new(GTK_WINDOW_DIALOG); | |
| 1136 gtk_window_set_wmclass(GTK_WINDOW(window), "prompt", "Gaim"); | |
| 1137 gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, TRUE); | |
| 1138 gtk_window_set_title(GTK_WINDOW(window), _("Gaim-MSN: New Mail")); | |
| 1139 gtk_widget_realize(window); | |
| 1140 aol_icon(window->window); | |
| 1141 | |
| 1142 vbox = gtk_vbox_new(FALSE, 5); | |
| 1143 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); | |
| 1144 gtk_container_add(GTK_CONTAINER(window), vbox); | |
| 1145 | |
| 1146 label = gtk_label_new(text); | |
| 1147 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); | |
| 1148 | |
| 1149 hbox = gtk_hbox_new(FALSE, 5); | |
| 1150 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
| 1151 | |
| 1152 button = picture_button(window, _("OK"), ok_xpm); | |
| 1153 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
| 1154 gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(msn_des_win), window); | |
| 1155 | |
| 1156 gtk_widget_show_all(window); | |
| 1157 } | |
| 1158 | |
| 1159 void msn_des_win(GtkWidget *a, GtkWidget *b) | |
| 1160 { | |
| 1161 gtk_widget_destroy(b); | |
| 1162 } | |
| 1163 | |
| 1164 static void mod_opt(GtkWidget *b, struct mod_usr_opt *m) | |
| 1165 { | |
| 1166 if (m->user) { | |
| 1167 if (m->user->proto_opt[m->opt][0] == '1') | |
| 1168 m->user->proto_opt[m->opt][0] = '\0'; | |
| 1169 else | |
| 1170 strcpy(m->user->proto_opt[m->opt],"1"); | |
| 1171 } | |
| 1172 } | |
| 1173 | |
| 1174 static void free_muo(GtkWidget *b, struct mod_usr_opt *m) | |
| 1175 { | |
| 1176 g_free(m); | |
| 1177 } | |
| 1178 | |
| 1179 static GtkWidget *msn_protoopt_button(const char *text, struct aim_user *u, int option, GtkWidget *box) | |
| 1180 { | |
| 1181 GtkWidget *button; | |
| 1182 struct mod_usr_opt *muo = g_new0(struct mod_usr_opt, 1); | |
| 1183 button = gtk_check_button_new_with_label(text); | |
| 1184 if (u) { | |
| 1185 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (u->proto_opt[option][0] == '1')); | |
| 1186 } | |
| 1187 gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0); | |
| 1188 muo->user = u; | |
| 1189 muo->opt = option; | |
| 1190 gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(mod_opt), muo); | |
| 1191 gtk_signal_connect(GTK_OBJECT(button), "destroy", GTK_SIGNAL_FUNC(free_muo), muo); | |
| 1192 gtk_widget_show(button); | |
| 1193 return button; | |
| 1194 } | |
| 1195 | |
| 1196 static void msn_user_opts(GtkWidget *book, struct aim_user *user) { | |
| 1197 GtkWidget *vbox; | |
| 1198 GtkWidget *button; | |
| 1199 | |
| 1200 vbox = gtk_vbox_new(FALSE, 5); | |
| 1201 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); | |
| 1202 gtk_notebook_append_page(GTK_NOTEBOOK(book), vbox, | |
| 1203 gtk_label_new("MSN Options")); | |
| 1204 gtk_widget_show(vbox); | |
| 1205 button = msn_protoopt_button("Notify me of new HotMail",user,USEROPT_HOTMAIL,vbox); | |
| 1206 } | |
| 1207 | |
| 1208 /* | |
| 1209 Process messages from Hotmail service. right now we just check for new | |
| 1210 mail notifications, if the user has checking enabled. | |
| 1211 */ | |
| 1212 | |
| 1213 static void process_hotmail_msg(struct gaim_connection *gc, gchar *msgdata) | |
| 1214 { | |
| 1215 gchar *mailnotice; | |
| 1216 char *mailfrom,*mailsubj,*mailct,*mailp; | |
| 1217 | |
| 1218 if (gc->user->proto_opt[USEROPT_HOTMAIL][0] != '1') return; | |
| 1219 mailfrom=NULL; mailsubj=NULL; mailct=NULL; mailp=NULL; | |
| 1220 mailct = strstr(msgdata,"Content-Type: "); | |
| 1221 mailp = strstr(mailct,";"); | |
| 1222 if (mailct != NULL && mailp != NULL && mailp > mailct && !strncmp(mailct,"Content-Type: text/x-msmsgsemailnotification",(mailp-mailct)-1)) | |
| 1223 { | |
| 1224 mailfrom=strstr(mailp,"From: "); | |
| 1225 mailsubj=strstr(mailp,"Subject: "); | |
| 1226 } | |
| 1227 | |
| 1228 if (mailfrom != NULL && mailsubj != NULL) | |
| 1229 { | |
| 1230 mailfrom += 6; | |
| 1231 mailp=strstr(mailfrom,"\r\n"); | |
| 1232 if (mailp==NULL) return; | |
| 1233 *mailp = 0; | |
| 1234 mailsubj += 9; | |
| 1235 mailp=strstr(mailsubj,"\r\n"); | |
| 1236 if (mailp==NULL) return; | |
| 1237 *mailp = 0; | |
| 1238 mailnotice = (gchar *)g_malloc(sizeof(gchar) *(strlen(mailfrom)+strlen(mailsubj)+128)); | |
| 1239 sprintf(mailnotice,"Mail from %s, re: %s",mailfrom,mailsubj); | |
| 1240 msn_newmail_dialog(mailnotice); | |
| 1241 g_free(mailnotice); | |
| 1242 } | |
| 1243 } | |
| 1244 | |
| 1572 | 1245 static char **msn_list_icon(int uc) |
| 1246 { | |
| 1247 if (uc == UC_UNAVAILABLE) | |
| 1248 return msn_away_xpm; | |
| 1249 else if (uc == UC_NORMAL) | |
| 1250 return msn_online_xpm; | |
| 1251 | |
| 1631 | 1252 return msn_away_xpm; |
| 1572 | 1253 } |
| 1254 | |
| 1259 | 1255 static struct prpl *my_protocol = NULL; |
| 1256 | |
| 1282 | 1257 void msn_init(struct prpl *ret) |
| 1258 { | |
| 1259 | 1259 ret->protocol = PROTO_MSN; |
| 1260 ret->name = msn_name; | |
| 1572 | 1261 ret->list_icon = msn_list_icon; |
| 1639 | 1262 ret->buddy_menu = msn_buddy_menu; |
| 1717 | 1263 ret->user_opts = msn_user_opts; |
| 1259 | 1264 ret->login = msn_login; |
| 1600 | 1265 ret->close = msn_close; |
| 1584 | 1266 ret->send_im = msn_send_im; |
| 1259 | 1267 ret->set_info = NULL; |
| 1268 ret->get_info = NULL; | |
| 1630 | 1269 ret->away_states = msn_away_states; |
| 1600 | 1270 ret->set_away = msn_set_away; |
| 1259 | 1271 ret->get_away_msg = NULL; |
| 1272 ret->set_dir = NULL; | |
| 1273 ret->get_dir = NULL; | |
| 1274 ret->dir_search = NULL; | |
| 1600 | 1275 ret->set_idle = msn_set_idle; |
| 1259 | 1276 ret->change_passwd = NULL; |
| 1598 | 1277 ret->add_buddy = msn_add_buddy; |
| 1259 | 1278 ret->add_buddies = NULL; |
| 1598 | 1279 ret->remove_buddy = msn_remove_buddy; |
| 1280 ret->add_permit = msn_add_permit; | |
| 1281 ret->rem_permit = msn_rem_permit; | |
| 1282 ret->add_deny = msn_add_deny; | |
| 1283 ret->rem_deny = msn_rem_deny; | |
| 1259 | 1284 ret->warn = NULL; |
| 1285 ret->accept_chat = NULL; | |
| 1286 ret->join_chat = NULL; | |
| 1287 ret->chat_invite = NULL; | |
| 1288 ret->chat_leave = NULL; | |
| 1289 ret->chat_whisper = NULL; | |
| 1290 ret->chat_send = NULL; | |
| 1291 ret->keepalive = NULL; | |
| 1292 | |
| 1293 my_protocol = ret; | |
| 1294 } | |
| 1295 | |
| 1282 | 1296 char *gaim_plugin_init(GModule * handle) |
| 1297 { | |
|
1443
336fc98b7f90
[gaim-migrate @ 1453]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1327
diff
changeset
|
1298 load_protocol(msn_init, sizeof(struct prpl)); |
| 1259 | 1299 return NULL; |
| 1300 } | |
| 1301 | |
| 1282 | 1302 void gaim_plugin_remove() |
| 1303 { | |
| 1259 | 1304 struct prpl *p = find_prpl(PROTO_MSN); |
| 1305 if (p == my_protocol) | |
| 1306 unload_protocol(p); | |
| 1307 } |
