1 /*
2 * Handles incoming and creates outgoing SNAC packets
3 * for the family 19 (roster) commands.
4 *
5 * climm Copyright (C) © 2001-2007 Rüdiger Kuhlmann
6 *
7 * climm is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 dated June, 1991.
10 *
11 * climm is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 * License for more details.
15 *
16 * In addition, as a special exception permission is granted to link the
17 * code of this release of climm with the OpenSSL project's "OpenSSL"
18 * library, and distribute the linked executables. You must obey the GNU
19 * General Public License in all respects for all of the code used other
20 * than "OpenSSL". If you modify this file, you may extend this exception
21 * to your version of the file, but you are not obligated to do so. If you
22 * do not wish to do so, delete this exception statement from your version
23 * of this file.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this package; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 * 02111-1307, USA.
29 *
30 * As a special exemption, you may link your binary against OpenSSL,
31 * provided your operating system distribution doesn't ship libgnutls.
32 *
33 * $Id: oscar_roster.c 2831 2009-08-20 21:48:15Z kuhlmann $
34 */
35
36 #include "climm.h"
37 #include <assert.h>
38 #include "oscar_base.h"
39 #include "oscar_tlv.h"
40 #include "oscar_snac.h"
41 #include "oscar_service.h"
42 #include "oscar_contact.h"
43 #include "oscar_roster.h"
44 #include "oscar_oldicq.h"
45 #include "packet.h"
46 #include "contact.h"
47 #include "connection.h"
48 #include "im_icq8.h"
49 #include "conv.h"
50 #include "file_util.h"
51 #include "util_ui.h"
52 #include "im_response.h"
53
54 #define TLV_REQAUTH 102
55 #define TLV_GROUPITEMS 200
56 #define TLV_UNKNIDLE 201
57 #define TLV_PRIVACY 202
58 #define TLV_VISIBILITY 203
59 #define TLV_ALLOWIDLE 204
60 #define TLV_ICQTIC 205
61 #define TLV_IMPORT 212
62 #define TLV_ICON 213
63 #define TLV_NICK 305
64 #define TLV_LOCALMAIL 311
65 #define TLV_LOCALSMS 314
66 #define TLV_LOCALCOMM 316
67 #define TLV_LOCALACT 317
68 #define TLV_LOCALSOUND 318
69 #define TLV_LASTUPD 325
70
OscarRosterC(void)71 Roster *OscarRosterC (void)
72 {
73 return calloc (sizeof (Roster), 1);
74 }
75
OscarRosterEntryD(RosterEntry * entry)76 static void OscarRosterEntryD (RosterEntry *entry)
77 {
78 RosterEntry *next;
79
80 while (entry)
81 {
82 s_free (entry->name);
83 s_free (entry->nick);
84 TLVD (entry->tlv);
85 next = entry->next;
86 free (entry);
87 entry = next;
88 }
89 }
90
OscarRosterD(Roster * roster)91 void OscarRosterD (Roster *roster)
92 {
93 OscarRosterEntryD (roster->generic);
94 OscarRosterEntryD (roster->groups);
95 OscarRosterEntryD (roster->normal);
96 OscarRosterEntryD (roster->visible);
97 OscarRosterEntryD (roster->invisible);
98 OscarRosterEntryD (roster->ignore);
99 s_free (roster->ICQTIC);
100 s_free (roster->delname);
101 free (roster);
102 }
103
104 /*
105 * CLI_REQLISTS - SNAC(13,2)
106 */
107
108 /* implemented as macro */
109
110 /*
111 * SRV_REPLYLISTS - SNAC(13,3)
112 */
JUMP_SNAC_F(SnacSrvReplylists)113 JUMP_SNAC_F(SnacSrvReplylists)
114 {
115 Server *serv = event->conn->serv;
116
117 if (serv->flags & CONN_WIZARD)
118 {
119 IMRoster (serv, IMROSTER_IMPORT);
120 if (serv->flags & CONN_INITWP)
121 {
122 Contact *cont = ContactScreen (serv, serv->screen);
123 CONTACT_GENERAL (cont);
124 CONTACT_MORE (cont);
125 SnacCliMetasetabout (serv, "climm");
126 SnacCliMetasetgeneral (serv, cont);
127 SnacCliMetasetmore (serv, cont);
128 }
129 }
130 else
131 IMRoster (serv, IMROSTER_DIFF);
132 }
133
134 /*
135 * CLI_REQROSTER - SNAC(13,4)
136 */
137
138 /* implemented as macro */
139
140 /*
141 * CLI_CHECKROSTER - SNAC(13,5)
142 */
SnacCliCheckroster(Server * serv)143 UDWORD SnacCliCheckroster (Server *serv)
144 {
145 ContactGroup *cg;
146 Packet *pak;
147 UDWORD ref;
148 int i;
149
150 cg = serv->contacts;
151 pak = SnacC (serv, 19, 5, 0, 0);
152 for (i = 0; (/*cont =*/ ContactIndex (cg, i)); )
153 i++;
154
155 PacketWriteB4 (pak, 0); /* last modification of server side contact list */
156 PacketWriteB2 (pak, 0); /* # of entries */
157 ref = pak->ref;
158 SnacSend (serv, pak);
159 return ref;
160 }
161
162 /*
163 * SRV_REPLYROSTER - SNAC(13,6)
164 */
JUMP_SNAC_F(SnacSrvReplyroster)165 JUMP_SNAC_F(SnacSrvReplyroster)
166 {
167 Server *serv;
168 Packet *pak;
169 Event *event2;
170 Roster *roster;
171 RosterEntry **rref;
172 RosterEntry *re;
173 int i, k, l;
174 int cnt_sbl_add, cnt_sbl_chn, cnt_sbl_del;
175 int cnt_loc_add, cnt_loc_chn, cnt_loc_del;
176 strc_t cname;
177 UWORD count, j, TLVlen;
178 time_t stmp;
179
180 if (!event)
181 return;
182
183 serv = event->conn->serv;
184 if (!serv)
185 return;
186
187 pak = event->pak;
188
189 if (!pak)
190 return;
191
192 event2 = QueueDequeue2 (serv->conn, QUEUE_REQUEST_ROSTER, 0, 0);
193 if (!event2 || !event2->callback)
194 {
195 DebugH (DEB_PROTOCOL, "Unrequested roster packet received.\n");
196 return;
197 }
198
199 roster = event2->data;
200 if (!roster)
201 {
202 roster = OscarRosterC ();
203 event2->data = roster;
204 }
205
206 PacketRead1 (pak);
207
208 count = PacketReadB2 (pak); /* COUNT */
209 cnt_sbl_add = cnt_sbl_chn = cnt_sbl_del = 0;
210 cnt_loc_add = cnt_loc_chn = cnt_loc_del = 0;
211 for (i = k = l = 0; i < count; i++)
212 {
213 re = calloc (sizeof (RosterEntry), 1);
214
215 cname = PacketReadB2Str (pak, NULL); /* GROUP NAME */
216 re->tag = PacketReadB2 (pak); /* TAG */
217 re->id = PacketReadB2 (pak); /* ID */
218 re->type = PacketReadB2 (pak); /* TYPE */
219 TLVlen = PacketReadB2 (pak); /* TLV length */
220 re->tlv = TLVRead (pak, TLVlen, -1);
221
222 re->name = strdup (ConvFromServ (cname));
223
224 j = TLVGet (re->tlv, TLV_NICK);
225 assert (j < 200 || j == (UWORD)-1);
226 if (j != (UWORD)-1 && re->tlv[j].str.len)
227 re->nick = strdup (ConvFromServ (&re->tlv[j].str));
228 else
229 re->nick = NULL;
230
231 rref = &roster->generic;
232 switch (re->type)
233 {
234 case roster_normal:
235 /* TLV_REQAUTH */
236 /* TLV_NICK */
237 /* TLV_LOCALMAIL */
238 /* TLV_LOCALSMS */
239 /* TLV_LOCALCOMM */
240 /* TLV_LOCALACT */
241 /* TLV_LOCALSOUND */
242 rref = &roster->normal;
243 if (TLVGet (re->tlv, TLV_REQAUTH) != (UWORD)-1)
244 re->reqauth = 1;
245 break;
246 case roster_group:
247 /* TLV_GROUPITEMS */
248 if (re->tag || re->id)
249 rref = &roster->groups;
250 break;
251 case roster_visible:
252 rref = &roster->visible;
253 break;
254 case roster_invisible:
255 rref = &roster->invisible;
256 break;
257 case roster_ignore:
258 rref = &roster->ignore;
259 break;
260 case roster_lastupd: /* LastUpdateDate */
261 /* TLV_LASTUPD */
262 break;
263 case roster_wierd17: /* wierd */
264 case roster_icon: /* buddy icon */
265 /* TLV_ICON */
266 break;
267 case roster_importt: /* ImportTime */
268 j = TLVGet (re->tlv, TLV_IMPORT);
269 if (j != (UWORD)-1 && re->tlv[j].str.len == 4)
270 roster->import = re->tlv[j].nr;
271 else
272 rl_printf ("#Bogus ImportTime item: %d: %s %d %d.\n", re->type, re->name, re->tag, re->id);
273 break;
274 case roster_icqtic:
275 j = TLVGet (re->tlv, TLV_ICQTIC);
276 if (j != (UWORD)-1)
277 s_repl (&roster->ICQTIC, re->tlv[j].str.txt);
278 break;
279 case roster_visibility:
280 serv->oscar_privacy_tag = re->id;
281 j = TLVGet (re->tlv, TLV_PRIVACY);
282 if (j != (UWORD)-1)
283 {
284 serv->oscar_privacy_value = *re->tlv[j].str.txt;
285 if (*re->tlv[j].str.txt != 3 && *re->tlv[j].str.txt != 4)
286 {
287 rl_printf ("# privacy mode: (%d)\n", *re->tlv[j].str.txt);
288 if (*re->tlv[j].str.txt == 1)
289 rl_printf ("# always visible to all users\n");
290 else if (*re->tlv[j].str.txt == 2)
291 rl_printf ("# never visible to anyone\n");
292 else if (*re->tlv[j].str.txt == 3)
293 rl_printf ("# only visible to always visible contacts\n");
294 else if (*re->tlv[j].str.txt == 4)
295 rl_printf ("# always visible except to invisible contacts\n");
296 else if (*re->tlv[j].str.txt == 5)
297 rl_printf ("# always visible to all contacts\n");
298 else
299 rl_printf ("# unknown/invalid privacy mode\n");
300 rl_printf ("# change with 'contact security <mode>' (to 3 or 4).\n");
301 }
302 }
303 break;
304
305 case roster_presence:
306 case roster_noncont:
307 /* TLV_UNKNIDLE */
308 /* TLV_PRIVACY */
309 /* TLV_VISIBILITY */
310 /* TLV_ALLOWIDLE */
311 case roster_wierd25:
312 case roster_wierd27:
313 case roster_wierd29:
314 case roster_wierd32:
315 break;
316 default:
317 rl_printf ("#Unknown type %d: %s %d %d.\n", re->type, re->name, re->tag, re->id);
318 }
319
320 re->next = *rref;
321 *rref = re;
322 }
323 stmp = PacketReadB4 (pak);
324 if (stmp)
325 {
326 #if 0
327 if (!roster->import)
328 {
329 time_t now = time (NULL);
330 UDWORD da = now;
331 SnacCliRosterentryadd (serv, "ImportTime", 0, 1, roster_importt, TLV_IMPORT, &da, 4);
332 }
333 if (!roster->ICQTIC)
334 SnacCliRosterentryadd (serv, "ICQTIC", 0, 2, roster_icqtic, TLV_ICQTIC, "3608,0,0,0,60,null", 18);
335 if (!serv->oscar_privacy_tag)
336 {
337 serv->oscar_privacy_tag = rand () % 0x8000;
338 SnacCliRosterentryadd (serv, "", 0, serv->oscar_privacy_tag, roster_visibility, TLV_PRIVACY, "\x03", 1);
339 serv->oscar_privacy_value = 3;
340 }
341 #endif
342 if (~serv->conn->connect & CONNECT_OK)
343 CliFinishLogin (serv);
344
345 SnacCliRosterack (serv);
346 event2->callback (event2);
347 }
348 else
349 QueueEnqueue (event2);
350 }
351
352 /*
353 * CLI_ROSTERACK - SNAC(13,7)
354 */
355
356 /* implemented as macro */
357
358 /*
359 * CLI_ADDBUDDY - SNAC(13,8)
360 */
361
SnacCliRosterbulkdata(Packet * pak,const char * name,UWORD tag,UWORD id,UWORD type)362 static void SnacCliRosterbulkdata (Packet *pak, const char *name, UWORD tag, UWORD id, UWORD type)
363 {
364 PacketWriteStrB (pak, name);
365 PacketWriteB2 (pak, tag);
366 PacketWriteB2 (pak, id);
367 PacketWriteB2 (pak, type);
368 PacketWriteBLen (pak);
369 }
370
SnacCliRosterbulkone(Server * serv,ContactGroup * cg,Contact * cont,Packet * pak,UWORD type,UWORD subtype)371 static void SnacCliRosterbulkone (Server *serv, ContactGroup *cg, Contact *cont, Packet *pak, UWORD type, UWORD subtype)
372 {
373 UWORD tag = 0;
374 ContactIDs *ids;
375
376 if (type == roster_normal && (ids = ContactIDHas (cont, roster_normal)) && ids->issbl)
377 tag = ids->tag;
378 else if (type == roster_group || type == roster_normal)
379 tag = ContactGroupID (cg);
380
381 SnacCliRosterbulkdata (pak, type == roster_group ? cg->name : cont->screen, tag,
382 type == roster_group ? 0 : ContactIDGet (cont, type), type);
383 if (type == roster_normal && subtype != 10)
384 {
385 PacketWriteTLVStr (pak, TLV_NICK, cont->nick);
386 if (ContactPrefVal (cont, CO_ASK_SBL))
387 {
388 PacketWriteTLV (pak, TLV_REQAUTH);
389 PacketWriteTLVDone (pak);
390 }
391 }
392 else if (type == roster_group && subtype == 9)
393 {
394 Contact *cont;
395 int i;
396 PacketWriteTLV (pak, TLV_GROUPITEMS);
397 for (i = 0; (cont = ContactIndex (cg, i)); i++)
398 if (cont->group == cg)
399 PacketWriteB2 (pak, ContactIDGet (cont, roster_normal));
400 PacketWriteTLVDone (pak);
401 }
402 PacketWriteBLenDone (pak);
403 QueueEnqueueData (serv->conn, QUEUE_CHANGE_ROSTER, pak->ref, 0x7fffffffL, NULL, cont, NULL, NULL);
404 }
405
SnacCliRosterbulkadd(Server * serv,ContactGroup * cs)406 void SnacCliRosterbulkadd (Server *serv, ContactGroup *cs)
407 {
408 Packet *pak;
409 Contact *cont;
410 ContactGroup *cg;
411 int i;
412
413 for (i = 0; (cont = ContactIndex (cs, i)); i++)
414 if (cont->group && cont->group->serv && !ContactGroupPrefVal (cont->group, CO_ISSBL))
415 SnacCliRosteraddgroup (serv, cont->group, 3);
416
417 SnacCliAddstart (serv);
418 pak = SnacC (serv, 19, 8, 0, 0);
419
420 for (i = 0; (cont = ContactIndex (cs, i)); i++)
421 {
422 if (!(cg = cont->group))
423 continue;
424
425 if (i && !(i % 64))
426 {
427 SnacSend (serv, pak);
428 pak = SnacC (serv, 19, 8, 0, 0);
429 }
430
431 SnacCliRosterbulkone (serv, cg, cont, pak, roster_normal, 8);
432
433 if (ContactPrefVal (cont, CO_HIDEFROM))
434 {
435 i++;
436 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_invisible, 8);
437 }
438 if (ContactPrefVal (cont, CO_INTIMATE))
439 {
440 i++;
441 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_visible, 8);
442 }
443 if (ContactPrefVal (cont, CO_IGNORE))
444 {
445 i++;
446 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_ignore, 8);
447 }
448 }
449 SnacSend (serv, pak);
450 SnacCliAddend (serv);
451 }
452
453 /*
454 * CLI_ADDBUDDY - SNAC(13,8)
455 */
SnacCliRosterentryadd(Server * serv,const char * name,UWORD tag,UWORD id,UWORD type,UWORD tlv,void * data,UWORD len)456 void SnacCliRosterentryadd (Server *serv, const char *name, UWORD tag, UWORD id, UWORD type, UWORD tlv, void *data, UWORD len)
457 {
458 Packet *pak;
459
460 SnacCliAddstart (serv);
461 pak = SnacC (serv, 19, 8, 0, 0);
462 SnacCliRosterbulkdata (pak, name, tag, id, type);
463 if (tlv)
464 PacketWriteTLVData (pak, tlv, data, len);
465 PacketWriteBLenDone (pak);
466 SnacSend (serv, pak);
467 SnacCliAddend (serv);
468 }
469
SnacCliRosteraddgroup(Server * serv,ContactGroup * cg,int mode)470 void SnacCliRosteraddgroup (Server *serv, ContactGroup *cg, int mode)
471 {
472 Packet *pak;
473 assert (cg);
474
475 if (mode & 1)
476 SnacCliAddstart (serv);
477 pak = SnacC (serv, 19, 8, 0, 0);
478 SnacCliRosterbulkone (serv, cg, NULL, pak, roster_group, 8);
479 SnacSend (serv, pak);
480 OptSetVal (&cg->copts, CO_ISSBL, 1);
481 if (mode & 2)
482 SnacCliAddend (serv);
483 }
484
SnacCliRosteraddcontact(Server * serv,Contact * cont,int mode)485 void SnacCliRosteraddcontact (Server *serv, Contact *cont, int mode)
486 {
487 Packet *pak;
488 assert (cont);
489
490 if (mode & 1)
491 SnacCliAddstart (serv);
492 if (!ContactGroupPrefVal (cont->group, CO_ISSBL))
493 SnacCliRosteraddgroup (serv, cont->group, 0);
494 pak = SnacC (serv, 19, 8, 0, 0);
495 OptSetVal (&cont->copts, CO_ASK_SBL, 1);
496 SnacCliRosterbulkone (serv, cont->group, cont, pak, roster_normal, 8);
497 if (ContactPrefVal (cont, CO_HIDEFROM))
498 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_invisible, 8);
499 if (ContactPrefVal (cont, CO_INTIMATE))
500 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_visible, 8);
501 if (ContactPrefVal (cont, CO_IGNORE))
502 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_ignore, 8);
503 SnacSend (serv, pak);
504 if (mode & 2)
505 SnacCliAddend (serv);
506 }
507
508 /*
509 * CLI_ROSTERUPDATE - SNAC(13,9)
510 */
SnacCliRosterupdategroup(Server * serv,ContactGroup * cg,int mode)511 void SnacCliRosterupdategroup (Server *serv, ContactGroup *cg, int mode)
512 {
513 Packet *pak;
514 assert (cg);
515
516 if (mode & 1)
517 SnacCliAddstart (serv);
518 pak = SnacC (serv, 19, 9, 0, 0);
519 SnacCliRosterbulkone (serv, cg, NULL, pak, roster_group, 9);
520 SnacSend (serv, pak);
521 if (mode & 2)
522 SnacCliAddend (serv);
523 }
524
SnacCliRosterupdatecontact(Server * serv,Contact * cont,int mode)525 void SnacCliRosterupdatecontact (Server *serv, Contact *cont, int mode)
526 {
527 Packet *pak;
528 assert (cont);
529
530 if (mode & 1)
531 SnacCliAddstart (serv);
532 if (!ContactGroupPrefVal (cont->group, CO_ISSBL))
533 SnacCliRosteraddgroup (serv, cont->group, 0);
534 pak = SnacC (serv, 19, 9, 0, 0);
535 SnacCliRosterbulkone (serv, cont->group, cont, pak, roster_normal, 9);
536 if (ContactPrefVal (cont, CO_HIDEFROM))
537 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_invisible, 9);
538 if (ContactPrefVal (cont, CO_INTIMATE))
539 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_visible, 9);
540 if (ContactPrefVal (cont, CO_IGNORE))
541 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_ignore, 9);
542 SnacSend (serv, pak);
543 if (mode & 2)
544 SnacCliAddend (serv);
545 }
546
SnacCliRostermovecontact(Server * serv,Contact * cont,ContactGroup * cg,int mode)547 void SnacCliRostermovecontact (Server *serv, Contact *cont, ContactGroup *cg, int mode)
548 {
549 Packet *pakd, *paka;
550 ContactIDs *ids;
551 char is, want;
552 is = ContactPrefVal (cont, CO_ISSBL);
553 want = ContactPrefVal (cont, CO_WANTSBL);
554
555 if (!is && !want && mode == 3)
556 return;
557
558 if (mode & 1)
559 SnacCliAddstart (serv);
560
561 if (!ContactGroupPrefVal (cg, CO_ISSBL))
562 SnacCliRosteraddgroup (serv, cg, 0);
563
564 pakd = SnacC (serv, 19, 10, 0, 0);
565 paka = SnacC (serv, 19, 8, 0, 0);
566
567 if (cont->ids && (ids = ContactIDHas (cont, roster_normal)) && ids->issbl)
568 SnacCliRosterbulkone (serv, cont->group, cont, pakd, roster_normal, 10);
569 cont->group = cg;
570 if (want)
571 SnacCliRosterbulkone (serv, cont->group, cont, paka, roster_normal, 8);
572
573 SnacSend (serv, pakd);
574 SnacSend (serv, paka);
575
576 if (mode & 2)
577 SnacCliAddend (serv);
578 }
579
SnacCliRosterbulkmove(Server * serv,ContactGroup * cg,int mode)580 void SnacCliRosterbulkmove (Server *serv, ContactGroup *cg, int mode)
581 {
582 Packet *pakd, *paka;
583 Contact *cont;
584 ContactIDs *ids;
585 int i;
586
587 if (!ContactIndex (cg, 0) && mode == 3)
588 return;
589
590 if (mode & 1)
591 SnacCliAddstart (serv);
592
593 for (i = 0; (cont = ContactIndex (cg, i)); i++)
594 if (!ContactGroupPrefVal (cont->group, CO_ISSBL))
595 SnacCliRosteraddgroup (serv, cont->group, 0);
596
597 pakd = SnacC (serv, 19, 10, 0, 0);
598 paka = SnacC (serv, 19, 8, 0, 0);
599
600 for (i = 0; (cont = ContactIndex (cg, i)); i++)
601 {
602 if (cont->ids && (ids = ContactIDHas (cont, roster_normal)) && ids->issbl)
603 SnacCliRosterbulkone (serv, cont->group, cont, pakd, roster_normal, 10);
604 if (ContactPrefVal (cont, CO_WANTSBL))
605 SnacCliRosterbulkone (serv, cont->group, cont, paka, roster_normal, 8);
606 }
607 SnacSend (serv, pakd);
608 SnacSend (serv, paka);
609
610 if (mode & 2)
611 SnacCliAddend (serv);
612 }
613
614 /*
615 * SRV_ROSTERADD
616 */
JUMP_SNAC_F(SnacSrvRosteradd)617 JUMP_SNAC_F(SnacSrvRosteradd)
618 {
619 }
620
621 /*
622 * SRV_ROSTERUPDATE
623 */
JUMP_SNAC_F(SnacSrvRosterupdate)624 JUMP_SNAC_F(SnacSrvRosterupdate)
625 {
626 Server *serv = event->conn->serv;
627 Packet *pak = event->pak;
628 Contact *cont;
629 UWORD tag, id, type, TLVlen;
630 TLV *tlv;
631 strc_t cname;
632 UWORD j;
633
634 cname = PacketReadB2Str (pak, NULL);
635 tag = PacketReadB2 (pak); /* TAG */
636 id = PacketReadB2 (pak); /* ID */
637 type = PacketReadB2 (pak); /* TYPE */
638 TLVlen = PacketReadB2 (pak); /* TLV length */
639 tlv = TLVRead (pak, TLVlen, -1);
640
641 if (type == roster_normal)
642 {
643 cont = ContactScreen (serv, cname->txt);
644 j = TLVGet (tlv, TLV_NICK);
645 assert (j < 200 || j == (UWORD)-1);
646 if (j != (UWORD)-1 && tlv[j].str.len)
647 ContactAddAlias (cont, ConvFromServ (&tlv[j].str));
648 }
649
650 TLVD (tlv);
651
652 if (pak->rpos < pak->len)
653 SnacSrvUnknown (event);
654 }
655
656 /*
657 * SRV_ROSTERDELETE
658 */
JUMP_SNAC_F(SnacSrvRosterdelete)659 JUMP_SNAC_F(SnacSrvRosterdelete)
660 {
661 }
662
JUMP_SNAC_F(cb_LoginVisibilitySet)663 static JUMP_SNAC_F(cb_LoginVisibilitySet)
664 {
665 UWORD err;
666
667 if (!event->pak)
668 {
669 EventD (event);
670 return;
671 }
672 if (event->pak->ref != 19) /* family */
673 return;
674 if (event->pak->cmd != 14) /* command */
675 return;
676
677 err = PacketReadB2 (event->pak);
678 PacketD (event->pak);
679 event->pak = NULL;
680
681 if (err)
682 rl_printf (i18n (2325, "Warning: server based contact list change failed with error code %d.\n"), err);
683 }
684
685 /*
686 * CLI_ROSTERADD/UPDATE - SNAC(13,9)
687 */
SnacCliSetvisibility(Server * serv,char value,char islogin)688 void SnacCliSetvisibility (Server *serv, char value, char islogin)
689 {
690 Packet *pak;
691
692 if (serv->oscar_privacy_tag)
693 {
694 pak = SnacC (serv, 19, 9, 0, 0);
695 SnacCliRosterbulkdata (pak, "", 0, serv->oscar_privacy_tag, roster_visibility);
696 PacketWriteTLV (pak, TLV_PRIVACY);
697 PacketWrite1 (pak, value);
698 PacketWriteTLVDone (pak);
699 PacketWriteBLenDone (pak);
700 SnacSendR (serv, pak, cb_LoginVisibilitySet, NULL);
701 serv->oscar_privacy_value = value;
702 }
703 else
704 {
705 serv->oscar_privacy_tag = rand () % 0x8000;
706 SnacCliRosterentryadd (serv, "", 0, serv->oscar_privacy_tag, roster_visibility, TLV_PRIVACY, &value, 1);
707 serv->oscar_privacy_value = value;
708 }
709 }
710
711 /*
712 * CLI_ROSTERUPDATE - SNAC(13,9)
713 */
SnacCliSetlastupdate(Server * serv)714 void SnacCliSetlastupdate (Server *serv)
715 {
716 Packet *pak;
717
718 pak = SnacC (serv, 19, 9, 0, 0);
719 SnacCliRosterbulkdata (pak, "LastUpdateDate", 0, 0x4141, roster_lastupd);
720 PacketWriteTLV (pak, TLV_LASTUPD);
721 PacketWrite4 (pak, time (NULL));
722 PacketWriteTLVDone (pak);
723 PacketWriteBLenDone (pak);
724 SnacSend (serv, pak);
725 }
726
727 /*
728 * CLI_ROSTERDELETE - SNAC(13,a)
729 */
SnacCliRosterdeletegroup(Server * serv,ContactGroup * cg,int mode)730 void SnacCliRosterdeletegroup (Server *serv, ContactGroup *cg, int mode)
731 {
732 Packet *pak;
733
734 if (mode & 1)
735 SnacCliAddstart (serv);
736 if (cg->id)
737 {
738 pak = SnacC (serv, 19, 10, 0, 0);
739 SnacCliRosterbulkone (serv, cg, NULL, pak, roster_group, 10);
740 SnacSend (serv, pak);
741 }
742 if (mode & 2)
743 SnacCliAddend (serv);
744 }
745
746 /*
747 * CLI_ROSTERDELETE - SNAC(13,a)
748 */
SnacCliRosterdeletecontact(Server * serv,Contact * cont,int mode)749 void SnacCliRosterdeletecontact (Server *serv, Contact *cont, int mode)
750 {
751 Packet *pak;
752 ContactIDs *ids;
753
754 if (mode & 1)
755 SnacCliAddstart (serv);
756 if (cont->ids)
757 {
758 pak = SnacC (serv, 19, 10, 0, 0);
759 if ((ids = ContactIDHas (cont, roster_normal)) && ids->issbl)
760 SnacCliRosterbulkone (serv, cont->group, cont, pak, roster_normal, 10);
761 if ((ids = ContactIDHas (cont, roster_invisible)) && ids->issbl)
762 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_invisible, 10);
763 if ((ids = ContactIDHas (cont, roster_visible)) && ids->issbl)
764 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_visible, 10);
765 if ((ids = ContactIDHas (cont, roster_ignore)) && ids->issbl)
766 SnacCliRosterbulkone (serv, NULL, cont, pak, roster_ignore, 10);
767 SnacSend (serv, pak);
768 }
769 if (mode & 2)
770 SnacCliAddend (serv);
771 }
772
773 /*
774 * CLI_ROSTERDELETE - SNAC(13,a)
775 */
SnacCliRosterentrydelete(Server * serv,RosterEntry * re)776 void SnacCliRosterentrydelete (Server *serv, RosterEntry *re)
777 {
778 Packet *pak;
779 int i;
780
781 SnacCliAddstart (serv);
782 pak = SnacC (serv, 19, 10, 0, 0);
783 SnacCliRosterbulkdata (pak, re->name, re->tag, re->id, re->type);
784 for (i = 0; i < 16 || re->tlv[i].tag; i++)
785 if (re->tlv[i].tag)
786 PacketWriteTLVData (pak, re->tlv[i].tag, re->tlv[i].str.txt, re->tlv[i].str.len);
787 PacketWriteBLenDone (pak);
788 SnacSend (serv, pak);
789 SnacCliAddend (serv);
790 }
791
SnacCliRosterdelete(Server * serv,const char * name,UWORD tag,UWORD id,roster_t type)792 void SnacCliRosterdelete (Server *serv, const char *name, UWORD tag, UWORD id, roster_t type)
793 {
794 Packet *pak;
795
796 SnacCliAddstart (serv);
797 pak = SnacC (serv, 19, 10, 0, 0);
798 SnacCliRosterbulkdata (pak, name, tag, id, type);
799 PacketWriteBLenDone (pak);
800 SnacSend (serv, pak);
801 SnacCliAddend (serv);
802 }
803
804 /*
805 * SRV_UPDATEACK - SNAC(13,e)
806 */
JUMP_SNAC_F(SnacSrvUpdateack)807 JUMP_SNAC_F(SnacSrvUpdateack)
808 {
809 Server *serv = event->conn->serv;
810 Contact *cont = NULL;
811 Event *event2;
812 UWORD err;
813
814 if (!PacketReadLeft (event->pak))
815 return;
816
817 err = PacketReadB2 (event->pak);
818 SnacSrvUpdateack (event);
819
820 event2 = QueueDequeue (serv->conn, QUEUE_CHANGE_ROSTER, event->pak->ref);
821 cont = event2 ? event2->cont : NULL;
822
823 switch (err)
824 {
825 case 0xe:
826 if (cont)
827 {
828 OptSetVal (&cont->copts, CO_ASK_SBL, 1);
829 OptSetVal (&cont->copts, CO_TO_SBL, 0);
830 OptSetVal (&cont->copts, CO_FROM_SBL, 0);
831 OptSetVal (&cont->copts, CO_ISSBL, 0);
832 SnacCliRosteraddcontact (serv, cont, 3);
833 }
834 break;
835 case 10:
836 if (cont)
837 {
838 OptSetVal (&cont->copts, CO_ASK_SBL, 1);
839 OptSetVal (&cont->copts, CO_TO_SBL, 0);
840 OptSetVal (&cont->copts, CO_FROM_SBL, 0);
841 OptSetVal (&cont->copts, CO_ISSBL, 0);
842 rl_printf (i18n (2565, "Contact upload for %s%s%s failed, authorization required.\n"),
843 COLCONTACT, s_quote (cont->nick), COLNONE);
844 }
845 else
846 rl_printf (i18n (2537, "Contact upload failed, authorization required.\n"));
847 break;
848 case 3:
849 if (cont)
850 {
851 rl_printf (i18n (2566, "Contact upload for %s%s%s failed, already on server.\n"),
852 COLCONTACT, s_quote (cont->nick), COLNONE);
853 }
854 else
855 rl_printf (i18n (2538, "Contact upload failed, already on server.\n"));
856 break;
857 case 0:
858 if (cont)
859 {
860 OptSetVal (&cont->copts, CO_ISSBL, 1);
861 if (!ContactPrefVal (cont, CO_ASK_SBL))
862 {
863 OptSetVal (&cont->copts, CO_TO_SBL, 1);
864 OptSetVal (&cont->copts, CO_FROM_SBL, 1);
865 }
866 rl_printf (i18n (2567, "Contact upload for %s%s%s succeeded.\n"),
867 COLCONTACT, s_quote (cont->nick), COLNONE);
868 }
869 else
870 rl_printf (i18n (2539, "Contact upload succeeded.\n"));
871 break;
872 default:
873 rl_printf (i18n (2325, "Warning: server based contact list change failed with error code %d.\n"), err);
874 }
875 if (event2)
876 EventD (event2);
877 }
878
879 /*
880 * SRV_ROSTEROK - SNAC(13,f)
881 */
JUMP_SNAC_F(SnacSrvRosterok)882 JUMP_SNAC_F(SnacSrvRosterok)
883 {
884 /* ignore */
885 Server *serv;
886 Packet *pak;
887 Event *event2;
888 Roster *roster;
889 UWORD count;
890 time_t stmp;
891
892 if (!event)
893 return;
894
895 serv = event->conn->serv;
896 if (!serv)
897 return;
898
899 pak = event->pak;
900 if (!pak)
901 return;
902
903 event2 = QueueDequeue2 (serv->conn, QUEUE_REQUEST_ROSTER, 0, 0);
904 if (!event2 || !event2->callback)
905 {
906 DebugH (DEB_PROTOCOL, "Unrequested roster packet received.\n");
907 return;
908 }
909
910 roster = event2->data;
911 if (!roster)
912 {
913 roster = OscarRosterC ();
914 event2->data = roster;
915 }
916
917 PacketRead1 (pak);
918 count = PacketReadB2 (pak); /* COUNT */
919 stmp = PacketReadB4 (pak);
920
921 #if 0
922 if (!roster->import)
923 {
924 time_t now = time (NULL);
925 UDWORD da = now;
926 SnacCliRosterentryadd (serv, "ImportTime", 0, 1, roster_importt, TLV_IMPORT, &da, 4);
927 }
928 if (!roster->ICQTIC)
929 SnacCliRosterentryadd (serv, "ICQTIC", 0, 2, roster_icqtic, TLV_ICQTIC, "3608,0,0,0,60,null", 18);
930 if (!serv->oscar_privacy_tag)
931 {
932 serv->oscar_privacy_tag = rand () % 0x8000;
933 SnacCliRosterentryadd (serv, "", 0, serv->oscar_privacy_tag, roster_visibility, TLV_PRIVACY, "\x03", 1);
934 serv->oscar_privacy_value = 3;
935 }
936 #endif
937 if (~serv->conn->connect & CONNECT_OK)
938 CliFinishLogin (serv);
939
940 SnacCliRosterack (serv);
941 event2->callback (event2);
942 }
943
944 /*
945 * SRV_ADDSTART
946 */
JUMP_SNAC_F(SnacSrvAddstart)947 JUMP_SNAC_F(SnacSrvAddstart)
948 {
949 if (event->pak->rpos < event->pak->len)
950 SnacSrvUnknown (event);
951 }
952
953 /*
954 * SRV_ADDEND
955 */
JUMP_SNAC_F(SnacSrvAddend)956 JUMP_SNAC_F(SnacSrvAddend)
957 {
958 if (event->pak->rpos < event->pak->len)
959 SnacSrvUnknown (event);
960 }
961
962
963 /*
964 * CLI_ADDSTART - SNAC(13,11)
965 */
SnacCliAddstart(Server * serv)966 void SnacCliAddstart (Server *serv)
967 {
968 Packet *pak;
969
970 pak = SnacC (serv, 19, 17, 0, 0);
971 SnacSend (serv, pak);
972 }
973
974 /*
975 * CLI_ADDEND - SNAC(13,12)
976 */
SnacCliAddend(Server * serv)977 void SnacCliAddend (Server *serv)
978 {
979 Packet *pak;
980
981 pak = SnacC (serv, 19, 18, 0, 0);
982 SnacSend (serv, pak);
983 }
984
985 /*
986 * CLI_GRANTAUTH - SNAC(13,14)
987 */
SnacCliGrantauth(Server * serv,Contact * cont)988 void SnacCliGrantauth (Server *serv, Contact *cont)
989 {
990 Packet *pak;
991
992 if (!cont)
993 return;
994 pak = SnacC (serv, 19, 20, 0, 0);
995 PacketWriteCont (pak, cont);
996 PacketWrite4 (pak, 0);
997 SnacSend (serv, pak);
998 }
999
1000 /*
1001 * CLI_REQAUTH - SNAC(13,18)
1002 */
SnacCliReqauth(Server * serv,Contact * cont,const char * msg)1003 void SnacCliReqauth (Server *serv, Contact *cont, const char *msg)
1004 {
1005 Packet *pak;
1006
1007 if (!cont)
1008 return;
1009 pak = SnacC (serv, 19, 24, 0, 0);
1010 PacketWriteCont (pak, cont);
1011 PacketWriteStrB (pak, c_out_to (msg, cont));
1012 PacketWrite2 (pak, 0);
1013 SnacSend (serv, pak);
1014 }
1015
1016 /*
1017 * SRV_AUTHREQ - SNAC(13,19)
1018 */
JUMP_SNAC_F(SnacSrvAuthreq)1019 JUMP_SNAC_F(SnacSrvAuthreq)
1020 {
1021 Server *serv = event->conn->serv;
1022 Packet *pak;
1023 Contact *cont;
1024 strc_t ctext;
1025 char *text;
1026
1027 pak = event->pak;
1028 cont = PacketReadCont (pak, serv);
1029 ctext = PacketReadB2Str (pak, NULL);
1030
1031 if (!cont)
1032 return;
1033
1034 text = strdup (c_in_to_split (ctext, cont));
1035 IMSrvMsg (cont, NOW, CV_ORIGIN_v8, MSG_AUTH_REQ, text);
1036 free (text);
1037 }
1038
1039 /*
1040 * CLI_AUTHORIZE - SNAC(13,1a)
1041 */
SnacCliAuthorize(Server * serv,Contact * cont,BOOL accept,const char * msg)1042 void SnacCliAuthorize (Server *serv, Contact *cont, BOOL accept, const char *msg)
1043 {
1044 Packet *pak;
1045
1046 if (!cont)
1047 return;
1048 pak = SnacC (serv, 19, 26, 0, 0);
1049 PacketWriteCont (pak, cont);
1050 PacketWrite1 (pak, accept ? 1 : 0);
1051 PacketWriteStrB (pak, accept ? "" : c_out_to (msg, cont));
1052 SnacSend (serv, pak);
1053 }
1054
1055 /*
1056 * SRV_AUTHREPLY - SNAC(13,1b)
1057 */
JUMP_SNAC_F(SnacSrvAuthreply)1058 JUMP_SNAC_F(SnacSrvAuthreply)
1059 {
1060 Server *serv = event->conn->serv;
1061 Packet *pak;
1062 Contact *cont;
1063 strc_t ctext;
1064 char *text;
1065 UBYTE acc;
1066
1067 pak = event->pak;
1068 cont = PacketReadCont (pak, serv);
1069 acc = PacketRead1 (pak);
1070 ctext = PacketReadB2Str (pak, NULL);
1071
1072 if (!cont)
1073 return;
1074
1075 text = strdup (c_in_to_split (ctext, cont));
1076 IMSrvMsg (cont, NOW, CV_ORIGIN_v8, acc ? MSG_AUTH_GRANT : MSG_AUTH_DENY, text);
1077 free (text);
1078 }
1079
1080 /*
1081 * SRV_ADDEDYOU - SNAC(13,1c)
1082 */
JUMP_SNAC_F(SnacSrvAddedyou)1083 JUMP_SNAC_F(SnacSrvAddedyou)
1084 {
1085 Contact *cont;
1086
1087 cont = PacketReadCont (event->pak, event->conn->serv);
1088 IMSrvMsg (cont, NOW, CV_ORIGIN_v8, MSG_AUTH_ADDED, "");
1089 }
1090