Mercurial > pidgin.yaz
annotate plugins/msn/msn.c @ 1731:7fc4b9fe295a
[gaim-migrate @ 1741]
hi rob
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Fri, 20 Apr 2001 08:27:43 +0000 |
parents | 1c8e109f8934 |
children | 4e51ddc6632f |
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; | |
1731
7fc4b9fe295a
[gaim-migrate @ 1741]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1717
diff
changeset
|
395 char rahc[MSN_BUF_LEN * 2]; |
1572 | 396 |
397 res = g_strsplit(buf, " ", 0); | |
398 | |
399 user = g_strdup(res[1]); | |
400 size = atoi(res[3]); | |
401 | |
402 /* Ok, we know who we're receiving a message from as well as | |
403 * how big the message is */ | |
404 | |
405 msgdata = (gchar *)g_malloc(sizeof(gchar) *(size + 1)); | |
406 num = recv(source, msgdata, size, 0); | |
407 msgdata[size] = 0; | |
408 | |
409 if (num < size) | |
410 printf("MSN: Uhh .. we gots a problem!. Expected %d but got %d.\n", size, num); | |
411 | |
412 /* We should ignore messages from the user Hotmail */ | |
413 if (!strcasecmp("hotmail", res[1])) | |
414 { | |
1717 | 415 process_hotmail_msg(gc,msgdata); |
1572 | 416 g_strfreev(res); |
417 g_free(msgdata); | |
418 return; | |
419 } | |
420 | |
421 /* Check to see if any body is in the message */ | |
422 if (!strcmp(strstr(msgdata, "\r\n\r\n") + 4, "\r\n")) | |
423 { | |
424 g_strfreev(res); | |
425 g_free(msgdata); | |
426 return; | |
427 } | |
428 | |
429 /* Otherwise, everything is ok. Let's show the message. Skipping, | |
430 * of course, the header. */ | |
431 | |
1731
7fc4b9fe295a
[gaim-migrate @ 1741]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1717
diff
changeset
|
432 g_snprintf(rahc, sizeof(rahc), "%s", strstr(msgdata, "\r\n\r\n") + 4); |
7fc4b9fe295a
[gaim-migrate @ 1741]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1717
diff
changeset
|
433 serv_got_im(gc, res[1], rahc, 0); |
1572 | 434 |
435 g_strfreev(res); | |
436 g_free(msgdata); | |
437 | |
438 return; | |
439 } | |
440 else if (!strncmp("RNG ", buf, 4)) | |
441 { | |
442 /* Ok, someone wants to talk to us. Ring ring? Hi!!! */ | |
443 gchar **address; | |
444 gchar **res; | |
445 struct msn_conn *mc = g_new0(struct msn_conn, 1); | |
446 | |
447 res = g_strsplit(buf, " ", 0); | |
448 address = g_strsplit(res[2], ":", 0); | |
449 | |
450 if (!(mc->fd = msn_connect(address[0], atoi(address[1])))) | |
451 { | |
452 /* Looks like we had an error connecting. */ | |
453 g_strfreev(address); | |
454 g_strfreev(res); | |
455 g_free(mc); | |
456 return; | |
457 } | |
458 | |
459 /* Set up our struct with user and input watcher */ | |
460 mc->user = g_strdup(res[5]); | |
461 mc->secret = g_strdup(res[4]); | |
462 mc->session = g_strdup(res[1]); | |
463 mc->gc = gc; | |
464 | |
465 mc->inpa = gdk_input_add(mc->fd, GDK_INPUT_WRITE, msn_answer_callback, mc); | |
466 | |
467 g_strfreev(address); | |
468 g_strfreev(res); | |
469 | |
470 return; | |
471 } | |
1584 | 472 else if (!strncmp("XFR ", buf, 4)) |
473 { | |
474 char **res; | |
475 char *host; | |
476 char *port; | |
477 struct msn_conn *mc; | |
478 | |
479 res = g_strsplit(buf, " ", 0); | |
480 | |
481 printf("Last trid is: %d\n", md->last_trid); | |
482 printf("This TrId is: %d\n", atoi(res[1])); | |
483 | |
484 mc = find_msn_conn_by_trid(atoi(res[1])); | |
485 | |
486 if (!mc) | |
487 { | |
488 g_strfreev(res); | |
489 return; | |
490 } | |
491 | |
492 strcpy(buf, res[3]); | |
493 | |
494 mc->secret = g_strdup(res[5]); | |
495 mc->session = g_strdup(res[1]); | |
496 | |
497 g_strfreev(res); | |
498 | |
499 res = g_strsplit(buf, ":", 0); | |
500 | |
501 /* Now we have the host and port */ | |
1585 | 502 if (!(mc->fd = msn_connect(res[0], atoi(res[1])))) |
1584 | 503 return; |
504 | |
505 printf("Connected to: %s:%s\n", res[0], res[1]); | |
506 | |
1585 | 507 if (mc->inpa) |
508 gdk_input_remove(mc->inpa); | |
509 | |
1584 | 510 mc->inpa = gdk_input_add(mc->fd, GDK_INPUT_WRITE, msn_invite_callback, mc); |
511 | |
512 g_strfreev(res); | |
513 | |
514 return; | |
515 } | |
1569 | 516 else if (!strncmp("LST ", buf, 4)) |
1567 | 517 { |
518 char **res; | |
519 | |
520 res = g_strsplit(buf, " ", 0); | |
521 | |
1568 | 522 /* If we have zero buddies, abort */ |
523 if (atoi(res[5]) == 0) | |
524 { | |
525 g_strfreev(res); | |
526 return; | |
527 } | |
528 | |
1567 | 529 /* First, let's check the list type */ |
530 if (!strcmp("FL", res[2])) | |
531 { | |
532 /* We're dealing with a forward list. Add them | |
533 * to our buddylist and continue along our | |
534 * merry little way */ | |
535 | |
536 struct buddy *b; | |
537 | |
538 b = find_buddy(gc, res[6]); | |
539 | |
540 if (!b) | |
541 add_buddy(gc, "Buddies", res[6], res[7]); | |
542 } | |
543 | |
544 g_strfreev(res); | |
545 | |
546 return; | |
1259 | 547 } |
1628 | 548 else if (!strncmp("FLN ", buf, 4)) |
549 { | |
550 /* Someone signed off */ | |
551 char **res; | |
552 | |
553 res = g_strsplit(buf, " ", 0); | |
554 | |
555 serv_got_update(gc, res[1], 0, 0, 0, 0, 0, 0); | |
556 | |
557 g_strfreev(res); | |
558 | |
559 return; | |
560 } | |
561 if ( (!strncmp("NLN ", buf, 4)) || (!strncmp("ILN ", buf, 4))) | |
562 { | |
563 int status; | |
564 int query; | |
565 char **res; | |
566 | |
567 res = g_strsplit(buf, " ", 0); | |
568 | |
569 if (strcasecmp(res[0], "NLN") == 0) | |
570 query = 1; | |
571 else | |
572 query = 2; | |
573 | |
574 if (!strcasecmp(res[query], "NLN")) | |
575 status = UC_NORMAL; | |
576 else if (!strcasecmp(res[query], "BSY")) | |
577 status = UC_NORMAL | (MSN_BUSY << 5); | |
578 else if (!strcasecmp(res[query], "IDL")) | |
579 status = UC_NORMAL | (MSN_IDLE << 5); | |
580 else if (!strcasecmp(res[query], "BRB")) | |
581 status = UC_NORMAL | (MSN_BRB << 5); | |
582 else if (!strcasecmp(res[query], "AWY")) | |
583 status = UC_UNAVAILABLE; | |
584 else if (!strcasecmp(res[query], "PHN")) | |
585 status = UC_NORMAL | (MSN_PHONE << 5); | |
586 else if (!strcasecmp(res[query], "LUN")) | |
587 status = UC_NORMAL | (MSN_LUNCH << 5); | |
588 else | |
589 status = UC_NORMAL; | |
590 | |
591 serv_got_update(gc, res[query+1], 1, 0, 0, 0, status, 0); | |
592 | |
593 g_strfreev(res); | |
594 return; | |
595 } | |
1259 | 596 |
597 } | |
598 | |
1567 | 599 static void msn_login_callback(gpointer data, gint source, GdkInputCondition condition) |
1282 | 600 { |
1567 | 601 struct gaim_connection *gc = data; |
602 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
603 char buf[MSN_BUF_LEN]; | |
1259 | 604 int i = 0; |
1282 | 605 |
1567 | 606 if (!gc->inpa) |
607 { | |
608 fcntl(source, F_SETFL, 0); | |
609 | |
610 gdk_input_remove(md->inpa); | |
611 md->inpa = 0; | |
612 | |
613 gc->inpa = gdk_input_add(md->fd, GDK_INPUT_READ, msn_login_callback, gc); | |
1307 | 614 |
1567 | 615 if (md->status & MSN_SIGNON_GOT_XFR) |
616 { | |
617 /* Looks like we were transfered here. Just send a sign on */ | |
618 set_login_progress(gc, 3, "Signing On"); | |
619 g_snprintf(buf, MSN_BUF_LEN, "USR %d %s I %s\n", md->last_trid, md->policy, gc->username); | |
620 msn_write(md->fd, buf); | |
621 | |
622 /* Reset this bit */ | |
623 md->status ^= MSN_SIGNON_GOT_XFR; | |
624 } | |
625 else | |
626 { | |
627 /* Otherwise, send an initial request */ | |
628 set_login_progress(gc, 2, "Verifiying"); | |
1259 | 629 |
1567 | 630 g_snprintf(md->protocol, 6, "MSNP2"); |
631 | |
632 g_snprintf(buf, MSN_BUF_LEN, "VER %d %s\n", trId(md), md->protocol); | |
633 msn_write(md->fd, buf); | |
634 } | |
635 | |
636 return; | |
637 } | |
638 | |
639 bzero(buf, MSN_BUF_LEN); | |
640 | |
641 do | |
642 { | |
1588 | 643 if (!read(source, buf + i, 1)) |
1567 | 644 { |
645 hide_login_progress(gc, "Read error"); | |
646 signoff(gc); | |
1259 | 647 return; |
1567 | 648 } |
1259 | 649 |
1567 | 650 } while (buf[i++] != '\n'); |
1259 | 651 |
652 g_strchomp(buf); | |
653 | |
1567 | 654 printf("MSN ==> %s\n", buf); |
655 | |
656 /* Check to see what was just sent back to us. We should be seeing a VER tag. */ | |
657 if (!strncmp("VER ", buf, 4) && (!strstr("MSNP2", buf))) | |
658 { | |
659 /* Now that we got our ver, we shoudl send a policy request */ | |
660 g_snprintf(buf, MSN_BUF_LEN, "INF %d\n", trId(md)); | |
661 msn_write(md->fd, buf); | |
662 | |
663 return; | |
664 } | |
665 else if (!strncmp("INF ", buf, 4)) | |
666 { | |
667 char **res; | |
668 | |
669 /* Make a copy of our resulting policy */ | |
670 res = g_strsplit(buf, " ", 0); | |
671 md->policy = g_strdup(res[2]); | |
672 | |
673 /* And send our signon packet */ | |
674 set_login_progress(gc, 3, "Signing On"); | |
675 | |
676 g_snprintf(buf, MSN_BUF_LEN, "USR %d %s I %s\n", trId(md), md->policy, gc->username); | |
677 msn_write(md->fd, buf); | |
678 | |
679 g_strfreev(res); | |
680 | |
681 return; | |
682 } | |
1598 | 683 else if (!strncmp("ADD ", buf, 4)) |
684 { | |
685 char **res; | |
686 | |
687 res = g_strsplit(buf, " ", 0); | |
688 | |
689 if (!strcasecmp(res[2], "RL")) | |
690 { | |
691 struct msn_ask_add_permit *ap = g_new0(struct msn_ask_add_permit, 1); | |
692 | |
693 snprintf(buf, MSN_BUF_LEN, "The user %s (%s) wants to add you to their buddylist.", res[4], res[5]); | |
694 | |
695 ap->user = g_strdup(res[4]); | |
696 ap->friendly = g_strdup(res[5]); | |
697 ap->gc = gc; | |
698 | |
699 do_ask_dialog(buf, ap, (GtkFunction) msn_accept_add_permit, (GtkFunction) msn_cancel_add_permit); | |
700 } | |
701 | |
702 g_strfreev(res); | |
703 return; | |
704 } | |
1589 | 705 |
1567 | 706 else if (!strncmp("XFR ", buf, 4)) |
707 { | |
708 char **res; | |
709 char *host; | |
710 char *port; | |
711 | |
712 res = g_strsplit(buf, " ", 0); | |
713 | |
714 strcpy(buf, res[3]); | |
715 | |
716 g_strfreev(res); | |
717 | |
718 res = g_strsplit(buf, ":", 0); | |
719 | |
720 close(md->fd); | |
721 | |
1603 | 722 set_login_progress(gc, 3, "Connecting to Auth"); |
1567 | 723 |
724 /* Now we have the host and port */ | |
725 if (!(md->fd = msn_connect(res[0], atoi(res[1])))) | |
726 { | |
727 hide_login_progress(gc, "Error connecting to server"); | |
728 signoff(gc); | |
729 return; | |
730 } | |
731 | |
732 g_strfreev(res); | |
733 | |
734 md->status |= MSN_SIGNON_GOT_XFR; | |
735 | |
736 gdk_input_remove(gc->inpa); | |
737 gc->inpa = 0; | |
738 | |
739 md->inpa = gdk_input_add(md->fd, GDK_INPUT_WRITE, msn_login_callback, gc); | |
740 | |
741 return; | |
742 } | |
743 else if (!strncmp("USR ", buf, 4)) | |
744 { | |
745 if (md->status & MSN_SIGNON_SENT_USR) | |
746 { | |
747 char **res; | |
748 | |
749 res = g_strsplit(buf, " ", 0); | |
750 | |
751 if (strcasecmp("OK", res[2])) | |
752 { | |
753 hide_login_progress(gc, "Error signing on"); | |
754 signoff(gc); | |
755 } | |
756 else | |
757 { | |
758 md->friendly = g_strdup(res[4]); | |
759 | |
760 /* Ok, ok. Your account is FINALLY online. Ya think Microsoft | |
761 * could have had any more steps involved? */ | |
762 | |
763 set_login_progress(gc, 4, "Fetching config"); | |
764 | |
765 /* Sync our buddylist */ | |
766 g_snprintf(buf, MSN_BUF_LEN, "SYN %d 0\n", trId(md)); | |
767 msn_write(md->fd, buf); | |
768 | |
769 /* And set ourselves online */ | |
770 g_snprintf(buf, MSN_BUF_LEN, "CHG %d NLN\n", trId(md)); | |
771 msn_write(md->fd, buf); | |
772 | |
773 account_online(gc); | |
774 serv_finish_login(gc); | |
775 | |
776 if (bud_list_cache_exists(gc)) | |
777 do_import(NULL, gc); | |
778 | |
779 gdk_input_remove(gc->inpa); | |
780 gc->inpa = gdk_input_add(md->fd, GDK_INPUT_READ, msn_callback, gc); | |
781 } | |
782 | |
783 g_strfreev(res); | |
784 } | |
785 else | |
786 { | |
787 char **res; | |
788 char buf2[MSN_BUF_LEN]; | |
789 int j; | |
790 md5_state_t st; | |
791 md5_byte_t di[16]; | |
792 | |
793 res = g_strsplit(buf, " ", 0); | |
794 | |
795 /* Make a copy of our MD5 Hash key */ | |
796 strcpy(buf, res[4]); | |
797 | |
798 /* Generate our secret with our key and password */ | |
799 snprintf(buf2, MSN_BUF_LEN, "%s%s", buf, gc->password); | |
800 | |
801 md5_init(&st); | |
802 md5_append(&st, (const md5_byte_t *)buf2, strlen(buf2)); | |
803 md5_finish(&st, di); | |
804 | |
805 /* Now that we have the MD5 Hash, lets' hex encode this bad boy. I smoke bad crack. */ | |
806 sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", | |
807 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], | |
808 di[13],di[14],di[15]); | |
809 | |
810 /* And now, send our final sign on packet */ | |
811 g_snprintf(buf2, MSN_BUF_LEN, "USR %s %s S %s\n", res[1], md->policy, buf); | |
812 msn_write(md->fd, buf2); | |
813 | |
814 md->status |= MSN_SIGNON_SENT_USR; | |
815 | |
816 g_strfreev(res); | |
817 } | |
818 | |
819 return; | |
820 } | |
1259 | 821 } |
822 | |
1282 | 823 int msn_connect(char *server, int port) |
824 { | |
1259 | 825 int fd; |
826 struct hostent *host; | |
827 struct sockaddr_in site; | |
828 | |
1567 | 829 if (!(host = gethostbyname(server))) |
830 { | |
831 printf("Could not resolve host name: %s\n", server); | |
1259 | 832 return -1; |
833 } | |
834 | |
1567 | 835 bzero(&site, sizeof(struct sockaddr_in)); |
836 site.sin_port = htons(port); | |
837 memcpy(&site.sin_addr, host->h_addr, host->h_length); | |
838 site.sin_family = host->h_addrtype; | |
1259 | 839 |
1567 | 840 fd = socket(host->h_addrtype, SOCK_STREAM, 0); |
1259 | 841 |
1567 | 842 fcntl(fd, F_SETFL, O_NONBLOCK); |
1259 | 843 |
1567 | 844 if (connect(fd, (struct sockaddr *)&site, sizeof(struct sockaddr_in)) < 0) |
845 { | |
846 if ((errno == EINPROGRESS) || (errno == EINTR)) | |
847 { | |
848 printf("Connection would block\n"); | |
849 return fd; | |
1259 | 850 } |
851 | |
1567 | 852 close(fd); |
853 fd = -1; | |
1259 | 854 } |
1567 | 855 |
856 return fd; | |
1259 | 857 } |
858 | |
1282 | 859 void msn_login(struct aim_user *user) |
860 { | |
1567 | 861 struct gaim_connection *gc = new_gaim_conn(user); |
862 struct msn_data *md = gc->proto_data = g_new0(struct msn_data, 1); | |
1282 | 863 |
1567 | 864 gc->inpa = 0; |
1282 | 865 |
866 set_login_progress(gc, 1, "Connecting"); | |
1259 | 867 |
868 while (gtk_events_pending()) | |
869 gtk_main_iteration(); | |
1567 | 870 |
1259 | 871 if (!g_slist_find(connections, gc)) |
872 return; | |
873 | |
1567 | 874 md->status = 0; |
1282 | 875 |
1567 | 876 if (!(md->fd = msn_connect("messenger.hotmail.com", 1863))) |
877 { | |
878 hide_login_progress(gc, "Error connecting to server"); | |
1259 | 879 signoff(gc); |
880 return; | |
881 } | |
882 | |
1567 | 883 md->inpa = gdk_input_add(md->fd, GDK_INPUT_WRITE, msn_login_callback, gc); |
1259 | 884 |
1567 | 885 printf("Connected.\n"); |
1284 | 886 } |
887 | |
1584 | 888 void msn_send_im(struct gaim_connection *gc, char *who, char *message, int away) |
889 { | |
890 struct msn_conn *mc; | |
891 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
892 char buf[MSN_BUF_LEN]; | |
893 | |
894 if (!g_strcasecmp(who, gc->username)) | |
895 { | |
896 do_error_dialog("You can not send a message to yourself!", "Gaim: MSN Error"); | |
897 return; | |
898 } | |
899 | |
900 mc = find_msn_conn_by_user(who); | |
901 | |
902 /* If we're not already in a conversation with | |
903 * this person then we have to do some tricky things. */ | |
904 | |
905 if (!mc) | |
906 { | |
907 gchar buf2[MSN_BUF_LEN]; | |
908 gchar *address; | |
909 gchar *auth; | |
910 gchar **res; | |
911 | |
912 /* Request a new switchboard connection */ | |
913 g_snprintf(buf, MSN_BUF_LEN, "XFR %d SB\n", trId(md)); | |
914 msn_write(md->fd, buf); | |
915 | |
916 mc = g_new0(struct msn_conn, 1); | |
917 | |
918 mc->user = g_strdup(who); | |
919 mc->gc = gc; | |
920 mc->last_trid = md->last_trid; | |
921 mc->txqueue = g_strdup(message); | |
922 | |
923 /* Append our connection */ | |
924 msn_connections = g_slist_append(msn_connections, mc); | |
925 } | |
1585 | 926 else |
927 { | |
1598 | 928 g_snprintf(buf, MSN_BUF_LEN, "MSG %d N %d\r\n%s%s", trId(md), |
929 strlen(message) + strlen(MIME_HEADER), MIME_HEADER, message); | |
1585 | 930 |
931 msn_write(mc->fd, buf); | |
932 } | |
1584 | 933 |
934 } | |
935 | |
1598 | 936 static void msn_add_buddy(struct gaim_connection *gc, char *who) |
937 { | |
938 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
939 char buf[MSN_BUF_LEN - 1]; | |
940 | |
941 snprintf(buf, MSN_BUF_LEN, "ADD %d FL %s %s\n", trId(md), who, who); | |
942 msn_write(md->fd, buf); | |
943 } | |
944 | |
945 static void msn_remove_buddy(struct gaim_connection *gc, char *who) | |
946 { | |
947 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
948 char buf[MSN_BUF_LEN - 1]; | |
949 | |
950 snprintf(buf, MSN_BUF_LEN, "REM %d FL %s\n", trId(md), who); | |
951 msn_write(md->fd, buf); | |
952 } | |
953 | |
954 static void msn_rem_permit(struct gaim_connection *gc, char *who) | |
955 { | |
956 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
957 char buf[MSN_BUF_LEN - 1]; | |
958 | |
959 snprintf(buf, MSN_BUF_LEN, "REM %d AL %s\n", trId(md), who); | |
960 msn_write(md->fd, buf); | |
961 } | |
962 | |
963 static void msn_add_permit(struct gaim_connection *gc, char *who) | |
964 { | |
965 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
966 char buf[MSN_BUF_LEN - 1]; | |
967 | |
968 snprintf(buf, MSN_BUF_LEN, "ADD %d AL %s %s\n", trId(md), who, who); | |
969 msn_write(md->fd, buf); | |
970 } | |
971 | |
972 static void msn_rem_deny(struct gaim_connection *gc, char *who) | |
973 { | |
974 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
975 char buf[MSN_BUF_LEN - 1]; | |
976 | |
977 snprintf(buf, MSN_BUF_LEN, "REM %d BL %s\n", trId(md), who); | |
978 msn_write(md->fd, buf); | |
979 } | |
980 | |
981 static void msn_add_deny(struct gaim_connection *gc, char *who) | |
982 { | |
983 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
984 char buf[MSN_BUF_LEN - 1]; | |
985 | |
986 snprintf(buf, MSN_BUF_LEN, "ADD %d BL %s %s\n", trId(md), who, who); | |
987 msn_write(md->fd, buf); | |
988 } | |
989 | |
1630 | 990 static GList *msn_away_states() |
991 { | |
992 GList *m = NULL; | |
993 | |
994 m = g_list_append(m, "Available"); | |
995 m = g_list_append(m, "Away From Computer"); | |
996 m = g_list_append(m, "Be Right Back"); | |
997 m = g_list_append(m, "Busy"); | |
998 m = g_list_append(m, "On The Phone"); | |
999 m = g_list_append(m, "Out To Lunch"); | |
1000 | |
1001 return m; | |
1002 } | |
1003 | |
1600 | 1004 static void msn_set_away(struct gaim_connection *gc, char *state, char *msg) |
1005 { | |
1006 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
1007 char buf[MSN_BUF_LEN - 1]; | |
1008 | |
1630 | 1009 |
1010 gc->away = NULL; | |
1011 | |
1600 | 1012 if (msg) |
1630 | 1013 { |
1014 gc->away = ""; | |
1600 | 1015 snprintf(buf, MSN_BUF_LEN, "CHG %d AWY\n", trId(md)); |
1630 | 1016 } |
1017 | |
1018 else if (state) | |
1019 { | |
1020 char away[4]; | |
1021 | |
1022 gc->away = ""; | |
1023 | |
1024 if (!strcmp(state, "Available")) | |
1025 sprintf(away, "NLN"); | |
1026 else if (!strcmp(state, "Away From Computer")) | |
1027 sprintf(away, "AWY"); | |
1028 else if (!strcmp(state, "Be Right Back")) | |
1029 sprintf(away, "BRB"); | |
1030 else if (!strcmp(state, "Busy")) | |
1031 sprintf(away, "BSY"); | |
1032 else if (!strcmp(state, "On The Phone")) | |
1033 sprintf(away, "PHN"); | |
1034 else if (!strcmp(state, "Out To Lunch")) | |
1035 sprintf(away, "LUN"); | |
1036 else | |
1037 sprintf(away, "NLN"); | |
1038 | |
1039 snprintf(buf, MSN_BUF_LEN, "CHG %d %s\n", trId(md), away); | |
1040 } | |
1600 | 1041 else if (gc->is_idle) |
1042 snprintf(buf, MSN_BUF_LEN, "CHG %d IDL\n", trId(md)); | |
1043 else | |
1044 snprintf(buf, MSN_BUF_LEN, "CHG %d NLN\n", trId(md)); | |
1045 | |
1046 msn_write(md->fd, buf); | |
1047 } | |
1048 | |
1049 | |
1050 static void msn_set_idle(struct gaim_connection *gc, int idle) | |
1051 { | |
1052 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
1053 char buf[MSN_BUF_LEN - 1]; | |
1054 | |
1055 if (idle) | |
1056 snprintf(buf, MSN_BUF_LEN, "CHG %d IDL\n", trId(md)); | |
1057 else | |
1058 snprintf(buf, MSN_BUF_LEN, "CHG %d NLN\n", trId(md)); | |
1059 | |
1060 msn_write(md->fd, buf); | |
1061 } | |
1062 | |
1063 static void msn_close(struct gaim_connection *gc) | |
1064 { | |
1065 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
1066 char buf[MSN_BUF_LEN - 1]; | |
1067 struct msn_conn *mc = NULL; | |
1068 | |
1069 while (msn_connections) | |
1070 { | |
1071 mc = (struct msn_conn *)msn_connections->data; | |
1072 | |
1073 free_msn_conn(mc); | |
1074 } | |
1075 | |
1076 if (md->fd) | |
1077 { | |
1078 snprintf(buf, MSN_BUF_LEN, "OUT\n"); | |
1079 msn_write(md->fd, buf); | |
1080 close(md->fd); | |
1081 } | |
1082 | |
1083 if (gc->inpa) | |
1084 gdk_input_remove(gc->inpa); | |
1085 | |
1086 if (md->friendly) | |
1087 free(md->friendly); | |
1088 | |
1089 g_free(gc->proto_data); | |
1090 } | |
1091 | |
1639 | 1092 static char *msn_get_away_text(int s) |
1093 { | |
1094 switch (s) | |
1095 { | |
1096 case MSN_BUSY : | |
1097 return "Busy"; | |
1098 case MSN_BRB : | |
1099 return "Be right back"; | |
1100 case MSN_AWAY : | |
1101 return "Away from the computer"; | |
1102 case MSN_PHONE : | |
1103 return "On the phone"; | |
1104 case MSN_LUNCH : | |
1105 return "Out to lunch"; | |
1640 | 1106 case MSN_IDLE : |
1107 return "Idle"; | |
1639 | 1108 default: |
1109 return NULL; | |
1110 } | |
1111 } | |
1112 | |
1113 static void msn_buddy_menu(GtkWidget *menu, struct gaim_connection *gc, char *who) | |
1114 { | |
1115 struct buddy *b = find_buddy(gc, who); | |
1116 char buf[MSN_BUF_LEN]; | |
1117 GtkWidget *button; | |
1118 | |
1119 if (!(b->uc >> 5)) | |
1120 return; | |
1121 | |
1122 g_snprintf(buf, MSN_BUF_LEN, "Status: %s", msn_get_away_text(b->uc >> 5)); | |
1123 | |
1124 button = gtk_menu_item_new_with_label(buf); | |
1125 gtk_menu_append(GTK_MENU(menu), button); | |
1126 gtk_widget_show(button); | |
1127 } | |
1128 | |
1717 | 1129 void msn_newmail_dialog(const char *text) |
1130 { | |
1131 GtkWidget *window; | |
1132 GtkWidget *vbox; | |
1133 GtkWidget *label; | |
1134 GtkWidget *hbox; | |
1135 GtkWidget *button; | |
1136 | |
1137 window = gtk_window_new(GTK_WINDOW_DIALOG); | |
1138 gtk_window_set_wmclass(GTK_WINDOW(window), "prompt", "Gaim"); | |
1139 gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, TRUE); | |
1140 gtk_window_set_title(GTK_WINDOW(window), _("Gaim-MSN: New Mail")); | |
1141 gtk_widget_realize(window); | |
1142 aol_icon(window->window); | |
1143 | |
1144 vbox = gtk_vbox_new(FALSE, 5); | |
1145 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); | |
1146 gtk_container_add(GTK_CONTAINER(window), vbox); | |
1147 | |
1148 label = gtk_label_new(text); | |
1149 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); | |
1150 | |
1151 hbox = gtk_hbox_new(FALSE, 5); | |
1152 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
1153 | |
1154 button = picture_button(window, _("OK"), ok_xpm); | |
1155 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
1156 gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(msn_des_win), window); | |
1157 | |
1158 gtk_widget_show_all(window); | |
1159 } | |
1160 | |
1161 void msn_des_win(GtkWidget *a, GtkWidget *b) | |
1162 { | |
1163 gtk_widget_destroy(b); | |
1164 } | |
1165 | |
1166 static void mod_opt(GtkWidget *b, struct mod_usr_opt *m) | |
1167 { | |
1168 if (m->user) { | |
1169 if (m->user->proto_opt[m->opt][0] == '1') | |
1170 m->user->proto_opt[m->opt][0] = '\0'; | |
1171 else | |
1172 strcpy(m->user->proto_opt[m->opt],"1"); | |
1173 } | |
1174 } | |
1175 | |
1176 static void free_muo(GtkWidget *b, struct mod_usr_opt *m) | |
1177 { | |
1178 g_free(m); | |
1179 } | |
1180 | |
1181 static GtkWidget *msn_protoopt_button(const char *text, struct aim_user *u, int option, GtkWidget *box) | |
1182 { | |
1183 GtkWidget *button; | |
1184 struct mod_usr_opt *muo = g_new0(struct mod_usr_opt, 1); | |
1185 button = gtk_check_button_new_with_label(text); | |
1186 if (u) { | |
1187 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (u->proto_opt[option][0] == '1')); | |
1188 } | |
1189 gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0); | |
1190 muo->user = u; | |
1191 muo->opt = option; | |
1192 gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(mod_opt), muo); | |
1193 gtk_signal_connect(GTK_OBJECT(button), "destroy", GTK_SIGNAL_FUNC(free_muo), muo); | |
1194 gtk_widget_show(button); | |
1195 return button; | |
1196 } | |
1197 | |
1198 static void msn_user_opts(GtkWidget *book, struct aim_user *user) { | |
1199 GtkWidget *vbox; | |
1200 GtkWidget *button; | |
1201 | |
1202 vbox = gtk_vbox_new(FALSE, 5); | |
1203 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); | |
1204 gtk_notebook_append_page(GTK_NOTEBOOK(book), vbox, | |
1205 gtk_label_new("MSN Options")); | |
1206 gtk_widget_show(vbox); | |
1207 button = msn_protoopt_button("Notify me of new HotMail",user,USEROPT_HOTMAIL,vbox); | |
1208 } | |
1209 | |
1210 /* | |
1211 Process messages from Hotmail service. right now we just check for new | |
1212 mail notifications, if the user has checking enabled. | |
1213 */ | |
1214 | |
1215 static void process_hotmail_msg(struct gaim_connection *gc, gchar *msgdata) | |
1216 { | |
1217 gchar *mailnotice; | |
1218 char *mailfrom,*mailsubj,*mailct,*mailp; | |
1219 | |
1220 if (gc->user->proto_opt[USEROPT_HOTMAIL][0] != '1') return; | |
1221 mailfrom=NULL; mailsubj=NULL; mailct=NULL; mailp=NULL; | |
1222 mailct = strstr(msgdata,"Content-Type: "); | |
1223 mailp = strstr(mailct,";"); | |
1224 if (mailct != NULL && mailp != NULL && mailp > mailct && !strncmp(mailct,"Content-Type: text/x-msmsgsemailnotification",(mailp-mailct)-1)) | |
1225 { | |
1226 mailfrom=strstr(mailp,"From: "); | |
1227 mailsubj=strstr(mailp,"Subject: "); | |
1228 } | |
1229 | |
1230 if (mailfrom != NULL && mailsubj != NULL) | |
1231 { | |
1232 mailfrom += 6; | |
1233 mailp=strstr(mailfrom,"\r\n"); | |
1234 if (mailp==NULL) return; | |
1235 *mailp = 0; | |
1236 mailsubj += 9; | |
1237 mailp=strstr(mailsubj,"\r\n"); | |
1238 if (mailp==NULL) return; | |
1239 *mailp = 0; | |
1240 mailnotice = (gchar *)g_malloc(sizeof(gchar) *(strlen(mailfrom)+strlen(mailsubj)+128)); | |
1241 sprintf(mailnotice,"Mail from %s, re: %s",mailfrom,mailsubj); | |
1242 msn_newmail_dialog(mailnotice); | |
1243 g_free(mailnotice); | |
1244 } | |
1245 } | |
1246 | |
1572 | 1247 static char **msn_list_icon(int uc) |
1248 { | |
1249 if (uc == UC_UNAVAILABLE) | |
1250 return msn_away_xpm; | |
1251 else if (uc == UC_NORMAL) | |
1252 return msn_online_xpm; | |
1253 | |
1631 | 1254 return msn_away_xpm; |
1572 | 1255 } |
1256 | |
1259 | 1257 static struct prpl *my_protocol = NULL; |
1258 | |
1282 | 1259 void msn_init(struct prpl *ret) |
1260 { | |
1259 | 1261 ret->protocol = PROTO_MSN; |
1262 ret->name = msn_name; | |
1572 | 1263 ret->list_icon = msn_list_icon; |
1639 | 1264 ret->buddy_menu = msn_buddy_menu; |
1717 | 1265 ret->user_opts = msn_user_opts; |
1259 | 1266 ret->login = msn_login; |
1600 | 1267 ret->close = msn_close; |
1584 | 1268 ret->send_im = msn_send_im; |
1259 | 1269 ret->set_info = NULL; |
1270 ret->get_info = NULL; | |
1630 | 1271 ret->away_states = msn_away_states; |
1600 | 1272 ret->set_away = msn_set_away; |
1259 | 1273 ret->get_away_msg = NULL; |
1274 ret->set_dir = NULL; | |
1275 ret->get_dir = NULL; | |
1276 ret->dir_search = NULL; | |
1600 | 1277 ret->set_idle = msn_set_idle; |
1259 | 1278 ret->change_passwd = NULL; |
1598 | 1279 ret->add_buddy = msn_add_buddy; |
1259 | 1280 ret->add_buddies = NULL; |
1598 | 1281 ret->remove_buddy = msn_remove_buddy; |
1282 ret->add_permit = msn_add_permit; | |
1283 ret->rem_permit = msn_rem_permit; | |
1284 ret->add_deny = msn_add_deny; | |
1285 ret->rem_deny = msn_rem_deny; | |
1259 | 1286 ret->warn = NULL; |
1287 ret->accept_chat = NULL; | |
1288 ret->join_chat = NULL; | |
1289 ret->chat_invite = NULL; | |
1290 ret->chat_leave = NULL; | |
1291 ret->chat_whisper = NULL; | |
1292 ret->chat_send = NULL; | |
1293 ret->keepalive = NULL; | |
1294 | |
1295 my_protocol = ret; | |
1296 } | |
1297 | |
1282 | 1298 char *gaim_plugin_init(GModule * handle) |
1299 { | |
1443
336fc98b7f90
[gaim-migrate @ 1453]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1327
diff
changeset
|
1300 load_protocol(msn_init, sizeof(struct prpl)); |
1259 | 1301 return NULL; |
1302 } | |
1303 | |
1282 | 1304 void gaim_plugin_remove() |
1305 { | |
1259 | 1306 struct prpl *p = find_prpl(PROTO_MSN); |
1307 if (p == my_protocol) | |
1308 unload_protocol(p); | |
1309 } |