]>
Commit | Line | Data |
---|---|---|
fa684c51 | 1 | |
2 | ||
3 | #include <faim/aim.h> | |
4 | ||
5 | void parser_icbm_incoming(u_char *data, int len) | |
6 | { | |
7 | struct aim_userinfo_s userinfo; | |
8 | u_int i = 0, j = 0, y = 0, z = 0; | |
9 | char *msg = NULL; | |
10 | u_int icbmflags = 0; | |
11 | u_char cookie[8]; | |
12 | int channel; | |
13 | struct aim_tlvlist_t *tlvlist; | |
14 | struct aim_tlv_t *msgblocktlv, *tmptlv; | |
15 | u_char *msgblock; | |
16 | u_short wastebits; | |
17 | u_short flag1,flag2; | |
18 | ||
19 | memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s)); | |
20 | ||
21 | i = 0; | |
22 | /* | |
23 | * Read ICBM Cookie. And throw away. | |
24 | */ | |
25 | for (z=0; z<8; z++,i++) | |
26 | cookie[z] = data[i]; | |
27 | ||
28 | /* | |
29 | * Channel ID. | |
30 | * | |
31 | * Channel 0x0001 is the message channel. There are | |
32 | * other channels for things called "rendevous" | |
33 | * which represent chat and some of the other new | |
34 | * features of AIM2/3/3.5. We only support | |
35 | * standard messages; those on channel 0x0001. | |
36 | */ | |
37 | channel = aimutil_get16(data+i); | |
38 | i += 2; | |
39 | if (channel != 0x0001) | |
40 | { | |
41 | printf("faim: icbm: ICBM received on an unsupported channel. Ignoring.\n (chan = %04x)", channel); | |
42 | return; | |
43 | } | |
44 | ||
45 | /* | |
46 | * Source screen name. | |
47 | */ | |
48 | memcpy(userinfo.sn, data+i+1, (int)data[i]); | |
49 | userinfo.sn[(int)data[i]] = '\0'; | |
50 | i += 1 + (int)data[i]; | |
51 | ||
52 | /* | |
53 | * Unknown bits. | |
54 | */ | |
55 | wastebits = aimutil_get16(data+i); | |
56 | i += 2; | |
57 | wastebits = aimutil_get16(data+i); | |
58 | i += 2; | |
59 | ||
60 | /* | |
61 | * Read block of TLVs. All further data is derived | |
62 | * from what is parsed here. | |
63 | */ | |
64 | tlvlist = aim_readtlvchain(data+i, len-i); | |
65 | ||
66 | /* | |
67 | * Check Autoresponse status. If it is an autoresponse, | |
68 | * it will contain a second type 0x0004 TLV, with zero length. | |
69 | */ | |
70 | if (aim_gettlv(tlvlist, 0x0004, 2)) | |
71 | icbmflags |= AIM_IMFLAGS_AWAY; | |
72 | ||
73 | /* | |
74 | * Check Ack Request status. | |
75 | */ | |
76 | if (aim_gettlv(tlvlist, 0x0003, 2)) | |
77 | icbmflags |= AIM_IMFLAGS_ACK; | |
78 | ||
79 | /* | |
80 | * Extract the various pieces of the userinfo struct. | |
81 | */ | |
82 | /* Class. */ | |
83 | if ((tmptlv = aim_gettlv(tlvlist, 0x0001, 1))) | |
84 | userinfo.class = aimutil_get16(tmptlv->value); | |
85 | /* Member-since date. */ | |
86 | if ((tmptlv = aim_gettlv(tlvlist, 0x0002, 1))) | |
87 | { | |
88 | /* If this is larger than 4, its probably the message block, skip */ | |
89 | if (tmptlv->length <= 4) | |
90 | userinfo.membersince = aimutil_get32(tmptlv->value); | |
91 | } | |
92 | /* On-since date */ | |
93 | if ((tmptlv = aim_gettlv(tlvlist, 0x0003, 1))) | |
94 | userinfo.onlinesince = aimutil_get32(tmptlv->value); | |
95 | /* Idle-time */ | |
96 | if ((tmptlv = aim_gettlv(tlvlist, 0x0004, 1))) | |
97 | userinfo.idletime = aimutil_get16(tmptlv->value); | |
98 | /* Session Length (AIM) */ | |
99 | if ((tmptlv = aim_gettlv(tlvlist, 0x000f, 1))) | |
100 | userinfo.sessionlen = aimutil_get16(tmptlv->value); | |
101 | /* Session Length (AOL) */ | |
102 | if ((tmptlv = aim_gettlv(tlvlist, 0x0010, 1))) | |
103 | userinfo.sessionlen = aimutil_get16(tmptlv->value); | |
104 | ||
105 | /* | |
106 | * Message block. | |
107 | * | |
108 | * XXX: Will the msgblock always be the second 0x0002? | |
109 | */ | |
110 | msgblocktlv = aim_gettlv(tlvlist, 0x0002, 1); | |
111 | if (!msgblocktlv) | |
112 | { | |
113 | printf("faim: icbm: major error! no message block TLV found!\n"); | |
114 | aim_freetlvchain(&tlvlist); | |
115 | } | |
116 | ||
117 | /* | |
118 | * Extracting the message from the unknown cruft. | |
119 | * | |
120 | * This is a bit messy, and I'm not really qualified, | |
121 | * even as the author, to comment on it. At least | |
122 | * its not as bad as a while loop shooting into infinity. | |
123 | * | |
124 | * "Do you believe in magic?" | |
125 | * | |
126 | */ | |
127 | msgblock = msgblocktlv->value; | |
128 | j = 0; | |
129 | ||
130 | wastebits = aimutil_get8(msgblock+j++); | |
131 | wastebits = aimutil_get8(msgblock+j++); | |
132 | ||
133 | y = aimutil_get16(msgblock+j); | |
134 | j += 2; | |
135 | for (z = 0; z < y; z++) | |
136 | wastebits = aimutil_get8(msgblock+j++); | |
137 | wastebits = aimutil_get8(msgblock+j++); | |
138 | wastebits = aimutil_get8(msgblock+j++); | |
139 | ||
140 | /* | |
141 | * Message string length, including flag words. | |
142 | */ | |
143 | i = aimutil_get16(msgblock+j); | |
144 | j += 2; | |
145 | ||
146 | /* | |
147 | * Flag words. | |
148 | * | |
149 | * Its rumored that these can kick in some funky | |
150 | * 16bit-wide char stuff that used to really kill | |
151 | * libfaim. Hopefully the latter is no longer true. | |
152 | * | |
153 | * Though someone should investiagte the former. | |
154 | * | |
155 | */ | |
156 | flag1 = aimutil_get16(msgblock+j); | |
157 | j += 2; | |
158 | flag2 = aimutil_get16(msgblock+j); | |
159 | j += 2; | |
160 | ||
161 | if (flag1 || flag2) | |
162 | printf("faim: icbm: **warning: encoding flags are being used! {%04x, %04x}\n", flag1, flag2); | |
163 | ||
164 | /* | |
165 | * Message string. | |
166 | */ | |
167 | i -= 4; | |
168 | msg = (char *)malloc(i+1); | |
169 | memcpy(msg, msgblock+j, i); | |
170 | msg[i] = '\0'; | |
171 | ||
172 | /* | |
173 | * Free up the TLV chain. | |
174 | */ | |
175 | aim_freetlvchain(&tlvlist); | |
176 | ||
177 | printf("ICBM:\n"); | |
178 | printf("\tChannel:\t0x%04x\n", channel); | |
179 | printf("\tSource:\t%s\n", userinfo.sn); | |
180 | printf("\tICBM Flags:\t%s %s\n", | |
181 | (icbmflags & AIM_IMFLAGS_AWAY)?"Away":"", | |
182 | (icbmflags & AIM_IMFLAGS_ACK)?"Ack":""); | |
183 | printf("\tEncoding Flags:\t{0x%02x, 0x%02x}\n", flag1, flag2); | |
184 | printf("\tMessage:\n"); | |
185 | printf("\t\t%s\n", msg); | |
186 | ||
187 | free(msg); | |
188 | ||
189 | return; | |
190 | } |