| |
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 } |