]> andersk Git - libfaim.git/blob - aim_chatnav.c
- Thu Feb 8 20:12:39 UTC 2001
[libfaim.git] / aim_chatnav.c
1 /*
2  * Handle ChatNav.
3  *
4  * [The ChatNav(igation) service does various things to keep chat
5  *  alive.  It provides room information, room searching and creating, 
6  *  as well as giving users the right ("permission") to use chat.]
7  *
8  */
9
10 #define FAIM_INTERNAL
11 #include <faim/aim.h>
12
13 /*
14  * conn must be a chatnav connection!
15  */
16 faim_export unsigned long aim_chatnav_reqrights(struct aim_session_t *sess,
17                                                 struct aim_conn_t *conn)
18 {
19   aim_genericreq_n(sess, conn, 0x000d, 0x0002);
20
21   return sess->snac_nextid;
22 }
23
24 faim_export unsigned long aim_chatnav_clientready(struct aim_session_t *sess,
25                                                   struct aim_conn_t *conn)
26 {
27   struct command_tx_struct *newpacket; 
28   int i;
29
30   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 0x20)))
31     return -1;
32
33   newpacket->lock = 1;
34
35   i = aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
36
37   i+= aimutil_put16(newpacket->data+i, 0x000d);
38   i+= aimutil_put16(newpacket->data+i, 0x0001);
39
40   i+= aimutil_put16(newpacket->data+i, 0x0004);
41   i+= aimutil_put16(newpacket->data+i, 0x0001);
42
43   i+= aimutil_put16(newpacket->data+i, 0x0001);
44   i+= aimutil_put16(newpacket->data+i, 0x0003);
45
46   i+= aimutil_put16(newpacket->data+i, 0x0004);
47   i+= aimutil_put16(newpacket->data+i, 0x0686);
48
49   aim_tx_enqueue(sess, newpacket);
50
51   return (sess->snac_nextid++);
52 }
53
54 /*
55  * Since multiple things can trigger this callback,
56  * we must lookup the snacid to determine the original
57  * snac subtype that was called.
58  */
59 faim_internal int aim_chatnav_parse_info(struct aim_session_t *sess, struct command_rx_struct *command)
60 {
61   struct aim_snac_t *snac;
62   u_long snacid;
63   rxcallback_t userfunc;
64   int ret=1;
65   
66   snacid = aimutil_get32(command->data+6);
67   snac = aim_remsnac(sess, snacid);
68
69   if (!snac)
70     {
71       printf("faim: chatnav_parse_info: received response to unknown request! (%08lx)\n", snacid);
72       return 1;
73     }
74   
75   if (snac->family != 0x000d)
76     {
77       printf("faim: chatnav_parse_info: recieved response that maps to corrupt request! (fam=%04x)\n", snac->family);
78       return 1;
79     }
80
81   /*
82    * We now know what the original SNAC subtype was.
83    */
84   switch(snac->type)
85     {
86     case 0x0002: /* request chat rights */
87       {
88           struct aim_tlvlist_t *tlvlist;
89           struct aim_chat_exchangeinfo *exchanges = NULL;
90           int curexchange = 0;
91           struct aim_tlv_t *exchangetlv;
92           u_char maxrooms = 0;
93           struct aim_tlvlist_t *innerlist;
94          
95           tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
96           
97           /* 
98            * Type 0x0002: Maximum concurrent rooms.
99            */ 
100           if (aim_gettlv(tlvlist, 0x0002, 1))
101             maxrooms = aim_gettlv8(tlvlist, 0x0002, 1);
102
103           /* 
104            * Type 0x0003: Exchange information
105            *
106            * There can be any number of these, each one
107            * representing another exchange.  
108            * 
109            */
110           curexchange = 0;
111           while ((exchangetlv = aim_gettlv(tlvlist, 0x0003, curexchange+1)))
112             {   
113               curexchange++;
114               exchanges = realloc(exchanges, curexchange * sizeof(struct aim_chat_exchangeinfo));
115               
116
117               /* exchange number */
118               exchanges[curexchange-1].number = aimutil_get16(exchangetlv->value);
119               innerlist = aim_readtlvchain(exchangetlv->value+2, exchangetlv->length-2);
120               
121               /* 
122                * Type 0x000d: Unknown.
123                */
124               if (aim_gettlv(innerlist, 0x000d, 1))
125                 ;
126               
127               /* 
128                * Type 0x0004: Unknown
129                */
130               if (aim_gettlv(innerlist, 0x0004, 1))
131                 ;
132
133               /* 
134                * Type 0x0002: Unknown
135                */
136               if (aim_gettlv(innerlist, 0x0002, 1)) {
137                 unsigned short classperms;
138
139                 classperms = aim_gettlv16(innerlist, 0x0002, 1);
140                 
141                 printf("faim: class permissions %x\n", classperms);
142               }
143
144               /*
145                * Type 0x00c9: Unknown
146                */ 
147               if (aim_gettlv(innerlist, 0x00c9, 1))
148                 ;
149               
150               /*
151                * Type 0x00ca: Creation Date 
152                */
153               if (aim_gettlv(innerlist, 0x00ca, 1))
154                 ;
155               
156               /*
157                * Type 0x00d0: Mandatory Channels?
158                */
159               if (aim_gettlv(innerlist, 0x00d0, 1))
160                 ;
161
162               /*
163                * Type 0x00d1: Maximum Message length
164                */
165               if (aim_gettlv(innerlist, 0x00d1, 1))
166                 ;
167
168               /*
169                * Type 0x00d2: Maximum Occupancy?
170                */
171               if (aim_gettlv(innerlist, 0x00d2, 1))     
172                 ;       
173
174               /*
175                * Type 0x00d3: Exchange Name
176                */
177               if (aim_gettlv(innerlist, 0x00d3, 1))     
178                 exchanges[curexchange-1].name = aim_gettlv_str(innerlist, 0x00d3, 1);
179               else
180                 exchanges[curexchange-1].name = NULL;
181
182               /*
183                * Type 0x00d5: Creation Permissions
184                *
185                * 0  Creation not allowed
186                * 1  Room creation allowed
187                * 2  Exchange creation allowed
188                * 
189                */
190               if (aim_gettlv(innerlist, 0x00d5, 1)) {
191                 unsigned char createperms;
192
193                 createperms = aim_gettlv8(innerlist, 0x00d5, 1);
194               }
195
196               /*
197                * Type 0x00d6: Character Set (First Time)
198                */             
199               if (aim_gettlv(innerlist, 0x00d6, 1))     
200                 exchanges[curexchange-1].charset1 = aim_gettlv_str(innerlist, 0x00d6, 1);
201               else
202                 exchanges[curexchange-1].charset1 = NULL;
203               
204               /*
205                * Type 0x00d7: Language (First Time)
206                */             
207               if (aim_gettlv(innerlist, 0x00d7, 1))     
208                 exchanges[curexchange-1].lang1 = aim_gettlv_str(innerlist, 0x00d7, 1);
209               else
210                 exchanges[curexchange-1].lang1 = NULL;
211
212               /*
213                * Type 0x00d8: Character Set (Second Time)
214                */             
215               if (aim_gettlv(innerlist, 0x00d8, 1))     
216                 exchanges[curexchange-1].charset2 = aim_gettlv_str(innerlist, 0x00d8, 1);
217               else
218                 exchanges[curexchange-1].charset2 = NULL;
219
220               /*
221                * Type 0x00d9: Language (Second Time)
222                */             
223               if (aim_gettlv(innerlist, 0x00d9, 1))     
224                 exchanges[curexchange-1].lang2 = aim_gettlv_str(innerlist, 0x00d9, 1);
225               else
226                 exchanges[curexchange-1].lang2 = NULL;
227               
228               aim_freetlvchain(&innerlist);
229             }
230           
231           /*
232            * Call client.
233            */
234           userfunc = aim_callhandler(command->conn, 0x000d, 0x0009);
235           if (userfunc)
236             ret = userfunc(sess, 
237                            command, 
238                            snac->type,
239                            maxrooms,
240                            curexchange, 
241                            exchanges);
242           curexchange--;
243           while(curexchange >= 0)
244             {
245               if (exchanges[curexchange].name)
246                 free(exchanges[curexchange].name);
247               if (exchanges[curexchange].charset1)
248                 free(exchanges[curexchange].charset1);
249               if (exchanges[curexchange].lang1)
250                 free(exchanges[curexchange].lang1);
251               if (exchanges[curexchange].charset2)
252                 free(exchanges[curexchange].charset2);
253               if (exchanges[curexchange].lang2)
254                 free(exchanges[curexchange].lang2);
255               curexchange--;
256             }
257           free(exchanges);
258           aim_freetlvchain(&tlvlist);
259           
260           break;
261       }
262     case 0x0003: /* request exchange info */
263       printf("faim: chatnav_parse_info: resposne to exchange info\n");
264       break;
265     case 0x0004: /* request room info */
266       printf("faim: chatnav_parse_info: response to room info\n");
267       break;
268     case 0x0005: /* request more room info */
269       printf("faim: chatnav_parse_info: response to more room info\n");
270       break;
271     case 0x0006: /* request occupant list */
272       printf("faim: chatnav_parse_info: response to occupant info\n");
273       break;
274     case 0x0007: /* search for a room */
275       printf("faim: chatnav_parse_info: search results\n");
276       break;
277     case 0x0008: { /* create room */
278       /*
279         000d 0009 0000 0000 0010 
280         
281         0004 0053 
282              0004 -- exchange
283              0c 7a 6f6f 6f6d 7a6f 6f6f 6d34 32 cookie/name
284              0000 -- instance
285              02 -- detail level
286              0007 -- unknown!
287              006a 000c 7a 6f 6f6f 6d7a 6f6f 6f6d 3432 -- fully qualified name 
288              00c9 0002 0011 -- flags
289              00ca 0004 39c0 0883 -- create time
290              00d1 0002 0200 -- max msg len 
291              00d2 0002 0018 -- max occupants
292              00d3 000c -- name
293                   7a6f 6f6f 6d7a 6f6f 6f6d 3432 
294              00d5 0001 02 -- creation permission
295        */
296       struct aim_tlvlist_t *tlvlist, *innerlist;
297       char *ck = NULL, *fqcn = NULL, *name = NULL;
298       unsigned short exchange, instance, unknown, flags, maxmsglen, maxoccupancy;
299       unsigned long createtime = 0;
300       unsigned char createperms;
301       int i, cklen;
302       struct aim_tlv_t *bigblock;
303
304       i = 10;
305       if (!(tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i))) {
306         printf("faim: unable to read top tlv in create room response\n");
307         break;
308       }
309
310       if (!(bigblock = aim_gettlv(tlvlist, 0x0004, 1))) {
311         printf("faim: no bigblock in top tlv in create room response\n");
312         aim_freetlvchain(&tlvlist);
313         break;
314       }
315       i = 0;
316
317       exchange = aimutil_get16(bigblock->value+i);
318       i += 2;
319
320       cklen = aimutil_get8(bigblock->value+i);
321       i++;
322
323       ck = malloc(cklen+1);
324       memcpy(ck, bigblock->value+i, cklen);
325       ck[cklen] = '\0';
326       i += cklen;
327
328       instance = aimutil_get16(bigblock->value+i);
329       i += 2;
330
331       if (aimutil_get8(bigblock->value+i) != 0x02) {
332         printf("faim: unknown detaillevel in create room response (0x%02x)\n", aimutil_get8(bigblock->value+i));
333         aim_freetlvchain(&tlvlist);
334         free(ck);       
335         break;
336       }
337       i += 1;
338       
339       unknown = aimutil_get16(bigblock->value+i);
340       i += 2;
341
342       if (!(innerlist = aim_readtlvchain(bigblock->value+i, bigblock->length-i))) {
343         printf("faim: unable to read inner tlv chain in create room response\n");
344         aim_freetlvchain(&tlvlist);
345         free(ck);
346         break;
347       }
348
349       if (aim_gettlv(innerlist, 0x006a, 1))
350         fqcn = aim_gettlv_str(innerlist, 0x006a, 1);
351
352       if (aim_gettlv(innerlist, 0x00c9, 1))
353         flags = aim_gettlv16(innerlist, 0x00c9, 1);
354
355       if (aim_gettlv(innerlist, 0x00ca, 1))
356         createtime = aim_gettlv32(innerlist, 0x00ca, 1);
357
358       if (aim_gettlv(innerlist, 0x00d1, 1))
359         maxmsglen = aim_gettlv16(innerlist, 0x00d1, 1);
360
361       if (aim_gettlv(innerlist, 0x00d2, 1))
362         maxoccupancy = aim_gettlv16(innerlist, 0x00d2, 1);
363
364       if (aim_gettlv(innerlist, 0x00d3, 1))
365         name = aim_gettlv_str(innerlist, 0x00d3, 1);
366
367       if (aim_gettlv(innerlist, 0x00d5, 1))
368         createperms = aim_gettlv8(innerlist, 0x00d5, 1);
369
370       if ((userfunc = aim_callhandler(command->conn, 0x000d, 0x0009))) {
371         ret = userfunc(sess, command, snac->type, fqcn, instance, exchange, flags, createtime, maxmsglen, maxoccupancy, createperms, unknown, name, ck);
372       }
373      
374       if (ck)
375         free(ck);
376       if (name)
377         free(name);
378       if (fqcn)
379         free(fqcn);
380       aim_freetlvchain(&innerlist);
381       aim_freetlvchain(&tlvlist);
382
383       break;
384     }
385     default: /* unknown */
386       printf("faim: chatnav_parse_info: unknown request subtype (%04x)\n", snac->type);
387     }
388
389   if (snac && snac->data)
390     free(snac->data);
391   if (snac)
392     free(snac);
393   
394   return ret;
395 }
396
397 faim_export unsigned long aim_chatnav_createroom(struct aim_session_t *sess,
398                                                  struct aim_conn_t *conn,
399                                                  char *name, 
400                                                  u_short exchange)
401 {
402   struct command_tx_struct *newpacket; 
403   int i;
404
405   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+12+strlen("invite")+strlen(name))))
406     return -1;
407
408   newpacket->lock = 1;
409
410   i = aim_putsnac(newpacket->data, 0x000d, 0x0008, 0x0000, sess->snac_nextid);
411
412   /* exchange */
413   i+= aimutil_put16(newpacket->data+i, exchange);
414
415   /* room cookie */
416   i+= aimutil_put8(newpacket->data+i, strlen("invite"));
417   i+= aimutil_putstr(newpacket->data+i, "invite", strlen("invite"));
418
419   /* instance */
420   i+= aimutil_put16(newpacket->data+i, 0xffff);
421   
422   /* detail level */
423   i+= aimutil_put8(newpacket->data+i, 0x01);
424   
425   /* tlvcount */
426   i+= aimutil_put16(newpacket->data+i, 0x0001);
427
428   /* room name */
429   i+= aim_puttlv_str(newpacket->data+i, 0x00d3, strlen(name), name);
430
431   aim_cachesnac(sess, 0x000d, 0x0008, 0x0000, NULL, 0);
432
433   aim_tx_enqueue(sess, newpacket);
434
435   return sess->snac_nextid;
436 }
This page took 0.06849 seconds and 5 git commands to generate.