comparison plugins/yay/libyahoo.c @ 1054:0b0b4cb53c17

[gaim-migrate @ 1064] yahoo prpl committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Fri, 03 Nov 2000 10:03:53 +0000
parents
children 4416ead31db7
comparison
equal deleted inserted replaced
1053:864f4aae0b60 1054:0b0b4cb53c17
1 /*
2 Yahoo Pager Client Library
3
4 This code is based on code by Douglas Winslow. The original info from
5 his code is listed below. This code has taken his code and has been
6 altered to my naming and coding conventions and has been made more
7 usable as a library of routines.
8
9 -- Nathan Neulinger <nneul@umr.edu>
10 */
11
12 /*
13 Yahoo Pager Client Emulator Pro - yppro.c
14 A basic reference implementation
15 Douglas Winslow <douglas@min.net>
16 Tue Sep 1 02:28:21 EDT 1998
17 Version 2, Revision 2
18 Known to compile on Linux 2.0, FreeBSD 2.2, and BSDi 3.0.
19 hi to aap bdc drw jfn jrc mm mcd [cejn]b #cz and rootshell
20
21 Finally!
22 Yahoo finally patched their server-side, and things will be getting
23 back to "normal". I will continue to maintain this code as long as
24 there is interest for it. Since Yahoo will be discontinuing YPNS1.1
25 login support shortly, I've upgraded this client to do YPNS1.2. You
26 *must* have a password to pass authentication to the pager server.
27 This authentication is done by a weird HTTP cookie method.
28
29 This code is distributed under the GNU General Public License (GPL)
30 */
31
32 #include "config.h"
33 #include <stdio.h>
34 #include <netdb.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #if defined(WITH_GTK)
40 #include <gtk/gtk.h>
41 #endif
42 #include <unistd.h>
43 #if defined(HAVE_STRINGS_H)
44 #include <strings.h>
45 #endif
46 #if defined(HAVE_STRING_H)
47 #include <string.h>
48 #endif
49 #include <ctype.h>
50 #include "libyahoo.h"
51 #ifdef HAVE_DMALLOC
52 #include "dmalloc.h"
53 #else
54 #include <stdlib.h>
55 #endif
56
57 #include "memtok.h"
58
59 /* allow libyahoo to be used without gtkyahoo's debug support */
60 #ifdef ENABLE_LIBYAHOO_DEBUG
61 #include "libyahoo-debug.h"
62 #else
63 static void yahoo_dbg_Print(char *tmp, ...)
64 {
65 }
66
67 #define yahoo_dbg_NullCheck(x) ((x)?(x):("[NULL]"))
68 #endif
69
70 /* remap functions to gtk versions */
71 #if defined(WITH_GTK)
72 #define malloc g_malloc
73 #define free g_free
74 #define calloc(x,y) g_malloc0((x)*(y))
75 #endif
76
77 #if (!defined(TRUE) || !defined(FALSE))
78 # define TRUE 1
79 # define FALSE 0
80 #endif
81
82 /* Define a quick shortcut function to free a pointer and set it to null */
83 #define FREE(x) if (x) { free(x); x=NULL; }
84
85 #if defined(WITH_SOCKS4)
86 void SOCKSinit(char *argv0);
87 #endif
88
89 /* pager server host */
90 #define YAHOO_PAGER_HOST "cs.yahoo.com"
91 #define YAHOO_PAGER_PORT 5050
92 /* pager server host for http connections */
93 #define YAHOO_PAGER_HTTP_HOST "http.pager.yahoo.com"
94 #define YAHOO_PAGER_HTTP_PORT 80
95 /* authentication/login host */
96 #define YAHOO_AUTH_HOST "msg.edit.yahoo.com"
97 #define YAHOO_AUTH_PORT 80
98 /* buddy/identity/config host */
99 #define YAHOO_DATA_HOST YAHOO_AUTH_HOST
100 #define YAHOO_DATA_PORT 80
101 /* Address book host */
102 #define YAHOO_ADDRESS_HOST "uk.address.yahoo.com"
103 #define YAHOO_ADDRESS_PORT 80
104
105 /* User agent to use for HTTP connections */
106 /* It needs to have Mozilla/4 in it, otherwise it fails */
107 #ifndef VERSION
108 #define VERSION "1.0"
109 #endif
110 #define YAHOO_USER_AGENT "Mozilla/4.6 (libyahoo/" VERSION ")"
111
112 #define YAHOO_PROTOCOL_HEADER "YPNS2.0"
113
114 /*
115 * Routines and data private to this library, should not be directly
116 * accessed outside of these routines.
117 */
118
119 /* Service code labels for debugging output */
120 static struct yahoo_idlabel yahoo_service_codes[] = {
121 {YAHOO_SERVICE_LOGON, "Pager Logon"},
122 {YAHOO_SERVICE_LOGOFF, "Pager Logoff"},
123 {YAHOO_SERVICE_ISAWAY, "Is Away"},
124 {YAHOO_SERVICE_ISBACK, "Is Back"},
125 {YAHOO_SERVICE_IDLE, "Idle"},
126 {YAHOO_SERVICE_MESSAGE, "Message"},
127 {YAHOO_SERVICE_IDACT, "Activate Identity"},
128 {YAHOO_SERVICE_IDDEACT, "Deactivate Identity"},
129 {YAHOO_SERVICE_MAILSTAT, "Mail Status"},
130 {YAHOO_SERVICE_USERSTAT, "User Status"},
131 {YAHOO_SERVICE_NEWMAIL, "New Mail"},
132 {YAHOO_SERVICE_CHATINVITE, "Chat Invitation"},
133 {YAHOO_SERVICE_CALENDAR, "Calendar Reminder"},
134 {YAHOO_SERVICE_NEWPERSONALMAIL, "New Personals Mail"},
135 {YAHOO_SERVICE_NEWCONTACT, "New Friend"},
136 {YAHOO_SERVICE_GROUPRENAME, "Group Renamed"},
137 {YAHOO_SERVICE_ADDIDENT, "Add Identity"},
138 {YAHOO_SERVICE_ADDIGNORE, "Add Ignore"},
139 {YAHOO_SERVICE_PING, "Ping"},
140 {YAHOO_SERVICE_SYSMESSAGE, "System Message"},
141 {YAHOO_SERVICE_CONFINVITE, "Conference Invitation"},
142 {YAHOO_SERVICE_CONFLOGON, "Conference Logon"},
143 {YAHOO_SERVICE_CONFDECLINE, "Conference Decline"},
144 {YAHOO_SERVICE_CONFLOGOFF, "Conference Logoff"},
145 {YAHOO_SERVICE_CONFMSG, "Conference Message"},
146 {YAHOO_SERVICE_CONFADDINVITE, "Conference Additional Invitation"},
147 {YAHOO_SERVICE_CHATLOGON, "Chat Logon"},
148 {YAHOO_SERVICE_CHATLOGOFF, "Chat Logoff"},
149 {YAHOO_SERVICE_CHATMSG, "Chat Message"},
150 {YAHOO_SERVICE_GAMELOGON, "Game Logon"},
151 {YAHOO_SERVICE_GAMELOGOFF, "Game Logoff"},
152 {YAHOO_SERVICE_FILETRANSFER, "File Transfer"},
153 {YAHOO_SERVICE_PASSTHROUGH2, "Passthrough 2"},
154 {0, NULL}
155 };
156
157 /* Status codes */
158 static struct yahoo_idlabel yahoo_status_codes[] = {
159 {YAHOO_STATUS_AVAILABLE, "I'm Available"},
160 {YAHOO_STATUS_BRB, "Be Right Back"},
161 {YAHOO_STATUS_BUSY, "Busy"},
162 {YAHOO_STATUS_NOTATHOME, "Not at Home"},
163 {YAHOO_STATUS_NOTATDESK, "Not at my Desk"},
164 {YAHOO_STATUS_NOTINOFFICE, "Not in the Office"},
165 {YAHOO_STATUS_ONPHONE, "On the Phone"},
166 {YAHOO_STATUS_ONVACATION, "On Vacation"},
167 {YAHOO_STATUS_OUTTOLUNCH, "Out to Lunch"},
168 {YAHOO_STATUS_STEPPEDOUT, "Stepped Out"},
169 {YAHOO_STATUS_INVISIBLE, "Invisible"},
170 {YAHOO_STATUS_IDLE, "Idle"},
171 {YAHOO_STATUS_CUSTOM, "Custom Message"},
172 {0, NULL}
173 };
174
175 /* Status codes */
176 static struct yahoo_idlabel yahoo_status_append[] = {
177 {YAHOO_STATUS_AVAILABLE, "is now available"},
178 {YAHOO_STATUS_BRB, "will be right back"},
179 {YAHOO_STATUS_BUSY, "is now busy"},
180 {YAHOO_STATUS_NOTATHOME, "is not at home"},
181 {YAHOO_STATUS_NOTATDESK, "is not at their desk"},
182 {YAHOO_STATUS_NOTINOFFICE, "is not in the office"},
183 {YAHOO_STATUS_ONPHONE, "is on the phone"},
184 {YAHOO_STATUS_ONVACATION, "is on vacation"},
185 {YAHOO_STATUS_OUTTOLUNCH, "is out to lunch"},
186 {YAHOO_STATUS_STEPPEDOUT, "has stepped out"},
187 {YAHOO_STATUS_INVISIBLE, "is now invisible"},
188 {YAHOO_STATUS_IDLE, "is now idle"},
189 {YAHOO_STATUS_CUSTOM, ""},
190 {0, NULL}
191 };
192
193 /* Take a 4-byte character string in little-endian format and return
194 a unsigned integer */
195 unsigned int yahoo_makeint(unsigned char *data)
196 {
197 if (data)
198 {
199 return ((data[3] << 24) + (data[2] << 16) + (data[1] << 8) +
200 (data[0]));
201 }
202 return 0;
203 }
204
205 /* Take an integer and store it into a 4 character little-endian string */
206 static void yahoo_storeint(unsigned char *data, unsigned int val)
207 {
208 unsigned int tmp = val;
209 int i;
210
211 if (data)
212 {
213 for (i = 0; i < 4; i++)
214 {
215 data[i] = tmp % 256;
216 tmp >>= 8;
217 }
218 }
219 }
220
221 /*
222 converts a comma seperated list to an array of strings
223 used primarily in conference code
224
225 allocates a string in here -- caller needs to free it
226 */
227 char **yahoo_list2array(char *buff)
228 {
229 char **tmp_array = NULL;
230 char *array_elem = NULL;
231 char *tmp = NULL;
232
233 char *buffer = 0;
234 char *ptr_buffer = 0;
235
236 int sublen = 0;
237 int cnt = 0;
238 int nxtelem = 0;
239 unsigned int i = 0;
240 unsigned int len = 0;
241
242 if (0 == buff)
243 return 0;
244
245 buffer = strdup(buff); /* play with a copy */
246 ptr_buffer = buffer;
247
248 /* count the number of users (commas + 1) */
249 for (i = 0; i < strlen(buffer); i++)
250 {
251 if (buffer[i] == ',')
252 {
253 /*
254 if not looking at end of list
255 ( ignore extra pesky comma at end of list)
256 */
257 if (i != (strlen(buffer) - 1))
258 cnt++;
259 }
260 }
261
262 /* add one more name than comma .. */
263 cnt++;
264
265 /* allocate the array to hold the list of buddys */
266 /* null terminated array of pointers */
267 tmp_array = (char **) malloc(sizeof(char *) * (cnt + 1));
268
269 memset(tmp_array, 0, (sizeof(char *) * (cnt + 1)));
270
271 /* Parse through the list and get all the entries */
272 while ((ptr_buffer[sublen] != ',') && (ptr_buffer[sublen] != '\0'))
273 sublen++;
274 tmp = (char *) malloc(sizeof(char) * (sublen + 1));
275
276 memcpy(tmp, ptr_buffer, sublen);
277 tmp[sublen] = '\0';
278
279 if (ptr_buffer[sublen] != '\0')
280 ptr_buffer = &(ptr_buffer[sublen + 1]);
281 else
282 ptr_buffer = &(ptr_buffer[sublen]); /* stay at the null char */
283 sublen = 0;
284
285 while (tmp && (strcmp(tmp, "") != 0))
286 {
287 len = strlen(tmp);
288 array_elem = (char *) malloc(sizeof(char) * (len + 1));
289
290 strncpy(array_elem, tmp, (len + 1));
291 array_elem[len] = '\0';
292
293 tmp_array[nxtelem++] = array_elem;
294 array_elem = NULL;
295
296 FREE(tmp);
297
298 while ((ptr_buffer[sublen] != ',') && (ptr_buffer[sublen] != '\0'))
299 sublen++;
300 tmp = (char *) malloc(sizeof(char) * (sublen + 1));
301
302 memcpy(tmp, ptr_buffer, sublen);
303 tmp[sublen] = '\0';
304
305 if (ptr_buffer[sublen] != '\0')
306 ptr_buffer = &(ptr_buffer[sublen + 1]);
307 else
308 ptr_buffer = &(ptr_buffer[sublen]); /* stay at the null char */
309
310 sublen = 0;
311 }
312 tmp_array[nxtelem] = NULL;
313
314 FREE(tmp);
315 FREE(buffer);
316 return (tmp_array);
317
318 } /* yahoo_list2array() */
319
320 /*
321 Free's the memory associated with an array generated bu yahoo_list2array
322 */
323 void yahoo_arraykill(char **array)
324 {
325 int nxtelem = 0;
326
327 if (NULL == array)
328 return;
329
330 while (array[nxtelem] != NULL)
331 {
332 free(array[nxtelem++]);
333 }
334
335 free(array);
336 } /* yahoo_arraykill() */
337
338 /*
339 converts an array of strings to a comma seperated list
340 used primarily in conference code
341
342 allocates a string in here.. needs to be freed by caller program
343 */
344 char *yahoo_array2list(char **array)
345 {
346 char *list = NULL;
347 int nxtelem = 0;
348 int arraylength = 0;
349
350 if (NULL == array)
351 return NULL;
352
353 while (array[nxtelem] != NULL)
354 {
355 arraylength += strlen(array[nxtelem++]);
356 arraylength++; /* comma */
357 }
358
359 nxtelem = 0; /* reset array counter */
360
361 /* allocate at least one - for NULL list - and to
362 allow my strcat to write past the end for the
363 last comma which gets converted to NULL */
364 list = (char *) malloc(sizeof(char) * (arraylength + 1));
365
366 memset(list, 0, (arraylength + 1));
367
368 while (array[nxtelem] != NULL)
369 {
370 strcat(list, array[nxtelem++]);
371 strcat(list, ",");
372 }
373 /*
374 overwrite last ',' with a NULL
375 makes the string end with two null characters, but this way
376 handles empty lists gracefully
377 */
378 list[arraylength - 1] = '\0';
379
380 return (list);
381 } /* yahoo_array2list() */
382
383 /* Free a buddy list */
384 static void yahoo_free_buddies(struct yahoo_context *ctx)
385 {
386 int i;
387
388 if (!ctx->buddies)
389 {
390 return;
391 }
392
393 i = 0;
394 while (ctx->buddies[i])
395 {
396 FREE(ctx->buddies[i]->group);
397 FREE(ctx->buddies[i]->id);
398 i++;
399 }
400
401 FREE(ctx->buddies);
402 }
403
404 /* Free a identities list */
405 static void yahoo_free_identities(struct yahoo_context *ctx)
406 {
407 int i;
408
409 if (!ctx->identities)
410 {
411 return;
412 }
413
414 i = 0;
415 while (ctx->identities[i])
416 {
417 FREE(ctx->identities[i]);
418 i++;
419 }
420
421 FREE(ctx->identities);
422 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_free_identities: done\n");
423 }
424
425 #if 0 /* not used at the moment */
426 static void yahoo_hexdump(char *label, unsigned char *data, int datalen)
427 {
428 int i, j;
429 int val, skipped_last;
430 char current[100];
431 char last[100];
432 char tmp[15];
433 char outline[100];
434 static int last_datalen = 0;
435 static unsigned char *last_data = NULL;
436
437 if (last_data)
438 {
439 if (last_datalen == datalen && !memcmp(data, last_data, datalen))
440 {
441 printf("\n%s: <same as last dump>\n", label);
442 return;
443 }
444 FREE(last_data);
445 }
446
447 /* Copy the packet so we can don't duplicate it next time. */
448 last_datalen = datalen;
449 last_data = (unsigned char *) malloc(datalen);
450 memcpy(last_data, data, datalen);
451
452 /* Handle printing the full entry out */
453 printf("\n");
454 printf("%s:\n", label);
455
456 skipped_last = 0;
457 last[0] = 0;
458 for (j = 0; j * 16 < datalen; j++)
459 {
460 current[0] = 0;
461
462 /* Print out in hex */
463 for (i = j * 16; i < (j * 16 + 16); i++)
464 {
465 if (i < datalen)
466 {
467 val = data[i];
468 sprintf(tmp, "%.2X ", val);
469 }
470 else
471 {
472 sprintf(tmp, " ");
473 }
474 strcat(current, tmp);
475 }
476
477 /* Print out in ascii */
478 strcat(current, " ");
479 for (i = j * 16; i < (j * 16) + 16; i++)
480 {
481 if (i < datalen)
482 {
483 if (isprint(data[i]))
484 {
485 sprintf(tmp, "%c", data[i]);
486 }
487 else
488 {
489 sprintf(tmp, ".");
490 }
491 }
492 else
493 {
494 sprintf(tmp, " ");
495 }
496 strcat(current, tmp);
497 }
498
499 outline[0] = 0;
500 if (!strcmp(current, last))
501 {
502 if (!skipped_last)
503 {
504 strcpy(outline, " ....:\n");
505 }
506 skipped_last = 1;
507 }
508 else
509 {
510 sprintf(outline, " %.4d: %s\n", j * 16, current);
511 skipped_last = 0;
512 }
513 printf("%s", outline);
514 strcpy(last, current);
515 }
516
517 if (skipped_last)
518 {
519 printf("%s", outline);
520 }
521 printf("\n");
522 }
523 #endif
524
525 static int yahoo_socket_connect(struct yahoo_context *ctx, char *host,
526 int port)
527 {
528 struct sockaddr_in serv_addr;
529 struct hostent *server;
530 int servfd;
531 int res;
532
533 yahoo_dbg_Print("libyahoo",
534 "[libyahoo] yahoo_socket_connect - starting [%s:%d]\n", host, port);
535
536 if (!ctx || !host || !port)
537 {
538 yahoo_dbg_Print("libyahoo",
539 "[libyahoo] yahoo_socket_connect - nulls\n");
540 return 0;
541 }
542
543 server = gethostbyname(host);
544 if (!server)
545 {
546 printf("[libyahoo] failed to look up server (%s:%d)\n", host, port);
547 return (0);
548 }
549
550 servfd = socket(AF_INET, SOCK_STREAM, 0);
551
552 bzero(&serv_addr, sizeof(serv_addr));
553 serv_addr.sin_family = AF_INET;
554 bcopy(server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length);
555 serv_addr.sin_port = htons(port);
556
557 res = -1;
558 if (ctx->connect_mode == YAHOO_CONNECT_SOCKS4)
559 {
560 #if defined(WITH_SOCKS4)
561 res =
562 Rconnect(servfd, (struct sockaddr *) &serv_addr,
563 sizeof(serv_addr));
564 #endif
565 }
566 else if (ctx->connect_mode == YAHOO_CONNECT_SOCKS5)
567 {
568 #if defined(WITH_SOCKS5)
569 #endif
570 }
571 else if (ctx->connect_mode == YAHOO_CONNECT_NORMAL ||
572 ctx->connect_mode == YAHOO_CONNECT_HTTP ||
573 ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
574 {
575 res =
576 connect(servfd, (struct sockaddr *) &serv_addr,
577 sizeof(serv_addr));
578 }
579 else
580 {
581 printf("[libyahoo] unhandled connect mode (%d).\n",
582 ctx->connect_mode);
583 return (0);
584 }
585
586 if (res < 0)
587 {
588 close(servfd);
589 servfd = 0;
590 printf("[libyahoo] failed to connect to server (%s:%d)\n", host,
591 port);
592 return (0);
593 }
594
595 yahoo_dbg_Print("libyahoo",
596 "[libyahoo] yahoo_socket_connect - finished\n");
597 return servfd;
598 }
599
600 /* really ugly brute force approach - someone find a GPL'd/free
601 equivalent and replace this p.o.s. */
602 static char *yahoo_urlencode(char *data)
603 {
604 static char *tmp = NULL;
605 char buf[4];
606 int i, len;
607
608 len = 3 * strlen(data) + 1;
609
610 FREE(tmp);
611
612 if (!data)
613 {
614 return NULL;
615 }
616
617 /* change this at some point to re-use the buffer, no sense
618 allocating repeatedly */
619 tmp = (char *) malloc(len);
620 tmp[0] = 0;
621
622 for (i = 0; i < strlen(data); i++)
623 {
624 if (isdigit((int) (data[i])) ||
625 isalpha((int) data[i]) || data[i] == '_')
626 {
627 buf[0] = data[i];
628 buf[1] = 0;
629 strcat(tmp, buf);
630 }
631 else
632 {
633 sprintf(buf, "%%%.2X", data[i]);
634 strcat(tmp, buf);
635 }
636 }
637
638 return tmp;
639 }
640
641 static void yahoo_addtobuffer(struct yahoo_context *ctx, char *data,
642 int datalen)
643 {
644 //yahoo_hexdump("yahoo_addtobuffer", data, datalen);
645
646 /* Check buffer, increase size if necessary */
647 if (!ctx->io_buf
648 || ((ctx->io_buf_maxlen - ctx->io_buf_curlen) < (datalen + 100)))
649 {
650 char *new_io_buf;
651
652 if (datalen < 10240)
653 {
654 ctx->io_buf_maxlen += 10240;
655 }
656 else
657 {
658 ctx->io_buf_maxlen += datalen;
659 }
660 new_io_buf = (char *) malloc(ctx->io_buf_maxlen);
661
662 if (ctx->io_buf)
663 {
664 memcpy(new_io_buf, ctx->io_buf, ctx->io_buf_curlen);
665 FREE(ctx->io_buf);
666 }
667
668 ctx->io_buf = new_io_buf;
669 }
670
671 memcpy(ctx->io_buf + ctx->io_buf_curlen, data, datalen);
672 ctx->io_buf_curlen += datalen;
673 }
674
675 static int yahoo_tcp_readline(char *ptr, int maxlen, int fd)
676 {
677 int n, rc;
678 char c;
679
680 for (n = 1; n < maxlen; n++)
681 {
682 again:
683
684 if ((rc = read(fd, &c, 1)) == 1)
685 {
686 *ptr++ = c;
687 if (c == '\n')
688 break;
689 }
690 else if (rc == 0)
691 {
692 if (n == 1)
693 return (0); /* EOF, no data */
694 else
695 break; /* EOF, w/ data */
696 }
697 else
698 {
699 if (errno == EINTR)
700 goto again;
701 printf
702 ("Yahoo: Error reading from socket in yahoo_tcp_readline.\n");
703 exit(1);
704 }
705 }
706
707 *ptr = 0;
708 return (n);
709 }
710
711 /*
712 * Published library interfaces
713 */
714
715 /* Initialize interface to yahoo library, sortof like a class object
716 creation routine. */
717 struct yahoo_context *yahoo_init(char *user, char *password,
718 struct yahoo_options *options)
719 {
720 struct yahoo_context *tmp;
721
722 if (!user || !password)
723 {
724 return NULL;
725 }
726
727 /* Allocate a new context */
728 tmp = (struct yahoo_context *) calloc(1, sizeof(*tmp));
729
730 /* Fill in any available info */
731 tmp->user = strdup(user);
732 tmp->password = strdup(password);
733 if (options->proxy_host)
734 {
735 tmp->proxy_host = strdup(options->proxy_host);
736 }
737 tmp->proxy_port = options->proxy_port;
738 tmp->connect_mode = options->connect_mode;
739
740 #if defined(WITH_SOCKS4)
741 if (connect_mode == YAHOO_CONNECT_SOCKS4)
742 {
743 static int did_socks_init = 0;
744
745 if (did_socks_init == 0)
746 {
747 SOCKSinit("libyahoo");
748 did_socks_init = 1;
749 }
750 }
751 #endif
752
753 /* Fetch the cookies */
754 if (!yahoo_fetchcookies(tmp))
755 {
756 yahoo_free_context(tmp);
757 return NULL;
758 }
759
760 return tmp;
761 }
762
763 /* Free a yahoo context */
764 void yahoo_free_context(struct yahoo_context *ctx)
765 {
766 FREE(ctx->user);
767 FREE(ctx->password);
768 FREE(ctx->proxy_host);
769 FREE(ctx->io_buf);
770 FREE(ctx->cookie);
771 FREE(ctx->login_cookie);
772 FREE(ctx->login_id);
773
774 yahoo_free_buddies(ctx);
775 yahoo_free_identities(ctx);
776
777 FREE(ctx);
778 }
779
780 /* Turn a status code into it's corresponding string */
781 char *yahoo_get_status_string(int statuscode)
782 {
783 int i;
784
785 for (i = 0; yahoo_status_codes[i].label; i++)
786 {
787 if (yahoo_status_codes[i].id == statuscode)
788 {
789 return yahoo_status_codes[i].label;
790 }
791 }
792 return NULL;
793 }
794
795 /* Turn a status code into it's corresponding string */
796 char *yahoo_get_status_append(int statuscode)
797 {
798 int i;
799
800 for (i = 0; yahoo_status_append[i].label; i++)
801 {
802 if (yahoo_status_append[i].id == statuscode)
803 {
804 return yahoo_status_append[i].label;
805 }
806 }
807 return NULL;
808 }
809
810 /* Turn a service code into it's corresponding string */
811 char *yahoo_get_service_string(int servicecode)
812 {
813 int i;
814 char *name = "Unknown Service";
815 static char tmp[50];
816
817 for (i = 0; yahoo_service_codes[i].label; i++)
818 {
819 if (yahoo_service_codes[i].id == servicecode)
820 {
821 name = yahoo_service_codes[i].label;
822 break;
823 }
824 }
825
826 snprintf(tmp, 50, "(%d) %s", servicecode, name);
827 return tmp;
828 }
829
830 /* Return a malloc()'d copy of the users cookie */
831 int yahoo_fetchcookies(struct yahoo_context *ctx)
832 {
833 char buffer[5000];
834 int servfd;
835 int i;
836 int res;
837 char *tmpstr;
838
839 if (!ctx)
840 {
841 return 0;
842 }
843
844 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_fetchcookies: starting\n");
845
846 /* Check for cached cookie */
847 if (ctx->cookie)
848 {
849 FREE(ctx->cookie);
850 }
851 if (ctx->login_cookie)
852 {
853 FREE(ctx->login_cookie);
854 }
855
856 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
857 {
858 servfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
859 }
860 else
861 {
862 servfd = yahoo_socket_connect(ctx, YAHOO_AUTH_HOST, YAHOO_AUTH_PORT);
863 }
864 if (!servfd)
865 {
866 printf("[libyahoo] failed to connect to pager auth server.\n");
867 return (0);
868 }
869
870 strcpy(buffer, "GET ");
871 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
872 {
873 strcat(buffer, "http://" YAHOO_AUTH_HOST);
874 }
875 strcat(buffer, "/config/ncclogin?login=");
876 if (ctx->login_id)
877 {
878 strcat(buffer, yahoo_urlencode(ctx->login_id));
879 }
880 else
881 {
882 strcat(buffer, yahoo_urlencode(ctx->user));
883 }
884 strcat(buffer, "&passwd=");
885 strcat(buffer, yahoo_urlencode(ctx->password));
886 strcat(buffer, "&n=1 HTTP/1.0\r\n");
887 strcat(buffer, "User-Agent: " YAHOO_USER_AGENT "\r\n");
888 strcat(buffer, "Host: " YAHOO_AUTH_HOST "\r\n");
889 strcat(buffer, "\r\n");
890
891 write(servfd, buffer, strlen(buffer));
892
893 yahoo_dbg_Print("libyahoo",
894 "[libyahoo] yahoo_fetchcookies: writing buffer '%s'\n", buffer);
895
896 ctx->cookie = NULL;
897 while ((res = yahoo_tcp_readline(buffer, 5000, servfd)) > 0)
898 {
899 /* strip out any non-alphas */
900 for (i = 0; i < strlen(buffer); i++)
901 {
902 if (!isprint((int) buffer[i]))
903 {
904 buffer[i] = 0;
905 }
906 }
907
908 yahoo_dbg_Print("libyahoo",
909 "[libyahoo] yahoo_fetchcookies: read buffer '%s'\n", buffer);
910
911 if (!strcasecmp(buffer, "ERROR: Invalid NCC Login"))
912 {
913 yahoo_dbg_Print("libyahoo",
914 "[libyahoo] yahoo_fetchcookies: password was invalid\n");
915 return (0);
916 }
917
918 if (!strncasecmp(buffer, "Set-Cookie: Y=", 14))
919 {
920 FREE(ctx->cookie);
921 ctx->cookie = strdup(buffer + 12);
922
923 tmpstr = strchr(ctx->cookie, ';');
924 if (tmpstr)
925 {
926 *tmpstr = '\0';
927 }
928 }
929 }
930 yahoo_dbg_Print("libyahoo",
931 "[libyahoo] yahoo_fetchcookies: closing server connection\n");
932 close(servfd);
933 servfd = 0;
934 yahoo_dbg_Print("libyahoo",
935 "[libyahoo] yahoo_fetchcookies: closed server connection\n");
936
937 if (ctx->cookie)
938 {
939 tmpstr = strstr(ctx->cookie, "n=");
940 if (tmpstr)
941 {
942 ctx->login_cookie = strdup(tmpstr + 2);
943 }
944
945 tmpstr = strchr(ctx->login_cookie, '&');
946 if (tmpstr)
947 {
948 *tmpstr = '\0';
949 }
950 }
951
952 if (ctx->cookie)
953 yahoo_dbg_Print("libyahoo",
954 "[libyahoo] yahoo_fetchcookies: cookie (%s)\n", ctx->cookie);
955 if (ctx->login_cookie)
956 yahoo_dbg_Print("libyahoo",
957 "[libyahoo] yahoo_fetchcookies: login cookie (%s)\n",
958 ctx->login_cookie);
959
960 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_fetchcookies: done\n");
961
962 return 1;
963 }
964
965 /* Add a buddy to your buddy list */
966 int yahoo_add_buddy(struct yahoo_context *ctx, char *addid,
967 char *active_id, char *group, char *msg)
968 {
969 char buffer[5000];
970 int servfd;
971
972 if (!ctx)
973 {
974 return 0;
975 }
976
977 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
978 {
979 yahoo_dbg_Print("libyahoo",
980 "[libyahoo] yahoo_add_buddy - connecting via proxy\n");
981 servfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
982 }
983 else
984 {
985 yahoo_dbg_Print("libyahoo",
986 "[libyahoo] yahoo_add_buddy - connecting\n");
987 servfd = yahoo_socket_connect(ctx, YAHOO_DATA_HOST, YAHOO_DATA_PORT);
988 }
989 if (!servfd)
990 {
991 yahoo_dbg_Print("libyahoo",
992 "[libyahoo] yahoo_add_buddy: failed to connect\n");
993 return (0);
994 }
995
996 strcpy(buffer, "GET ");
997 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
998 {
999 strcat(buffer, "http://" YAHOO_DATA_HOST);
1000 }
1001 strcat(buffer, "/config/set_buddygrp?.bg=");
1002 strcat(buffer, yahoo_urlencode(group));
1003 strcat(buffer, "&.src=bl&.cmd=a&.bdl=");
1004 strcat(buffer, yahoo_urlencode(addid));
1005 strcat(buffer, "&.id=");
1006 strcat(buffer, yahoo_urlencode(active_id));
1007 strcat(buffer, "&.l=");
1008 strcat(buffer, yahoo_urlencode(ctx->user));
1009 strcat(buffer, "&.amsg=");
1010 strcat(buffer, yahoo_urlencode(msg));
1011 strcat(buffer, " HTTP/1.0\r\n");
1012
1013 strcat(buffer, "User-Agent: " YAHOO_USER_AGENT "\r\n");
1014 strcat(buffer, "Host: " YAHOO_DATA_HOST "\r\n");
1015 strcat(buffer, "Cookie: ");
1016 strcat(buffer, ctx->cookie);
1017 strcat(buffer, "\r\n");
1018 strcat(buffer, "\r\n");
1019
1020 write(servfd, buffer, strlen(buffer));
1021 while (yahoo_tcp_readline(buffer, 5000, servfd) > 0)
1022 {
1023 /* just dump the output, I don't care about errors at the moment */
1024 }
1025 close(servfd);
1026 servfd = 0;
1027
1028 /* indicate success for now with 0 */
1029 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_add_buddy: finished\n");
1030 return 0;
1031 }
1032
1033 /* Remove a buddy from your buddy list */
1034 int yahoo_remove_buddy(struct yahoo_context *ctx, char *addid,
1035 char *active_id, char *group, char *msg)
1036 {
1037 char buffer[5000];
1038 int servfd;
1039
1040 if (!ctx)
1041 {
1042 return 0;
1043 }
1044
1045 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
1046 {
1047 yahoo_dbg_Print("libyahoo",
1048 "[libyahoo] yahoo_add_buddy - connecting via proxy\n");
1049 servfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
1050 }
1051 else
1052 {
1053 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_add_buddy - connecting\n");
1054 servfd = yahoo_socket_connect(ctx, YAHOO_DATA_HOST, YAHOO_DATA_PORT);
1055 }
1056 if (!servfd)
1057 {
1058 yahoo_dbg_Print("libyahoo",
1059 "[libyahoo] yahoo_add_buddy: failed to connect\n");
1060 return (0);
1061 }
1062
1063 strcpy(buffer, "GET ");
1064 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
1065 {
1066 strcat(buffer, "http://" YAHOO_DATA_HOST);
1067 }
1068 strcat(buffer, "/config/set_buddygrp?.bg=");
1069 strcat(buffer, yahoo_urlencode(group));
1070 strcat(buffer, "&.src=bl&.cmd=d&.bdl=");
1071 strcat(buffer, yahoo_urlencode(addid));
1072 strcat(buffer, "&.id=");
1073 strcat(buffer, yahoo_urlencode(active_id));
1074 strcat(buffer, "&.l=");
1075 strcat(buffer, yahoo_urlencode(ctx->user));
1076 strcat(buffer, "&.amsg=");
1077 strcat(buffer, yahoo_urlencode(msg));
1078 strcat(buffer, " HTTP/1.0\r\n");
1079
1080 strcat(buffer, "User-Agent: " YAHOO_USER_AGENT "\r\n");
1081 strcat(buffer, "Host: " YAHOO_DATA_HOST "\r\n");
1082 strcat(buffer, "Cookie: ");
1083 strcat(buffer, ctx->cookie);
1084 strcat(buffer, "\r\n");
1085 strcat(buffer, "\r\n");
1086
1087 write(servfd, buffer, strlen(buffer));
1088 while (yahoo_tcp_readline(buffer, 5000, servfd) > 0)
1089 {
1090 /* just dump the output, I don't care about errors at the moment */
1091 }
1092 close(servfd);
1093 servfd = 0;
1094
1095 /* indicate success for now with 0 */
1096 return 0;
1097 }
1098
1099 /* Retrieve the configuration from the server */
1100 int yahoo_get_config(struct yahoo_context *ctx)
1101 {
1102 char buffer[5000];
1103 int i, j;
1104 int servfd;
1105 int commas;
1106 int in_section;
1107 struct yahoo_buddy **buddylist = NULL;
1108 int buddycnt = 0;
1109 int nextbuddy = 0;
1110
1111 /* Check for cached cookie */
1112 if (!ctx || !ctx->cookie)
1113 {
1114 return 0;
1115 }
1116
1117 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_get_config: starting\n");
1118
1119 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
1120 {
1121 servfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
1122 }
1123 else
1124 {
1125 servfd = yahoo_socket_connect(ctx, YAHOO_DATA_HOST, YAHOO_DATA_PORT);
1126 }
1127 if (!servfd)
1128 {
1129 yahoo_dbg_Print("libyahoo",
1130 "[libyahoo] yahoo_get_config: failed to connect\n");
1131 return (0);
1132 }
1133
1134 strcpy(buffer, "GET ");
1135 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
1136 {
1137 strcat(buffer, "http://" YAHOO_DATA_HOST);
1138 }
1139 strcat(buffer, "/config/get_buddylist?.src=bl HTTP/1.0\r\n");
1140 strcat(buffer, "Cookie: ");
1141 strcat(buffer, ctx->cookie);
1142 strcat(buffer, "\r\n");
1143 strcat(buffer, "\r\n");
1144
1145 write(servfd, buffer, strlen(buffer));
1146 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_get_config: sending '%s'\n",
1147 buffer);
1148
1149 in_section = 0;
1150 while (yahoo_tcp_readline(buffer, 5000, servfd) > 0)
1151 {
1152 /* strip out any non-alphas */
1153 for (i = 0; i < strlen(buffer); i++)
1154 {
1155 if (!isprint((int) buffer[i]))
1156 {
1157 for (j = i; j < strlen(buffer); j++)
1158 {
1159 buffer[j] = buffer[j + 1];
1160 }
1161 }
1162 }
1163
1164 yahoo_dbg_Print("libyahoo",
1165 "[libyahoo] yahoo_get_config: read '%s'\n", buffer);
1166
1167 if (!strcasecmp(buffer, "BEGIN IDENTITIES"))
1168 {
1169 in_section = 1;
1170 }
1171 else if (!strcasecmp(buffer, "END IDENTITIES"))
1172 {
1173 in_section = 0;
1174 }
1175 else if (!strcasecmp(buffer, "BEGIN BUDDYLIST"))
1176 {
1177 in_section = 2;
1178 }
1179 else if (!strcasecmp(buffer, "END BUDDYLIST"))
1180 {
1181 in_section = 0;
1182 }
1183 else if (in_section == 1)
1184 {
1185 char *tmp;
1186
1187 /* count the commas */
1188 commas = 0;
1189 for (i = 0; i < strlen(buffer); i++)
1190 {
1191 if (buffer[i] == ',')
1192 {
1193 commas++;
1194 }
1195 }
1196
1197 /* make sure we've gotten rid of any previous identities array */
1198 yahoo_free_identities(ctx);
1199
1200 /* allocate the array to hold the list of identities */
1201 ctx->identities = (char **) calloc(commas + 2, sizeof(char *));
1202
1203 /* Parse through the list and get all the entries */
1204 i = 0;
1205 tmp = strtok(buffer, ",");
1206 while (tmp)
1207 {
1208 yahoo_dbg_Print("libyahoo",
1209 "[libyahoo] yahoo_get_config: retrieved "
1210 "identity '%s'\n", tmp);
1211 ctx->identities[i++] = strdup(tmp);
1212 tmp = strtok(NULL, ",");
1213 }
1214 ctx->identities[i] = 0;
1215 }
1216 else if (in_section == 2)
1217 {
1218 char *group;
1219 char *tmp;
1220 struct yahoo_buddy **tmp_buddylist;
1221 struct yahoo_buddy *tmpbuddy;
1222 int tmp_buddycnt;
1223
1224 /* count the buddies on this line */
1225 tmp_buddycnt = buddycnt;
1226 for (i = 0; i < strlen(buffer); i++)
1227 {
1228 if (buffer[i] == ',')
1229 {
1230 buddycnt++;
1231 }
1232 }
1233 buddycnt++; /* always one more than comma count */
1234
1235 /* allocate the array to hold the list of buddy */
1236 tmp_buddylist = (struct yahoo_buddy **)
1237 malloc(sizeof(struct yahoo_buddy *) * (buddycnt + 1));
1238
1239 /* Free and copy the old one if necessary */
1240 if (buddylist)
1241 {
1242 memcpy(tmp_buddylist, buddylist,
1243
1244 (tmp_buddycnt + 1) * sizeof(struct yahoo_buddy *));
1245
1246 FREE(buddylist);
1247 }
1248 buddylist = tmp_buddylist;
1249
1250 /* Parse through the list and get all the entries */
1251 tmp = strtok(buffer, ",:");
1252 group = NULL;
1253 while (tmp)
1254 {
1255 if (tmp == buffer) /* group name */
1256 {
1257 group = tmp;
1258 }
1259 else
1260 {
1261 tmpbuddy = (struct yahoo_buddy *)
1262
1263 malloc(sizeof(struct yahoo_buddy));
1264
1265 tmpbuddy->id = strdup(tmp);
1266 tmpbuddy->group = strdup(group);
1267 yahoo_dbg_Print("libyahoo",
1268 "[libyahoo] yahoo_get_config: retrieved buddy '%s:%s'\n",
1269 group, tmp);
1270 buddylist[nextbuddy++] = tmpbuddy;
1271 }
1272 tmp = strtok(NULL, ",");
1273 }
1274 buddylist[nextbuddy] = 0;
1275 }
1276 else if (!strncasecmp(buffer, "Mail=", strlen("Mail=")))
1277 {
1278 ctx->mail = atoi(buffer + strlen("Mail="));
1279 yahoo_dbg_Print("libyahoo",
1280 "[libyahoo] yahoo_get_config: retrieved mail flag '%d'\n",
1281 ctx->mail);
1282 }
1283 else if (!strncasecmp(buffer, "Login=", strlen("Login=")))
1284 {
1285 FREE(ctx->login_id);
1286 ctx->login_id = strdup(buffer + strlen("Login="));
1287 yahoo_dbg_Print("libyahoo",
1288 "[libyahoo] yahoo_get_config: retrieved login id '%s'\n",
1289 ctx->login_id);
1290 }
1291 }
1292 close(servfd);
1293 servfd = 0;
1294
1295 yahoo_free_buddies(ctx);
1296 ctx->buddies = buddylist;
1297
1298 /* fill in a bogus login_in, just in case */
1299 if (!ctx->login_id)
1300 {
1301 ctx->login_id = strdup(ctx->user);
1302 }
1303
1304 /* refetch the cookie if the login_id is different so that
1305 it will have the correct info in it */
1306 if (strcmp(ctx->login_id, ctx->user))
1307 {
1308 yahoo_dbg_Print("libyahoo",
1309 "[libyahoo] yahoo_get_config - refetching cookies\n");
1310 yahoo_fetchcookies(ctx);
1311 }
1312
1313 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_get_config - finished\n");
1314
1315 return 1;
1316 }
1317
1318 /* Log in, optionally activating other secondary identities */
1319 int yahoo_cmd_logon(struct yahoo_context *ctx, unsigned int initial_status)
1320 {
1321 char login_string[5000]; /* need to change to malloc ASAP */
1322 char *tmpid;
1323 char **identities = ctx->identities;
1324 int i;
1325
1326 if (!ctx || !ctx->login_cookie)
1327 {
1328 yahoo_dbg_Print("libyahoo",
1329 "[libyahoo] yahoo_cmd_logon: logon called without "
1330 "context and/or cookie.\n");
1331 exit(1);
1332 }
1333
1334 strcpy(login_string, ctx->login_cookie);
1335 /* testing with new logon code */
1336 // strcpy(login_string, "$1$_2S43d5f$XXXXXXXXWtRKNclLWyy8C.");
1337
1338 login_string[strlen(login_string) + 1] = 0;
1339 login_string[strlen(login_string)] = 1; /* control-A */
1340
1341 strcat(login_string, ctx->user);
1342
1343 /* Send all identities */
1344 if (identities)
1345 {
1346 i = 0;
1347 tmpid = identities[i];
1348 while (tmpid)
1349 {
1350 if (strcasecmp(tmpid, ctx->user))
1351 {
1352 strcat(login_string, ",");
1353 strcat(login_string, tmpid);
1354 }
1355 tmpid = identities[i++];
1356 }
1357 }
1358
1359 yahoo_sendcmd(ctx, YAHOO_SERVICE_LOGON, ctx->user, login_string,
1360 initial_status);
1361
1362 /* something that the windows one sends, not sure what it is */
1363 #if 0
1364 login_string[0] = 0;
1365 strcat(login_string, "C=0\002");
1366 strcat(login_string, "F=0,P=0,H=0,S=0,W=0,O=0\002");
1367 strcat(login_string, "M=0,P=0,C=0,S=0");
1368 yahoo_sendcmd(ctx, YAHOO_SERVICE_PASSTHROUGH2, ctx->user, login_string,
1369 0);
1370 #endif
1371
1372 return 0;
1373 }
1374
1375 int yahoo_connect(struct yahoo_context *ctx)
1376 {
1377 int res;
1378
1379 res = 0;
1380 ctx->sockfd = 0;
1381
1382 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_connect - starting\n");
1383
1384 switch (ctx->connect_mode)
1385 {
1386 case YAHOO_CONNECT_SOCKS4:
1387 case YAHOO_CONNECT_SOCKS5:
1388 case YAHOO_CONNECT_NORMAL:
1389 yahoo_dbg_Print("libyahoo",
1390 "[libyahoo] yahoo_connect - establishing socket connection\n");
1391 ctx->sockfd =
1392 yahoo_socket_connect(ctx, YAHOO_PAGER_HOST, YAHOO_PAGER_PORT);
1393 if (!ctx->sockfd)
1394 {
1395 printf("[libyahoo] couldn't connect to pager host\n");
1396 return (0);
1397 }
1398 break;
1399
1400 case YAHOO_CONNECT_HTTP:
1401 case YAHOO_CONNECT_HTTPPROXY:
1402 yahoo_dbg_Print("libyahoo",
1403 "[libyahoo] yahoo_connect - no connect for HTTP\n");
1404 /* no pager connection will be established for this */
1405 break;
1406
1407 default:
1408 printf("[libyahoo] unhandled connect mode (%d)\n",
1409 ctx->connect_mode);
1410 }
1411
1412 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_connect - finished\n");
1413 return (1);
1414 }
1415
1416 /* Send a packet to the server via http connection method */
1417 /* at moment only handles regular http connection, once I have that
1418 working, this code needs to also do http proxy connections as well */
1419 int yahoo_sendcmd_http(struct yahoo_context *ctx, struct yahoo_rawpacket *pkt)
1420 {
1421 int sockfd;
1422 char buffer[5000];
1423 char tmpbuf[1000];
1424 int size;
1425 int res;
1426
1427 if (!ctx || !pkt)
1428 {
1429 return (0);
1430 }
1431
1432 size = YAHOO_PACKET_HEADER_SIZE + strlen(pkt->content) + 1;
1433
1434 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
1435 {
1436 sockfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
1437 }
1438 else
1439 {
1440 sockfd = yahoo_socket_connect(ctx, YAHOO_PAGER_HTTP_HOST,
1441 YAHOO_PAGER_HTTP_PORT);
1442 }
1443 if (!sockfd)
1444 {
1445 printf("[libyahoo] failed to connect to pager http server.\n");
1446 return (0);
1447 }
1448
1449 strcpy(buffer, "POST ");
1450 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
1451 {
1452 strcat(buffer, "http://" YAHOO_PAGER_HTTP_HOST);
1453 }
1454 strcat(buffer, "/notify HTTP/1.0\r\n");
1455
1456 strcat(buffer, "User-Agent: " YAHOO_USER_AGENT "\r\n");
1457 strcat(buffer, "Host: " YAHOO_PAGER_HTTP_HOST "\r\n");
1458 snprintf(tmpbuf, 1000, "Content-Length: %d\r\n", size);
1459 strcat(buffer, tmpbuf);
1460
1461 strcat(buffer, "Pragma: No-Cache\r\n");
1462
1463 strcat(buffer, "Cookie: ");
1464 strcat(buffer, ctx->cookie);
1465 strcat(buffer, "\r\n");
1466 strcat(buffer, "\r\n");
1467
1468 write(sockfd, buffer, strlen(buffer));
1469 write(sockfd, pkt, size);
1470 write(sockfd, "\r\n", 2);
1471
1472 /* now we need to read the results */
1473 /* I'm taking the cheat approach and just dumping them onto the
1474 buffer, headers and all, the _skip_to_YHOO_ code will handle it
1475 for now */
1476
1477 while ((res = read(sockfd, buffer, 5000)) > 0)
1478 {
1479 if (res == -1)
1480 {
1481 printf("[libyahoo] Error reading data from server.\n");
1482 exit(1);
1483 }
1484 yahoo_addtobuffer(ctx, buffer, res);
1485 }
1486 close(sockfd);
1487 sockfd = 0;
1488
1489 return (0);
1490 }
1491
1492 /* Send a packet to the server, called by all routines that want to issue
1493 a command. */
1494 int yahoo_sendcmd(struct yahoo_context *ctx, int service, char *active_nick,
1495 char *content, unsigned int msgtype)
1496 {
1497 int size;
1498 struct yahoo_rawpacket *pkt;
1499 int maxcontentsize;
1500
1501 /* why the )&*@#$( did they hardwire the packet size that gets sent
1502 when the size of the packet is included in what is sent, bizarre */
1503 size = 4 * 256 + YAHOO_PACKET_HEADER_SIZE;
1504 pkt = (struct yahoo_rawpacket *) calloc(1, size);
1505
1506 /* figure out max content length, including trailing null */
1507 maxcontentsize = size - sizeof(struct yahoo_rawpacket);
1508
1509 /* Build the packet */
1510 strcpy(pkt->version, YAHOO_PROTOCOL_HEADER);
1511 yahoo_storeint(pkt->len, size);
1512 yahoo_storeint(pkt->service, service);
1513
1514 /* not sure if this is valid with YPNS1.4 or if it needs 2.0 */
1515 yahoo_storeint(pkt->msgtype, msgtype);
1516
1517 /* Not sure, but might as well send for regular connections as well. */
1518 yahoo_storeint(pkt->magic_id, ctx->magic_id);
1519 strcpy(pkt->nick1, ctx->login_id);
1520 strcpy(pkt->nick2, active_nick);
1521 strncpy(pkt->content, content, maxcontentsize);
1522
1523 // yahoo_hexdump("send_cmd", (char *) pkt, size);
1524
1525 switch (ctx->connect_mode)
1526 {
1527 case YAHOO_CONNECT_SOCKS4:
1528 case YAHOO_CONNECT_SOCKS5:
1529 case YAHOO_CONNECT_NORMAL:
1530 write(ctx->sockfd, pkt, size);
1531 break;
1532 case YAHOO_CONNECT_HTTP:
1533 case YAHOO_CONNECT_HTTPPROXY:
1534 yahoo_sendcmd_http(ctx, pkt);
1535 break;
1536 }
1537
1538 FREE(pkt);
1539 return (0);
1540 }
1541
1542 int yahoo_cmd_ping(struct yahoo_context *ctx)
1543 {
1544 yahoo_sendcmd(ctx, YAHOO_SERVICE_PING, ctx->user, "", 0);
1545 return (0);
1546 }
1547
1548 int yahoo_cmd_idle(struct yahoo_context *ctx)
1549 {
1550 yahoo_sendcmd(ctx, YAHOO_SERVICE_IDLE, ctx->user, "", 0);
1551 return (0);
1552 }
1553
1554 int yahoo_cmd_sendfile(struct yahoo_context *ctx, char *active_user,
1555 char *touser, char *msg, char *filename)
1556 {
1557 yahoo_dbg_Print("libyahoo", "yahoo_cmd_sendfile not implemented yet!");
1558 return (0);
1559 }
1560
1561 int yahoo_cmd_msg(struct yahoo_context *ctx, char *active_user,
1562 char *touser, char *msg)
1563 {
1564 char *content;
1565
1566 content = (char *) malloc(strlen(touser) + strlen(msg) + 5);
1567
1568 if (strlen(touser))
1569 {
1570 sprintf(content, "%s,%s", touser, msg);
1571 yahoo_sendcmd(ctx, YAHOO_SERVICE_MESSAGE, active_user, content, 0);
1572 }
1573
1574 FREE(content);
1575 return (0);
1576 }
1577
1578 int yahoo_cmd_msg_offline(struct yahoo_context *ctx, char *active_user,
1579 char *touser, char *msg)
1580 {
1581 char *content;
1582
1583 content = (char *) malloc(strlen(touser) + strlen(msg) + 5);
1584
1585 if (strlen(touser))
1586 {
1587 sprintf(content, "%s,%s", touser, msg);
1588 yahoo_sendcmd(ctx, YAHOO_SERVICE_MESSAGE, active_user, content,
1589 YAHOO_MSGTYPE_KNOWN_USER);
1590 }
1591
1592 FREE(content);
1593 return (0);
1594 }
1595
1596 /* appended the " " so that won't trigger yahoo bug - hack for the moment */
1597 int yahoo_cmd_set_away_mode(struct yahoo_context *ctx, int status, char *msg)
1598 {
1599 char statusstring[500];
1600
1601 yahoo_dbg_Print("libyahoo",
1602 "[libyahoo] yahoo_cmd_set_away_mode: set status (%d), msg(%s)\n",
1603 status, yahoo_dbg_NullCheck(msg));
1604
1605 if (status == YAHOO_STATUS_CUSTOM)
1606 {
1607 if (msg && msg[0] != 0)
1608 {
1609 snprintf(statusstring, 500, "%d%c%s", status, 1, msg);
1610 }
1611 else
1612 {
1613 snprintf(statusstring, 500, "%d%c---", status, 1);
1614 }
1615 }
1616 else
1617 {
1618 snprintf(statusstring, 500, "%d", status);
1619 }
1620 yahoo_sendcmd(ctx, YAHOO_SERVICE_ISAWAY, ctx->user, statusstring, 0);
1621
1622 return 0;
1623 }
1624
1625 int yahoo_cmd_set_back_mode(struct yahoo_context *ctx, int status, char *msg)
1626 {
1627 char statusstring[500];
1628
1629 yahoo_dbg_Print("libyahoo",
1630 "[libyahoo] yahoo_cmd_set_back_mode: set status (%d), msg(%s)\n",
1631 status, yahoo_dbg_NullCheck(msg));
1632
1633 snprintf(statusstring, 500, "%d%c%s ", status, 1, msg ? msg : "");
1634 yahoo_sendcmd(ctx, YAHOO_SERVICE_ISBACK, ctx->user, statusstring, 0);
1635
1636 return 0;
1637 }
1638
1639 int yahoo_cmd_activate_id(struct yahoo_context *ctx, char *newid)
1640 {
1641 if (strlen(newid))
1642 {
1643 yahoo_sendcmd(ctx, YAHOO_SERVICE_IDACT, newid, newid, 0);
1644 }
1645 return (0);
1646 }
1647
1648 int yahoo_cmd_user_status(struct yahoo_context *ctx)
1649 {
1650 yahoo_sendcmd(ctx, YAHOO_SERVICE_USERSTAT, ctx->user, "", 0);
1651 return (0);
1652 }
1653
1654 int yahoo_cmd_logoff(struct yahoo_context *ctx)
1655 {
1656 yahoo_sendcmd(ctx, YAHOO_SERVICE_LOGOFF, ctx->user, ctx->user, 0);
1657 return (0);
1658 }
1659
1660 /*
1661
1662 yahoo_cmd_start_conf()
1663
1664 Starts a conference. (You create the conference)
1665
1666 Arguments:
1667 char *conf_id == The conference id -- usually of the form name-number,
1668 though it doesn't seem to matter much. ex: jaylubo-123
1669 You create this id to start the conference, but pass it
1670 along after that.
1671 char **userlist == Users to invite. Null terminated array of strings.
1672 car *msg == Invitiation message.
1673 int type == 0 - normal, 1 - voice (not supported yet)
1674
1675 Packet format:
1676 id^invited-users^msg^0or1
1677 */
1678 int yahoo_cmd_start_conf(struct yahoo_context *ctx, char *conf_id,
1679 char **userlist, char *msg, int type)
1680 {
1681 char ctrlb = 2;
1682 char *content;
1683 char *new_userlist = yahoo_array2list(userlist);
1684 int cont_len = 0;
1685
1686 #ifdef ENABLE_LIBYAHOO_DEBUG
1687 char *unraw_msg = NULL;
1688 #endif /* def ENABLE_LIBYAHOO_DEBUG */
1689
1690 int size = strlen(conf_id) + strlen(msg) + 8 + strlen(new_userlist);
1691
1692 content = (char *) malloc(size);
1693 memset(content, 0, size);
1694
1695 cont_len = snprintf(content,
1696 size - 1,
1697 "%s%c%s%c%s%c%d",
1698 conf_id, ctrlb, new_userlist, ctrlb, msg, ctrlb, type);
1699
1700 #ifdef ENABLE_LIBYAHOO_DEBUG
1701 unraw_msg = yahoo_unraw_buffer(content, cont_len);
1702 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_cmd_start_conf: %s\n",
1703 unraw_msg);
1704 free(unraw_msg);
1705 #endif /* def ENABLE_LIBYAHOO_DEBUG */
1706 yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFINVITE, ctx->user, content, 0);
1707
1708 FREE(new_userlist);
1709 FREE(content);
1710 return (0);
1711 }
1712
1713 /*
1714 yahoo_cmd_conf_logon()
1715
1716 Reply to a conference invitation, logs you into conference.
1717
1718 Arguments:
1719 char *conf_id == The conference id -- usually of the form name-number,
1720 though it doesn't seem to matter much. ex: jaylubo-123
1721 This comes from the invitiation.
1722 char *host == The person that sent you the invitation.
1723 char **userlist == Everyone else invited. This comes from the invitiation.
1724 Null terminated array of strings.
1725
1726 Packet format:
1727 id^all-invited-users-and-host
1728
1729 */
1730 int yahoo_cmd_conf_logon(struct yahoo_context *ctx, char *conf_id,
1731 char *host, char **userlist)
1732 {
1733 char ctrlb = 2;
1734 char *content;
1735 char *new_userlist = yahoo_array2list(userlist);
1736 int cont_len = 0;
1737
1738 #ifdef ENABLE_LIBYAHOO_DEBUG
1739 char *unraw_msg = NULL;
1740 #endif /* def ENABLE_LIBYAHOO_DEBUG */
1741
1742 int size = strlen(conf_id) + strlen(host) + 8 + strlen(new_userlist);
1743
1744 content = (char *) malloc(size);
1745 memset(content, 0, size);
1746
1747 cont_len =
1748 sprintf(content, "%s%c%s,%s", conf_id, ctrlb, host, new_userlist);
1749
1750 #ifdef ENABLE_LIBYAHOO_DEBUG
1751 unraw_msg = yahoo_unraw_buffer(content, cont_len);
1752 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_cmd_conf_logon: %s\n",
1753 unraw_msg);
1754 free(unraw_msg);
1755 #endif /* def ENABLE_LIBYAHOO_DEBUG */
1756 yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFLOGON, ctx->user, content, 0);
1757
1758 FREE(new_userlist);
1759 FREE(content);
1760 return (0);
1761 }
1762
1763 /*
1764
1765 yahoo_cmd_decline_conf()
1766
1767 Reply to a conference invitation, decline offer.
1768
1769 Arguments:
1770 char *conf_id == The conference id -- usually of the form name-number,
1771 though it doesn't seem to matter much. ex: jaylubo-123
1772 This comes from the invitiation.
1773 char *host == The person that sent you the invitation.
1774 char **userlist == Everyone else invited. This comes from the invitiation.
1775 Null terminated array of strings.
1776 (Null if replying to a conference additional invite )
1777 char *msg == Reason for declining.
1778
1779 Packet format:
1780 id^all-invited-users-and-host^msg
1781
1782 */
1783 int yahoo_cmd_decline_conf(struct yahoo_context *ctx, char *conf_id,
1784 char *host, char **userlist, char *msg)
1785 {
1786 char ctrlb = 2;
1787 char *content;
1788 char *new_userlist = yahoo_array2list(userlist);
1789
1790 int size =
1791
1792 strlen(conf_id) + strlen(host) + strlen(msg) + 8 +
1793 strlen(new_userlist);
1794
1795 content = (char *) malloc(size);
1796 memset(content, 0, size);
1797
1798 sprintf(content, "%s%c%s,%s%c%s", conf_id, ctrlb, host, new_userlist,
1799 ctrlb, msg);
1800
1801 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_cmd_decline_conf: %s\n",
1802 content);
1803 yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFDECLINE, ctx->user, content, 0);
1804
1805 FREE(new_userlist);
1806 FREE(content);
1807 return (0);
1808 }
1809
1810 /*
1811
1812 yahoo_cmd_conf_logoff()
1813
1814 Logoff of a conference.
1815
1816 Arguments:
1817 char *conf_id == The conference id -- usually of the form name-number,
1818 though it doesn't seem to matter much. ex: jaylubo-123
1819 This comes from the invitiation.
1820 char **userlist == Everyone in conference.
1821 Null terminated array of strings.
1822
1823 Packet format:
1824 id^all-invited-users
1825
1826 */
1827
1828 int yahoo_cmd_conf_logoff(struct yahoo_context *ctx, char *conf_id,
1829 char **userlist)
1830 {
1831 char ctrlb = 2;
1832 char *content;
1833 int cont_len = 0;
1834
1835 #ifdef ENABLE_LIBYAHOO_DEBUG
1836 char *unraw_msg = NULL;
1837 #endif /* def ENABLE_LIBYAHOO_DEBUG */
1838 char *new_userlist = yahoo_array2list(userlist);
1839
1840 int size = strlen(conf_id) + strlen(new_userlist) + 8;
1841
1842 content = (char *) malloc(size);
1843 memset(content, 0, size);
1844
1845 cont_len =
1846 snprintf(content, size, "%s%c%s", conf_id, ctrlb, new_userlist);
1847 #ifdef ENABLE_LIBYAHOO_DEBUG
1848 unraw_msg = yahoo_unraw_buffer(content, cont_len);
1849 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_cmd_conf_logoff: %s\n",
1850 unraw_msg);
1851 free(unraw_msg);
1852 #endif /* def ENABLE_LIBYAHOO_DEBUG */
1853 yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFLOGOFF, ctx->user, content, 0);
1854
1855 FREE(new_userlist);
1856 FREE(content);
1857 return (0);
1858 }
1859
1860 /*
1861
1862 yahoo_cmd_conf_invite()
1863
1864 Invite another user to an already running conference.
1865
1866 Arguments:
1867 char *conf_id == The conference id -- usually of the form name-number,
1868 though it doesn't seem to matter much. ex: jaylubo-123
1869 This comes from the invitiation.
1870 char *invited_user == The person being invited to conference.
1871 char **userlist == Everyone else in conference.
1872 Null terminated array of strings.
1873 char *msg == Invitation message.
1874
1875 Packet format:
1876 id^invited-user^who-else-in-conf^who-else-in-conf^msg^0
1877
1878 */
1879
1880 int yahoo_cmd_conf_invite(struct yahoo_context *ctx, char *conf_id,
1881 char **userlist, char *invited_user, char *msg)
1882 {
1883 char ctrlb = 2;
1884 char *content;
1885 char *new_userlist = yahoo_array2list(userlist);
1886
1887 int size = strlen(conf_id) + strlen(invited_user)
1888 + (2 * strlen(new_userlist)) + strlen(msg) + 7;
1889
1890 content = (char *) malloc(size);
1891 memset(content, 0, size);
1892
1893 sprintf(content, "%s%c%s%c%s%c%s%c%s%c0", conf_id, ctrlb,
1894 invited_user, ctrlb, new_userlist, ctrlb,
1895 new_userlist, ctrlb, msg, ctrlb);
1896 yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_cmd_conf_invite: %s\n",
1897 content);
1898 yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFADDINVITE, ctx->user, content, 0);
1899
1900 FREE(new_userlist);
1901 FREE(content);
1902 return (0);
1903 }
1904
1905 /*
1906
1907 yahoo_cmd_conf_msg()
1908
1909 Send a message to everyone in conference.
1910
1911 Arguments:
1912 char *conf_id == The conference id -- usually of the form name-number,
1913 though it doesn't seem to matter much. ex: jaylubo-123
1914 This comes from the invitiation.
1915 char **userlist == Everyone in conference.
1916 Null terminated array of strings.
1917 char *msg == Message to send.
1918
1919 Packet format:
1920 id^all-invited-users^msg
1921
1922 */
1923 int yahoo_cmd_conf_msg(struct yahoo_context *ctx, char *conf_id,
1924 char **userlist, char *msg)
1925 {
1926 char ctrlb = 2;
1927 char *content;
1928 int cont_len = 0;
1929
1930 #ifdef ENABLE_LIBYAHOO_DEBUG
1931 char *unraw_msg = NULL;
1932 #endif /* def ENABLE_LIBYAHOO_DEBUG */
1933 char *new_userlist = yahoo_array2list(userlist);
1934
1935 int size = strlen(conf_id) + strlen(new_userlist) + strlen(msg) + 8;
1936
1937 content = (char *) malloc(size);
1938 memset(content, 0, size);
1939
1940 cont_len =
1941 snprintf(content, size, "%s%c%s%c%s", conf_id, ctrlb, new_userlist,
1942 ctrlb, msg);
1943 #ifdef ENABLE_LIBYAHOO_DEBUG
1944 unraw_msg = yahoo_unraw_buffer(content, cont_len);
1945 yahoo_dbg_Print("libyahoo", "yahoo_cmd_conf_msg: %s\n", unraw_msg);
1946 free(unraw_msg);
1947 #endif /* def ENABLE_LIBYAHOO_DEBUG */
1948 yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFMSG, ctx->user, content, 0);
1949
1950 FREE(new_userlist);
1951 FREE(content);
1952 return (0);
1953 }
1954
1955 /*
1956 * Free the rawpacket structure - primarily a placeholder
1957 * since all static elements at the moment
1958 */
1959 void yahoo_free_rawpacket(struct yahoo_rawpacket *pkt)
1960 {
1961 FREE(pkt);
1962 }
1963
1964 /*
1965 * Free entire packet structure including string elements
1966 */
1967 void yahoo_free_packet(struct yahoo_packet *pkt)
1968 {
1969 int i;
1970
1971 if (pkt)
1972 {
1973 FREE(pkt->real_id);
1974 FREE(pkt->active_id);
1975 FREE(pkt->conf_id);
1976 FREE(pkt->conf_host);
1977 FREE(pkt->conf_user);
1978 FREE(pkt->conf_msg);
1979 FREE(pkt->cal_url);
1980 FREE(pkt->cal_timestamp);
1981 FREE(pkt->cal_title);
1982 FREE(pkt->cal_description);
1983 FREE(pkt->chat_invite_content);
1984 FREE(pkt->msg_id);
1985 FREE(pkt->msg_timestamp);
1986 FREE(pkt->msg);
1987 FREE(pkt->file_from);
1988 FREE(pkt->file_flag);
1989 FREE(pkt->file_url);
1990 FREE(pkt->file_description);
1991 FREE(pkt->group_old);
1992 FREE(pkt->group_new);
1993 if (pkt->idstatus)
1994 {
1995 for (i = 0; i < pkt->idstatus_count; i++)
1996 {
1997 yahoo_free_idstatus(pkt->idstatus[i]);
1998 }
1999 free(pkt->idstatus);
2000 }
2001 free(pkt);
2002 }
2003 }
2004
2005 void yahoo_free_idstatus(struct yahoo_idstatus *idstatus)
2006 {
2007 if (!idstatus)
2008 {
2009 return;
2010 }
2011
2012 FREE(idstatus->id);
2013 FREE(idstatus->connection_id);
2014 FREE(idstatus->status_msg);
2015 FREE(idstatus);
2016 }
2017
2018 struct yahoo_packet *yahoo_parsepacket(struct yahoo_context *ctx,
2019 struct yahoo_rawpacket *inpkt)
2020 {
2021 struct yahoo_packet *pkt;
2022
2023 /* If no valid inpkt passed, return */
2024 if (!inpkt)
2025 {
2026 return NULL;
2027 }
2028
2029 /* Allocate the packet structure, zeroed out */
2030 pkt = (struct yahoo_packet *) calloc(sizeof(*pkt), 1);
2031
2032 /* Pull out the standard data */
2033 pkt->service = yahoo_makeint(inpkt->service);
2034 pkt->connection_id = yahoo_makeint(inpkt->connection_id);
2035 pkt->real_id = strdup(inpkt->nick1);
2036 pkt->active_id = strdup(inpkt->nick2);
2037
2038 pkt->magic_id = yahoo_makeint(inpkt->magic_id);
2039 pkt->unknown1 = yahoo_makeint(inpkt->unknown1);
2040 pkt->msgtype = yahoo_makeint(inpkt->msgtype);
2041
2042 /* doing this seems like a cleaner approach, but am not sure if it is
2043 a valid one */
2044 if (pkt->magic_id != 0)
2045 {
2046 ctx->magic_id = pkt->magic_id;
2047 }
2048 if (pkt->connection_id != 0)
2049 {
2050 ctx->connection_id = pkt->connection_id;
2051 }
2052
2053 /* Call a particular parse routine to pull out the content */
2054 switch (pkt->service)
2055 {
2056 case YAHOO_SERVICE_LOGON:
2057 case YAHOO_SERVICE_LOGOFF:
2058 case YAHOO_SERVICE_ISAWAY:
2059 case YAHOO_SERVICE_ISBACK:
2060 case YAHOO_SERVICE_USERSTAT:
2061 case YAHOO_SERVICE_CHATLOGON:
2062 case YAHOO_SERVICE_CHATLOGOFF:
2063 case YAHOO_SERVICE_GAMELOGON:
2064 case YAHOO_SERVICE_GAMELOGOFF:
2065 yahoo_parsepacket_status(ctx, pkt, inpkt);
2066 break;
2067 case YAHOO_SERVICE_IDACT:
2068 case YAHOO_SERVICE_IDDEACT:
2069 /* nothing needs done, only has main fields */
2070 break;
2071 case YAHOO_SERVICE_MESSAGE:
2072 case YAHOO_SERVICE_SYSMESSAGE:
2073 case YAHOO_SERVICE_CHATMSG:
2074 yahoo_parsepacket_message(ctx, pkt, inpkt);
2075 break;
2076 case YAHOO_SERVICE_NEWMAIL:
2077 case YAHOO_SERVICE_NEWPERSONALMAIL:
2078 yahoo_parsepacket_newmail(ctx, pkt, inpkt);
2079 break;
2080 case YAHOO_SERVICE_CALENDAR:
2081 yahoo_parsepacket_calendar(ctx, pkt, inpkt);
2082 break;
2083 case YAHOO_SERVICE_CHATINVITE:
2084 yahoo_parsepacket_chatinvite(ctx, pkt, inpkt);
2085 break;
2086 case YAHOO_SERVICE_NEWCONTACT:
2087 yahoo_parsepacket_newcontact(ctx, pkt, inpkt);
2088 break;
2089 case YAHOO_SERVICE_GROUPRENAME:
2090 yahoo_parsepacket_grouprename(ctx, pkt, inpkt);
2091 break;
2092 case YAHOO_SERVICE_CONFINVITE:
2093 yahoo_parsepacket_conference_invite(ctx, pkt, inpkt);
2094 break;
2095 case YAHOO_SERVICE_CONFLOGON:
2096 case YAHOO_SERVICE_CONFLOGOFF:
2097 yahoo_parsepacket_conference_user(ctx, pkt, inpkt);
2098 break;
2099 case YAHOO_SERVICE_CONFDECLINE:
2100 yahoo_parsepacket_conference_decline(ctx, pkt, inpkt);
2101 break;
2102 case YAHOO_SERVICE_CONFADDINVITE:
2103 yahoo_parsepacket_conference_addinvite(ctx, pkt, inpkt);
2104 break;
2105 case YAHOO_SERVICE_CONFMSG:
2106 yahoo_parsepacket_conference_msg(ctx, pkt, inpkt);
2107 break;
2108 case YAHOO_SERVICE_PING:
2109 yahoo_parsepacket_ping(ctx, pkt, inpkt);
2110 break;
2111 case YAHOO_SERVICE_FILETRANSFER:
2112 yahoo_parsepacket_filetransfer(ctx, pkt, inpkt);
2113 break;
2114 default:
2115 yahoo_dbg_Print("libyahoo",
2116 "yahoo_parsepacket: can't parse packet type (%d)\n",
2117 pkt->service);
2118 break;
2119 }
2120
2121 return pkt;
2122 }
2123
2124 int yahoo_parsepacket_ping(struct yahoo_context *ctx,
2125 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2126 {
2127 char *content;
2128
2129 /* Make working copy of content */
2130 content = inpkt->content;
2131
2132 pkt->msg = NULL;
2133 if (content)
2134 {
2135 pkt->msg = strdup(content);
2136 }
2137
2138 return 0;
2139 }
2140
2141 int yahoo_parsepacket_newmail(struct yahoo_context *ctx,
2142 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2143 {
2144 char *content;
2145 int len;
2146
2147 /* Make working copy of content */
2148 content = inpkt->content;
2149 len = strlen(content);
2150
2151 if (pkt->service == YAHOO_SERVICE_NEWMAIL)
2152 {
2153 pkt->mail_status = 0;
2154 if (len > 0)
2155 {
2156 pkt->mail_status = atoi(content);
2157 }
2158 }
2159 else if (pkt->service == YAHOO_SERVICE_NEWPERSONALMAIL)
2160 {
2161 pkt->mail_status = 0;
2162 if (len > 0)
2163 {
2164 pkt->mail_status = atoi(content);
2165 }
2166 }
2167
2168 return 0;
2169 }
2170
2171 int yahoo_parsepacket_grouprename(struct yahoo_context *ctx,
2172 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2173 {
2174 char *content;
2175 char *tmp, delim[5];
2176
2177 /* Make working copy of content */
2178 content = strdup(inpkt->content);
2179
2180 /* init elements to all null */
2181 pkt->group_old = NULL;
2182 pkt->group_new = NULL;
2183
2184 tmp = NULL;
2185 delim[0] = 1; /* control-a */
2186 delim[1] = 0;
2187
2188 if (content)
2189 {
2190 tmp = strtok(content, delim);
2191 }
2192
2193 if (tmp) /* got the conference id */
2194 {
2195 pkt->group_old = strdup(tmp);
2196 tmp = strtok(NULL, delim);
2197 }
2198
2199 if (tmp) /* conference host */
2200 {
2201 pkt->group_new = strdup(tmp);
2202 tmp = strtok(NULL, delim);
2203 }
2204
2205 FREE(content);
2206 return (0);
2207 }
2208
2209 /*
2210
2211 yahoo_parsepacket_conference_invite()
2212
2213 Packet format:
2214 id^host^invited-users^msg^0or1
2215
2216 Parses Arguments:
2217 char *conf_id == The conference id -- usually of the form name-number,
2218 though it doesn't seem to matter much. ex: jaylubo-123
2219 char *conf_host == The person inviting you to conference.
2220 char **userlist == Everyone else invited to conference.
2221 Null terminated array of strings.
2222 char *msg == Invitation message.
2223 int conf_type == Type of conference ( 0 = text, 1 = voice )
2224
2225 */
2226 int yahoo_parsepacket_conference_invite(struct yahoo_context *ctx,
2227 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2228 {
2229 char *content;
2230 char *tmp = 0;
2231 size_t found = 0, len = yahoo_makeint(inpkt->len);
2232
2233 /* Make working copy of content */
2234 content = memdup(inpkt->content, len);
2235
2236 /* init elements to all null */
2237 pkt->conf_id = NULL;
2238 pkt->conf_host = NULL;
2239 pkt->conf_user = pkt->active_id;
2240 pkt->conf_userlist = NULL;
2241 pkt->conf_inviter = NULL;
2242 pkt->conf_msg = NULL;
2243
2244 if (content)
2245 {
2246 tmp = memtok(content, len, "\002", 2, &found);
2247 }
2248
2249 if (tmp) /* got the conference id */
2250 {
2251 pkt->conf_id = memdupasstr(tmp, found);
2252 tmp = memtok(0, 0, "\002", 2, &found);
2253 }
2254
2255 if (tmp) /* conference host */
2256 {
2257 pkt->conf_host = memdupasstr(tmp, found);
2258 tmp = memtok(0, 0, "\002", 2, &found);
2259 }
2260
2261 if (tmp) /* who else is invited */
2262 {
2263 char *userlist = memdupasstr(tmp, found);
2264
2265 pkt->conf_userlist = yahoo_list2array(userlist);
2266 FREE(userlist);
2267 tmp = memtok(0, 0, "\002", 2, &found);
2268 }
2269
2270 if (tmp) /* msg */
2271 {
2272 pkt->conf_msg = memdupasstr(tmp, found);
2273 tmp = memtok(0, 0, "\002", 2, &found);
2274 }
2275
2276 if (tmp) /* 0 == text chat 1 == voice chat */
2277 {
2278 char *conftype = memdupasstr(tmp, found);
2279
2280 if (0 != conftype)
2281 pkt->conf_type = atoi(conftype);
2282 FREE(conftype);
2283 tmp = memtok(0, 0, "\002", 2, &found);
2284 }
2285
2286 FREE(content);
2287 return 0;
2288 }
2289
2290 /*
2291
2292 yahoo_parsepacket_conference_decline()
2293
2294 Packet format:
2295 id^user-who-declined^msg
2296
2297 Parses Arguments:
2298 char *conf_id == The conference id -- usually of the form name-number,
2299 though it doesn't seem to matter much. ex: jaylubo-123
2300 char *conf_user == User who declined.
2301 char *msg == Reason for declining.
2302
2303 */
2304 int yahoo_parsepacket_conference_decline(struct yahoo_context *ctx,
2305 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2306 {
2307 char *content;
2308 char *tmp, delim[2];
2309
2310 /* Make working copy of content */
2311 content = strdup(inpkt->content);
2312
2313 /* init elements to all null */
2314 pkt->conf_id = NULL;
2315 pkt->conf_host = NULL;
2316 pkt->conf_user = NULL;
2317 pkt->conf_userlist = NULL;
2318 pkt->conf_inviter = NULL;
2319 pkt->conf_msg = NULL;
2320
2321 tmp = NULL;
2322 delim[0] = 2; /* control-b */
2323 delim[1] = 0;
2324
2325 if (content)
2326 {
2327 tmp = strtok(content, delim);
2328 }
2329
2330 if (tmp) /* got the conference id */
2331 {
2332 pkt->conf_id = strdup(tmp);
2333 tmp = strtok(NULL, delim);
2334 }
2335 if (tmp) /* got the user who declined */
2336 {
2337 pkt->conf_user = strdup(tmp);
2338 tmp = strtok(NULL, delim);
2339 }
2340 if (tmp) /* msg */
2341 {
2342 pkt->conf_msg = strdup(tmp);
2343 tmp = strtok(NULL, delim);
2344 }
2345
2346 FREE(content);
2347 return 0;
2348
2349 }
2350
2351 /*
2352
2353 yahoo_parsepacket_conference_addinvite()
2354
2355 Packet format:
2356 Msgtype == 1
2357 id^inviter^who-else-invited^who-else-in-conf^msg^0or1
2358 Msgtype == 11
2359 id^inviter^invited-user
2360
2361 Parses Arguments:
2362 char *conf_id == The conference id -- usually of the form name-number,
2363 though it doesn't seem to matter much. ex: jaylubo-123
2364 char *conf_inviter == The person inviting you to conference.
2365 char **userlist == Everyone else in conference.
2366 Null terminated array of strings.
2367 char *msg == Invitation message.
2368 int conf_type == Type of conference ( 0 = text, 1 = voice )
2369
2370 char *conf_user == User invited to conference (msgtype == 11)
2371 */
2372 int yahoo_parsepacket_conference_addinvite(struct yahoo_context *ctx,
2373 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2374 {
2375 char *content = 0, *tmp = 0;
2376 size_t found = 0, len = yahoo_makeint(inpkt->len);
2377
2378 /* Make working copy of content */
2379 content = memdup(inpkt->content, len);
2380
2381 /* init elements to all null */
2382 pkt->conf_id = NULL;
2383 pkt->conf_host = NULL;
2384 pkt->conf_user = NULL;
2385 pkt->conf_userlist = NULL;
2386 pkt->conf_inviter = NULL;
2387 pkt->conf_msg = NULL;
2388
2389 if (pkt->msgtype == 1)
2390 {
2391 if (content)
2392 {
2393 tmp = memtok(content, len, "\002", 2, &found);
2394 }
2395
2396 if (tmp) /* got the conference id */
2397 {
2398 pkt->conf_id = memdupasstr(tmp, found);
2399 tmp = memtok(0, 0, "\002", 2, &found);
2400 }
2401 if (tmp) /* got the inviter */
2402 {
2403 pkt->conf_inviter = memdupasstr(tmp, found);
2404 tmp = memtok(0, 0, "\002", 2, &found);
2405 }
2406 if (tmp) /* got who-else-invited */
2407 {
2408 /* don't use this field, its the same as the next one
2409 so I'm going to use the second field */
2410 /* pkt->conf_userlist = yahoo_list2array(tmp); */
2411 tmp = memtok(0, 0, "\002", 2, &found);
2412 }
2413 if (tmp) /* got the people in conference
2414 not counting the inviter */
2415 {
2416 char *userlist = memdupasstr(tmp, found);
2417
2418 pkt->conf_userlist = yahoo_list2array(userlist);
2419 FREE(userlist);
2420 tmp = memtok(0, 0, "\002", 2, &found);
2421 }
2422 if (tmp) /* got the message */
2423 {
2424 pkt->conf_msg = memdupasstr(tmp, found);
2425 tmp = memtok(0, 0, "\002", 2, &found);
2426 }
2427 if (tmp) /* 0 at the end */
2428 {
2429 char *conftype = memdupasstr(tmp, found);
2430
2431 if (0 != conftype)
2432 pkt->conf_type = atoi(conftype);
2433 FREE(conftype);
2434 /* tmp = memtok (0, 0, "\002", 2, &found); */
2435 }
2436 }
2437 else
2438 /* msgid == 11 (someone else is being invited) */
2439 {
2440 if (content)
2441 {
2442 tmp = memtok(content, len, "\002", 2, &found);
2443 }
2444
2445 if (tmp) /* got the conference id */
2446 {
2447 pkt->conf_id = memdupasstr(tmp, found);
2448 tmp = memtok(0, 0, "\002", 2, &found);
2449 }
2450
2451 if (tmp) /* got the inviter */
2452 {
2453 pkt->conf_inviter = memdupasstr(tmp, found);
2454 tmp = memtok(0, 0, "\002", 2, &found);
2455 }
2456
2457 if (tmp) /* got the invited-user */
2458 {
2459 pkt->conf_user = memdupasstr(tmp, found);
2460 /* tmp = memtok (0, 0, "\002", 2, &found); */
2461 }
2462 }
2463
2464 FREE(content);
2465 return 0;
2466 }
2467
2468 /*
2469
2470 yahoo_parsepacket_conference_msg()
2471
2472 Packet format:
2473 id^who-from^msg
2474
2475 Parses Arguments:
2476 char *conf_id == The conference id -- usually of the form name-number,
2477 though it doesn't seem to matter much. ex: jaylubo-123
2478 char *conf_user == User who sent message.
2479 char *msg == Message.
2480
2481 */
2482 int yahoo_parsepacket_conference_msg(struct yahoo_context *ctx,
2483 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2484 {
2485 char *content;
2486 char *tmp, delim[5];
2487
2488 /* Make working copy of content */
2489 content = strdup(inpkt->content);
2490
2491 /* init elements to all null */
2492 pkt->conf_id = NULL;
2493 pkt->conf_host = NULL;
2494 pkt->conf_user = NULL;
2495 pkt->conf_userlist = NULL;
2496 pkt->conf_inviter = NULL;
2497 pkt->conf_msg = NULL;
2498
2499 tmp = NULL;
2500 delim[0] = 2; /* control-b */
2501 delim[1] = 0;
2502
2503 /* parse error messages first */
2504 if (pkt->msgtype == YAHOO_MSGTYPE_ERROR)
2505 {
2506 FREE(content);
2507 return 0;
2508 }
2509
2510 if (content)
2511 {
2512 tmp = strtok(content, delim);
2513 }
2514
2515 if (tmp) /* got the conference id */
2516 {
2517 pkt->conf_id = strdup(tmp);
2518 tmp = strtok(NULL, delim);
2519 }
2520
2521 if (tmp) /* conference user */
2522 {
2523 pkt->conf_user = strdup(tmp);
2524 tmp = strtok(NULL, delim);
2525 }
2526
2527 if (tmp) /* msg */
2528 {
2529 pkt->conf_msg = strdup(tmp);
2530 tmp = strtok(NULL, delim);
2531 }
2532
2533 FREE(content);
2534 return 0;
2535 }
2536
2537 /*
2538
2539 yahoo_parsepacket_conference_user()
2540 (User logged on/off to conference)
2541 Packet format:
2542 id^user_who_logged_on/off
2543
2544 Parses Arguments:
2545 char *conf_id == The conference id -- usually of the form name-number,
2546 though it doesn't seem to matter much. ex: jaylubo-123
2547 char *conf_user == User who logged on to conference.
2548
2549 */
2550 int yahoo_parsepacket_conference_user(struct yahoo_context *ctx,
2551 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2552 {
2553 char *content;
2554 char *tmp, delim[5];
2555
2556 /* Make working copy of content */
2557 content = strdup(inpkt->content);
2558
2559 /* init elements to all null */
2560 pkt->conf_id = NULL;
2561 pkt->conf_host = NULL;
2562 pkt->conf_user = NULL;
2563 pkt->conf_userlist = NULL;
2564 pkt->conf_inviter = NULL;
2565 pkt->conf_msg = NULL;
2566
2567 tmp = NULL;
2568 delim[0] = 2; /* control-b */
2569 delim[1] = 0;
2570
2571 if (content)
2572 {
2573 tmp = strtok(content, delim);
2574 }
2575
2576 if (tmp) /* got the conference id */
2577 {
2578 pkt->conf_id = strdup(tmp);
2579 tmp = strtok(NULL, delim);
2580 }
2581
2582 if (tmp) /* conference user */
2583 {
2584 pkt->conf_user = strdup(tmp);
2585 tmp = strtok(NULL, delim);
2586 }
2587
2588 FREE(content);
2589 return 0;
2590 }
2591
2592 int yahoo_parsepacket_filetransfer(struct yahoo_context *ctx,
2593 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2594 {
2595 char *content;
2596 char *tmp[5];
2597 int i, j, section;
2598
2599 /* Make working copy of content */
2600 content = strdup(inpkt->content);
2601
2602 /* init elements to all null */
2603 pkt->file_from = NULL;
2604 pkt->file_flag = NULL;
2605 pkt->file_url = NULL;
2606 pkt->file_expires = 0;
2607 pkt->file_description = NULL;
2608
2609 /* overkill allocation, but simple since only temporary use */
2610 tmp[0] = strdup(content);
2611 tmp[1] = strdup(content);
2612 tmp[2] = strdup(content);
2613 tmp[3] = strdup(content);
2614 tmp[4] = strdup(content);
2615
2616 /* raw data format: from,flag,url,timestamp,description */
2617
2618 i = 0;
2619 j = 0;
2620 section = 0;
2621 tmp[0][0] = 0;
2622 tmp[1][0] = 0;
2623 tmp[2][0] = 0;
2624 tmp[3][0] = 0;
2625 tmp[4][0] = 0;
2626
2627 while (i < strlen(content))
2628 {
2629 char ch = content[i];
2630
2631 if (ch == ',' && section < 4)
2632 {
2633 j = 0;
2634 section++;
2635 }
2636 else
2637 {
2638 tmp[section][j++] = ch;
2639 tmp[section][j] = 0;
2640 }
2641 i++;
2642 }
2643
2644 /* do stuff with extracted parts */
2645 pkt->file_from = strdup(tmp[0]);
2646 pkt->file_flag = strdup(tmp[1]);
2647 pkt->file_url = strdup(tmp[2]);
2648 pkt->file_expires = atoi(tmp[3]);
2649 pkt->file_description = strdup(tmp[4]);
2650
2651 /* free working variables */
2652 FREE(tmp[0]);
2653 FREE(tmp[1]);
2654 FREE(tmp[2]);
2655 FREE(tmp[3]);
2656 FREE(tmp[4]);
2657 FREE(content);
2658 return 0;
2659 }
2660
2661 int yahoo_parsepacket_calendar(struct yahoo_context *ctx,
2662 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2663 {
2664 char *content;
2665 char *tmp, delim[5];
2666
2667 /* Make working copy of content */
2668 content = strdup(inpkt->content);
2669
2670 /* init elements to all null */
2671 pkt->cal_url = NULL;
2672 pkt->cal_timestamp = NULL;
2673 pkt->cal_type = 0;
2674 pkt->cal_title = NULL;
2675 pkt->cal_description = NULL;
2676
2677 tmp = NULL;
2678 delim[0] = 2; /* control-b */
2679 delim[1] = 0;
2680
2681 if (content)
2682 {
2683 tmp = strtok(content, delim);
2684 }
2685
2686 if (tmp) /* got the url */
2687 {
2688 pkt->cal_url = strdup(tmp);
2689 tmp = strtok(NULL, delim);
2690
2691 /*
2692 v= is not the type code
2693 i= doesn't look like it either
2694 tmp2 = strstr(pkt->cal_url, "v=");
2695 if ( tmp2 )
2696 {
2697 pkt->cal_type = atoi(tmp2);
2698 }
2699 */
2700
2701 }
2702
2703 if (tmp) /* unknown (type code?) */
2704 {
2705 /* appears this isn't it either, I don't see where it is */
2706 /* pkt->cal_type = atoi(tmp); */
2707 tmp = strtok(NULL, "\r\n");
2708 }
2709
2710 if (tmp) /* timestamp */
2711 {
2712 pkt->cal_timestamp = strdup(tmp);
2713 tmp = strtok(NULL, "\r\n");
2714 }
2715
2716 if (tmp) /* title */
2717 {
2718 pkt->cal_title = strdup(tmp);
2719 tmp = strtok(NULL, delim); /* use delim since it won't occur again */
2720 }
2721
2722 if (tmp)
2723 {
2724 pkt->cal_description = strdup(tmp);
2725 }
2726
2727 FREE(content);
2728 return 0;
2729 }
2730
2731 int yahoo_parsepacket_chatinvite(struct yahoo_context *ctx,
2732 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2733 {
2734 char *content;
2735 int len;
2736
2737 /* Make working copy of content */
2738 content = strdup(inpkt->content);
2739 len = strlen(content);
2740
2741 /* do special parsing for invite later on */
2742 pkt->chat_invite_content = strdup(content);
2743
2744 return 0;
2745 }
2746
2747 int yahoo_parsepacket_newcontact(struct yahoo_context *ctx,
2748 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2749 {
2750 char *content;
2751 int len;
2752
2753 /* Make working copy of content */
2754 content = strdup(inpkt->content);
2755 len = strlen(content);
2756
2757 /* cheat for now, say if first digit is number */
2758 if (len > 0)
2759 {
2760 if (isdigit((int) content[0]))
2761 {
2762 return yahoo_parsepacket_status(ctx, pkt, inpkt);
2763 }
2764 else
2765 {
2766 return yahoo_parsepacket_message(ctx, pkt, inpkt);
2767 }
2768 }
2769
2770 return 0;
2771 }
2772
2773 int yahoo_parsepacket_status(struct yahoo_context *ctx,
2774 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2775 {
2776 char *content;
2777 char *tmpc;
2778 char *tmp1;
2779 int i;
2780 int len;
2781 int index;
2782 int realcount;
2783
2784 /* Make working copy of content */
2785 content = strdup(inpkt->content);
2786 len = strlen(content);
2787
2788 /* Pull off the flag from the initial part of the content */
2789 /* this flag indicates the number of buddy that're online */
2790 pkt->flag = 0;
2791 tmpc = content;
2792 while (tmpc[0] && isdigit((int) tmpc[0]))
2793 {
2794 pkt->flag = pkt->flag * 10 + (content[0] - '0');
2795 tmpc++;
2796 }
2797 if (tmpc[0] && tmpc[0] == ',')
2798 {
2799 tmpc++;
2800 }
2801
2802 /*
2803 We're receiving either this:
2804 2,buddy1(0,728EE9FB,0,1,0,0),buddy2(0,7AC00000,0,1,0,0)
2805 or this:
2806 buddy1(0,728EE9FB,0,1,0,0)
2807 hence:
2808 */
2809
2810 if (pkt->flag == 0)
2811 {
2812 pkt->idstatus_count = 1;
2813 }
2814 else
2815 {
2816 pkt->idstatus_count = pkt->flag;
2817 }
2818
2819 /* print an error if I get the was not AWAY */
2820 if (strstr(tmpc, "was not AWAY"))
2821 {
2822 pkt->idstatus_count = 0;
2823 yahoo_dbg_Print("libyahoo", "yahoo_parsepacket_status: "
2824 "got a 'was not AWAY' message\n");
2825 }
2826
2827 if (pkt->idstatus_count == 0)
2828 {
2829 /* No entries, so no array needed */
2830 pkt->idstatus = NULL;
2831 }
2832 else
2833 {
2834 /* Allocate the array */
2835 pkt->idstatus = (struct yahoo_idstatus **)
2836 calloc(sizeof(struct yahoo_idstatus), pkt->idstatus_count);
2837
2838 for (i = 0; i < pkt->idstatus_count; i++)
2839 {
2840 pkt->idstatus[i] = (struct yahoo_idstatus *)
2841
2842 calloc(1, sizeof(struct yahoo_idstatus));
2843 }
2844 }
2845
2846 index = 0;
2847 tmp1 = NULL;
2848 realcount = 0;
2849 while (tmpc && tmpc[0] && pkt->idstatus)
2850 {
2851 struct yahoo_idstatus *tmpid;
2852
2853 /* Get pointer to allocated structure to hold status data */
2854 tmpid = pkt->idstatus[index++];
2855 if (!tmpid)
2856 {
2857 /* shortcut, we know there can't be any more status entries
2858 at this point */
2859 /* yahoo_dbg_Print("status", "null tmpid"); */
2860 break;
2861 }
2862
2863 /* YPNS2.0 nick(status,msg,connection_id,UNK,in_pager,in_chat,in_game) */
2864 /* tnneul(99,test,message^A,6AD68325,0,1,0,0) */
2865 /* 0 1 2 3 4 5 6 */
2866
2867 /* YPNS1.0 nick(status,connection_id,UNK,in_pager,in_chat,in_game) */
2868 /* nneul(0,7081F531,0,1,0,0) */
2869 /* 0 2 3 4 5 6 */
2870
2871 /* rewrite this whole section in a less ugly fashion */
2872 /* first pull off the id */
2873
2874 /* YUCK - YPNS2.0 has variable format status records, if type is 99,
2875 it has 7 fields, second is msg */
2876
2877 #if 0
2878 yahoo_dbg_Print("status", "whole string = '%s'\n",
2879 yahoo_dbg_NullCheck(tmpc));
2880 #endif
2881
2882 if (tmp1)
2883 {
2884 tmp1 = strtok(NULL, "(");
2885 }
2886 else
2887 {
2888 tmp1 = strtok(tmpc, "(");
2889 }
2890 if (tmp1 && tmp1[0] == ',')
2891 {
2892 tmp1++;
2893 }
2894
2895 if (tmp1)
2896 {
2897 tmpid->id = strdup(tmp1);
2898 realcount++;
2899
2900 for (i = 0; i <= 6 && tmp1; i++)
2901 {
2902 #if 0
2903 yahoo_dbg_Print("status", "i==%d\n", i);
2904 #endif
2905
2906 if (i == 6) /* end of status area */
2907 {
2908 tmp1 = strtok(NULL, "),");
2909 }
2910 else if (i == 1)
2911 {
2912 char delim[3];
2913
2914 if (tmpid->status == YAHOO_STATUS_CUSTOM)
2915 {
2916 delim[0] = 1;
2917 delim[1] = ',';
2918 delim[1] = 0;
2919 tmp1 = strtok(NULL, delim);
2920 }
2921 else
2922 {
2923 i = 2;
2924 tmp1 = strtok(NULL, ",");
2925 }
2926 }
2927 else
2928 {
2929
2930 tmp1 = strtok(NULL, ",");
2931 }
2932
2933 /* then pull off the particular element of the list */
2934 if (tmp1)
2935 {
2936 switch (i)
2937 {
2938 case 0: /* status */
2939 tmpid->status = atoi(tmp1);
2940 break;
2941 case 1: /* msg */
2942 if (tmpid->status == YAHOO_STATUS_CUSTOM)
2943 {
2944 tmpid->status_msg = strdup(tmp1);
2945 }
2946 break;
2947 case 2: /* session id */
2948 tmpid->connection_id = strdup(tmp1);
2949 break;
2950 case 3: /* dunno what this is */
2951 break;
2952 case 4:
2953 tmpid->in_pager = atoi(tmp1);
2954 break;
2955 case 5:
2956 tmpid->in_chat = atoi(tmp1);
2957 break;
2958 case 6:
2959 tmpid->in_game = atoi(tmp1);
2960 break;
2961 }
2962 }
2963 }
2964 }
2965 }
2966
2967 for (i = realcount; i <= pkt->idstatus_count; i++)
2968 {
2969 if (pkt->idstatus && pkt->idstatus[i])
2970 {
2971 FREE(pkt->idstatus[i]);
2972 }
2973 }
2974 pkt->idstatus_count = realcount;
2975
2976 /* Free working copy of content */
2977 FREE(content);
2978
2979 /* Return ok for success */
2980 return (0);
2981 }
2982
2983 int yahoo_parsepacket_message(struct yahoo_context *ctx,
2984 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
2985 {
2986 char *content;
2987 char *tmp_id;
2988 int i, j, section;
2989
2990 if (pkt->msgtype == YAHOO_MSGTYPE_OFFLINE)
2991 {
2992 return yahoo_parsepacket_message_offline(ctx, pkt, inpkt);
2993 }
2994
2995 /* Make working copy of content */
2996 content = strdup(inpkt->content);
2997 tmp_id = strdup(content);
2998
2999 /* initialize */
3000 pkt->msg_status = 0;
3001
3002 /* possible message content formats: */
3003 /* userid(#) *//* msgtype == YAHOO_MSGTYPE_STATUS */
3004 /* userid,,msg */
3005
3006 /* this needed butchered */
3007 /* YAHOO_MSGTYPE_OFFLINE */
3008 /* 6,6,tnneul,nneul,Tue Mar 7 12:14:50 2000,test offline msg^A */
3009
3010 i = 0;
3011 j = 0;
3012 section = 0;
3013 tmp_id[0] = 0;
3014 while (i < strlen(content))
3015 {
3016 char ch = content[i];
3017
3018 if (section == 0) /* parsing userid */
3019 {
3020 if (ch == ',')
3021 {
3022 j = 0;
3023 section = 1;
3024 }
3025 else if (ch == '(')
3026 {
3027 j = 0;
3028 section = 2;
3029 }
3030 else
3031 {
3032 tmp_id[j++] = ch;
3033 tmp_id[j] = 0;
3034 }
3035 }
3036 else if (section == 1) /* parsing flag */
3037 {
3038 if (ch == ',')
3039 {
3040 j = 0;
3041 section = 3;
3042 }
3043 }
3044 else if (section == 2) /* parsing status */
3045 {
3046 if (ch == ')')
3047 {
3048 j = 0;
3049 section = 3;
3050 }
3051 else
3052 {
3053 if (isdigit((int) ch))
3054 {
3055 pkt->msg_status *= 10;
3056 pkt->msg_status += ch - '0';
3057 }
3058 }
3059 }
3060 else
3061 {
3062 pkt->msg = strdup(&content[i]);
3063 break;
3064 }
3065
3066 i++;
3067 }
3068
3069 /* do stuff with extracted parts */
3070 pkt->msg_id = strdup(tmp_id);
3071
3072 /* handle empty message case */
3073 /* don't pass a message if it's just a status update */
3074 if (!pkt->msg && pkt->msgtype != YAHOO_MSGTYPE_STATUS)
3075 {
3076 pkt->msg = strdup("");
3077 }
3078
3079 /* free working variables */
3080 FREE(tmp_id);
3081 FREE(content);
3082
3083 /* Return ok for success */
3084 return (0);
3085 }
3086
3087 /* This parses a special format offline message, and is only currently
3088 called from yahoo_parsepacket_message. */
3089 int yahoo_parsepacket_message_offline(struct yahoo_context *ctx,
3090 struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
3091 {
3092 char *content;
3093 char *to_id;
3094 char *from_id;
3095 char *timestamp;
3096 int i, j, section;
3097
3098 /* Make working copy of content */
3099 content = strdup(inpkt->content);
3100 to_id = strdup(content);
3101 from_id = strdup(content);
3102 timestamp = strdup(content);
3103
3104 /* initialize */
3105 pkt->msg_status = 0;
3106
3107 /* 6,6,tnneul,nneul,Tue Mar 7 12:14:50 2000,test offline msg^A */
3108 /* sec0,sec1,sec2=to,sec3=from,sec4=tstamp,sec5=msg */
3109
3110 i = 0;
3111 j = 0;
3112 section = 0;
3113 to_id[0] = 0;
3114 from_id[0] = 0;
3115 timestamp[0] = 0;
3116
3117 while (i < strlen(content))
3118 {
3119 char ch = content[i];
3120
3121 if (section == 0) /* parsing first unknown number */
3122 {
3123 if (ch == ',')
3124 {
3125 j = 0;
3126 section = 1;
3127 }
3128 }
3129 else if (section == 1) /* parsing second unknown number */
3130 {
3131 if (ch == ',')
3132 {
3133 j = 0;
3134 section = 2;
3135 }
3136 }
3137 else if (section == 2) /* parsing to-id */
3138 {
3139 if (ch == ',')
3140 {
3141 j = 0;
3142 section = 3;
3143 }
3144 else
3145 {
3146 to_id[j++] = ch;
3147 to_id[j] = 0;
3148 }
3149 }
3150 else if (section == 3) /* parsing from-id */
3151 {
3152 if (ch == ',')
3153 {
3154 j = 0;
3155 section = 4;
3156 }
3157 else
3158 {
3159 from_id[j++] = ch;
3160 from_id[j] = 0;
3161 }
3162 }
3163 else if (section == 4) /* parsing timestamp */
3164 {
3165 if (ch == ',')
3166 {
3167 j = 0;
3168 section = 5;
3169 }
3170 else
3171 {
3172 timestamp[j++] = ch;
3173 timestamp[j] = 0;
3174 }
3175 }
3176 else
3177 {
3178 pkt->msg = strdup(&content[i]);
3179 break;
3180 }
3181
3182 i++;
3183 }
3184
3185 /* do stuff with extracted parts */
3186 pkt->msg_id = strdup(from_id);
3187 pkt->msg_timestamp = strdup(timestamp);
3188 if (pkt->active_id)
3189 {
3190 FREE(pkt->active_id);
3191 pkt->active_id = strdup(to_id);
3192 }
3193
3194 /* free working variables */
3195 FREE(timestamp);
3196 FREE(from_id);
3197 FREE(to_id) FREE(content);
3198
3199 /* Return ok for success */
3200 return (0);
3201 }
3202
3203 int yahoo_getdata(struct yahoo_context *ctx)
3204 {
3205 char buf[1000];
3206 int res;
3207
3208 /* This is a http mode connection, so just send a ping to get any
3209 new data from the server. */
3210 if (ctx->connect_mode == YAHOO_CONNECT_HTTP ||
3211 ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
3212 {
3213 yahoo_sendcmd(ctx, YAHOO_SERVICE_PING, ctx->user, "", 0);
3214 return (1);
3215 }
3216
3217 /* this assumes that data is ready */
3218 /* Read from the connection to the server and get any new data */
3219 res = read(ctx->sockfd, buf, 1000);
3220 if (res == -1)
3221 {
3222 yahoo_dbg_Print("io",
3223 "yahoo_getdata: error reading data from server\n");
3224 return (0);
3225 }
3226 if (res > 0)
3227 {
3228 yahoo_addtobuffer(ctx, buf, res);
3229 yahoo_dbg_Print("io", "[libyahoo] yahoo_getdata: read (%d) bytes\n",
3230 res);
3231 return 1;
3232 }
3233 else if (res == 0)
3234 {
3235 yahoo_dbg_Print("io",
3236 "[libyahoo] yahoo_getdata: got zero length read\n", res);
3237 return 0;
3238 }
3239
3240 return (1);
3241 }
3242
3243 struct yahoo_rawpacket *yahoo_getpacket(struct yahoo_context *ctx)
3244 {
3245 struct yahoo_rawpacket *pkt;
3246 struct yahoo_rawpacket *retpkt;
3247 int *buflen = &ctx->io_buf_curlen;
3248 char *buffer = ctx->io_buf;
3249 unsigned int contentlen;
3250
3251 /* If buffer doesn't start with YHOO, skip bytes until it
3252 does. This is to protect against possible packet alignment
3253 errors if I size something wrong at any time. */
3254
3255 while ((*buflen >= 4) && (memcmp(buffer, "YHOO", 4)))
3256 {
3257 /* making quiet for now so I don't have to work too hard on the HTTP support */
3258 #if 0
3259 printf("\nskipped buffer byte (%d)\n", buffer[0]);
3260 #endif
3261 memmove(buffer, buffer + 1, *buflen - 1);
3262 *buflen = *buflen - 1;
3263 }
3264
3265 /* Don't do anything if the buffer doesn't have at least a full
3266 header */
3267 if (*buflen < YAHOO_PACKET_HEADER_SIZE)
3268 {
3269 // printf("returning null cause buffer is too small\n");
3270 return NULL;
3271 }
3272
3273 /* print out the beginning of the buffer */
3274 #if 0
3275 printf("Buffer (buflen = %d):\n", *buflen);
3276 for (i = 0; i < *buflen; i++)
3277 {
3278 if ((i) % 10 == 0)
3279 {
3280 printf("\n%.4d: ", i);
3281 }
3282 if (isprint(buffer[i]))
3283 {
3284 printf("%-3d %c ", buffer[i], buffer[i]);
3285 }
3286 else
3287 {
3288 printf("%-3d ", buffer[i]);
3289 }
3290 }
3291 printf("\n");
3292 #endif
3293 /* Make pkt point to buffer for ease of use */
3294 pkt = (struct yahoo_rawpacket *) buffer;
3295
3296 /* Determine the content size specified by the header */
3297 contentlen = yahoo_makeint(pkt->len) - YAHOO_PACKET_HEADER_SIZE;
3298 // printf("contentlen = %d\n", contentlen);
3299
3300 /* Don't continue if buffer doesn't have full content in it */
3301 if (*buflen < (YAHOO_PACKET_HEADER_SIZE + contentlen))
3302 {
3303 // printf("buffer not big enough for contentlen\n");
3304 return NULL;
3305 }
3306
3307 /* Copy this packet */
3308 retpkt =
3309 (struct yahoo_rawpacket *) malloc(YAHOO_PACKET_HEADER_SIZE +
3310 contentlen);
3311 memcpy(retpkt, buffer, YAHOO_PACKET_HEADER_SIZE + contentlen);
3312
3313 /* Shift the buffer */
3314 memmove(buffer, buffer + YAHOO_PACKET_HEADER_SIZE + contentlen,
3315 *buflen - YAHOO_PACKET_HEADER_SIZE - contentlen);
3316
3317 /* Adjust the buffer length */
3318 *buflen -= (YAHOO_PACKET_HEADER_SIZE + contentlen);
3319
3320 /* Return the packet */
3321 return retpkt;
3322 }
3323
3324 int yahoo_isbuddy(struct yahoo_context *ctx, const char *id)
3325 {
3326 int i;
3327 char *buddy = NULL;
3328
3329 if (!id || !ctx || !ctx->buddies)
3330 {
3331 return FALSE;
3332 }
3333
3334 for (i = 0; ctx->buddies[i]; i++)
3335 {
3336 buddy = (ctx->buddies[i])->id;
3337 if (!strcasecmp(id, buddy))
3338 {
3339 return TRUE;
3340 }
3341 }
3342
3343 return FALSE;
3344 }
3345
3346 static void yahoo_free_address (struct yahoo_address *add)
3347 {
3348 yahoo_dbg_Print("addressbook",
3349 "[libyahoo] yahoo_free_address: record at address 0x%08p for user %s (%s %s) being free'd\n",
3350 add, add->id, add->firstname, add->lastname);
3351
3352 FREE (add->firstname);
3353 FREE (add->lastname);
3354 FREE (add->emailnickname);
3355 FREE (add->email);
3356 FREE (add->workphone);
3357 FREE (add->homephone);
3358 }
3359
3360 void yahoo_freeaddressbook(struct yahoo_context *ctx)
3361 {
3362 unsigned int count = ctx->address_count;
3363 struct yahoo_address *add_p = ctx->addresses;
3364
3365 if (NULL == ctx || NULL == ctx->addresses)
3366 return;
3367
3368 while (count-- > 0)
3369 {
3370 yahoo_free_address (add_p++);
3371 }
3372
3373 ctx->address_count = 0;
3374 FREE (ctx->addresses);
3375 }
3376
3377 static void yahoo_data_to_addressbook (char *block, struct yahoo_context *ctx)
3378 {
3379 char *token = NULL;
3380 int record = 0;
3381 struct yahoo_address *add = NULL;
3382
3383 if (NULL == block || NULL == ctx)
3384 return;
3385
3386 yahoo_freeaddressbook (ctx);
3387
3388 add = ctx->addresses = calloc (ctx->address_count, sizeof (struct yahoo_address));
3389
3390 /*
3391 Okay!
3392 At this point we have a char * (block) that has \012 delimited records
3393 Each record (as a string when retreived with strtok) follows the format:
3394 <ID>:<FIRSTNAME>\011<LASTNAME>\011<EMAILNICKNAME>\011<EMAIL>\011<HOMEPHONE>\011<WORKPHONE>\011[01]\011<ENTRYID>\000
3395 */
3396
3397 token = strtok (block, "\012");
3398 while (NULL != token)
3399 {
3400 /*
3401 Here we must use memtok because we'll get some repeated tokens!!!!!
3402 */
3403 char *field = NULL;
3404 size_t token_len = 0, found = 0;
3405
3406 ++record;
3407 token_len = strlen (token);
3408
3409 field = memtok(token, token_len, ":", 1, &found);
3410
3411 if (NULL != field)
3412 {
3413 add->id = memdupasstr(field, found);
3414 field = memtok(0, 0, "\011", 1, &found);
3415 }
3416
3417 if (NULL != field)
3418 {
3419 add->firstname = memdupasstr(field, found);
3420 field = memtok(0, 0, "\011", 1, &found);
3421 }
3422
3423 if (NULL != field)
3424 {
3425 add->lastname = memdupasstr(field, found);
3426 field = memtok(0, 0, "\011", 1, &found);
3427 }
3428
3429 if (NULL != field)
3430 {
3431 add->emailnickname = memdupasstr(field, found);
3432 field = memtok(0, 0, "\011", 1, &found);
3433 }
3434
3435 if (NULL != field)
3436 {
3437 add->email = memdupasstr(field, found);
3438 field = memtok(0, 0, "\011", 1, &found);
3439 }
3440
3441 if (NULL != field)
3442 {
3443 add->homephone = memdupasstr(field, found);
3444 field = memtok(0, 0, "\011", 1, &found);
3445 }
3446
3447 if (NULL != field)
3448 {
3449 add->workphone = memdupasstr(field, found);
3450 field = memtok(0, 0, "\011", 1, &found);
3451 }
3452
3453 if (NULL != field)
3454 {
3455 add->primary_phone = (*field == '0' ? home : work);
3456 field = memtok(0, 0, "", 1, &found);
3457 }
3458
3459 if (NULL != field)
3460 {
3461 char *entryid = memdupasstr(field, found);
3462 if (NULL != entryid)
3463 {
3464 add->entryid = atoi (entryid);
3465 FREE (entryid);
3466 }
3467 }
3468
3469 yahoo_dbg_Print("addressbook",
3470 "[libyahoo] yahoo_fetchaddressbook: record #%d is for user %s (%s %s)\n",
3471 record, add->id, add->firstname, add->lastname);
3472
3473 ++add;
3474
3475 token = strtok (NULL, "\012");
3476 }
3477 }
3478
3479 /* retreive the details of the friends in your address book that have a Yahoo! id listed */
3480 int yahoo_fetchaddressbook(struct yahoo_context *ctx)
3481 {
3482 char buffer[5000];
3483 int servfd;
3484 int res;
3485 int copied = 0, size = 5000;
3486 char *address = NULL, *copy = NULL;
3487
3488 if (!ctx)
3489 {
3490 return 0;
3491 }
3492
3493 yahoo_dbg_Print("addressbook",
3494 "[libyahoo] yahoo_fetchaddressbook: starting\n");
3495
3496 /* Check for cached addresses */
3497 if (ctx->addresses)
3498 {
3499 yahoo_freeaddressbook(ctx);
3500 }
3501
3502 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
3503 {
3504 servfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
3505 }
3506 else
3507 {
3508 servfd = yahoo_socket_connect(ctx, YAHOO_ADDRESS_HOST, YAHOO_ADDRESS_PORT);
3509 }
3510
3511 if (!servfd)
3512 {
3513 printf("[libyahoo] failed to connect to address book server.\n");
3514 return (0);
3515 }
3516
3517 strcpy(buffer, "GET ");
3518 if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
3519 {
3520 strcat(buffer, YAHOO_ADDRESS_HOST);
3521 }
3522 strcat(buffer, "/yab/uk/yab?v=PG&A=s");
3523 strcat(buffer, " HTTP/1.0\r\n");
3524 strcat(buffer, "User-Agent: " YAHOO_USER_AGENT "\r\n");
3525 strcat(buffer, "Host: " YAHOO_AUTH_HOST "\r\n");
3526 strcat(buffer, "Cookie: ");
3527 strcat(buffer, ctx->cookie);
3528 strcat(buffer, "\r\n");
3529 strcat(buffer, "\r\n");
3530
3531 write(servfd, buffer, strlen(buffer));
3532
3533 yahoo_dbg_Print("addressbook",
3534 "[libyahoo] yahoo_fetchaddressbook: writing buffer '%s'\n", buffer);
3535
3536 while ((res = yahoo_tcp_readline(buffer, 5000, servfd)) > 0)
3537 {
3538 if ('\012' == buffer[0])
3539 continue;
3540
3541 if (0 == strncmp (buffer, "1\011", 2))
3542 {
3543 yahoo_dbg_Print("addressbook",
3544 "[libyahoo] yahoo_fetchaddressbook: found first line\n");
3545 if (3 == res)
3546 {
3547 yahoo_dbg_Print("addressbook",
3548 "[libyahoo] yahoo_fetchaddressbook: however there's been a problem\n");
3549 break;
3550 }
3551
3552 address = &buffer[2];
3553 }
3554 else if (NULL != address)
3555 {
3556 address = &buffer[0];
3557 }
3558
3559 if (NULL != address)
3560 {
3561 if (NULL == copy)
3562 {
3563 copy = malloc (size);
3564 memset (copy, 0, size);
3565 }
3566
3567 if ((copied + res) > size)
3568 {
3569 char *newcopy = NULL;
3570
3571 yahoo_dbg_Print("addressbook",
3572 "[libyahoo] yahoo_fetchaddressbook: resizing buffer from %d bytes to %d bytes\n", size, size * 2);
3573 size *= 2;
3574 newcopy = malloc (size);
3575 memset (newcopy, 0, size);
3576 memcpy (newcopy, copy, copied);
3577 free (copy);
3578 copy = newcopy;
3579 }
3580
3581 copied += res;
3582 strcat (copy, address);
3583 ++ctx->address_count;
3584 }
3585 }
3586
3587 yahoo_data_to_addressbook (copy, ctx);
3588 FREE (copy);
3589
3590 yahoo_dbg_Print("addressbook",
3591 "[libyahoo] yahoo_fetchaddressbook: closing server connection\n");
3592 close(servfd);
3593 servfd = 0;
3594 yahoo_dbg_Print("addressbook",
3595 "[libyahoo] yahoo_fetchaddressbook: closed server connection\n");
3596
3597 yahoo_dbg_Print("addressbook", "[libyahoo] yahoo_fetchaddressbook: done (%d addresses retreived)\n", ctx->address_count);
3598
3599 return ctx->address_count;
3600 }