2
|
1 /*
|
|
2 * aim_im.c
|
|
3 *
|
|
4 * The routines for sending/receiving Instant Messages.
|
|
5 *
|
|
6 */
|
|
7
|
|
8 #include "aim.h"
|
|
9
|
|
10 /*
|
|
11 * Send an ICBM (instant message).
|
|
12 *
|
|
13 *
|
|
14 * Possible flags:
|
|
15 * AIM_IMFLAGS_AWAY -- Marks the message as an autoresponse
|
|
16 * AIM_IMFLAGS_ACK -- Requests that the server send an ack
|
|
17 * when the message is received (of type 0x0004/0x000c)
|
|
18 *
|
|
19 *
|
|
20 * TODO: Update to new standard form
|
|
21 *
|
|
22 *
|
|
23 */
|
|
24
|
|
25 u_long aim_send_im(struct aim_conn_t *conn, char *destsn, int flags, char *msg)
|
|
26 {
|
|
27
|
|
28 int curbyte;
|
|
29 struct command_tx_struct newpacket;
|
|
30
|
|
31 newpacket.lock = 1; /* lock struct */
|
|
32 newpacket.type = 0x02; /* IMs are always family 0x02 */
|
|
33 if (conn)
|
|
34 newpacket.conn = conn;
|
|
35 else
|
|
36 newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
|
|
37
|
|
38 newpacket.commandlen = 20+1+strlen(destsn)+1+1+2+7+2+4+strlen(msg)+2;
|
|
39
|
|
40 if (flags & AIM_IMFLAGS_ACK)
|
|
41 newpacket.commandlen += 4;
|
|
42 if (flags & AIM_IMFLAGS_AWAY)
|
|
43 newpacket.commandlen += 4;
|
|
44
|
|
45 newpacket.data = (char *) calloc(1, newpacket.commandlen);
|
|
46
|
|
47 curbyte = 0;
|
|
48 curbyte += aim_putsnac(newpacket.data+curbyte, 0x0004, 0x0006, 0x0000, aim_snac_nextid);
|
|
49 curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
|
|
50 curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
|
|
51 curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
|
|
52 curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
|
|
53 curbyte += aimutil_put16(newpacket.data+curbyte,0x0001);
|
|
54 curbyte += aimutil_put8(newpacket.data+curbyte,strlen(destsn));
|
|
55 curbyte += aimutil_putstr(newpacket.data+curbyte, destsn, strlen(destsn));
|
|
56
|
|
57 if (flags & AIM_IMFLAGS_ACK)
|
|
58 {
|
|
59 curbyte += aimutil_put16(newpacket.data+curbyte,0x0003);
|
|
60 curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
|
|
61 }
|
|
62
|
|
63 if (flags & AIM_IMFLAGS_AWAY)
|
|
64 {
|
|
65 curbyte += aimutil_put16(newpacket.data+curbyte,0x0004);
|
|
66 curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
|
|
67 }
|
|
68
|
|
69 curbyte += aimutil_put16(newpacket.data+curbyte,0x0002);
|
|
70 curbyte += aimutil_put16(newpacket.data+curbyte,strlen(msg)+0xf);
|
|
71 curbyte += aimutil_put16(newpacket.data+curbyte,0x0501);
|
|
72 curbyte += aimutil_put16(newpacket.data+curbyte,0x0001);
|
|
73 curbyte += aimutil_put16(newpacket.data+curbyte,0x0101);
|
|
74 curbyte += aimutil_put16(newpacket.data+curbyte,0x0101);
|
|
75 curbyte += aimutil_put8(newpacket.data+curbyte,0x01);
|
|
76 curbyte += aimutil_put16(newpacket.data+curbyte,strlen(msg)+4);
|
|
77 curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
|
|
78 curbyte += aimutil_put16(newpacket.data+curbyte,0x0000);
|
|
79 curbyte += aimutil_putstr(newpacket.data+curbyte, msg, strlen(msg));
|
|
80
|
|
81 aim_tx_enqueue(&newpacket);
|
|
82
|
|
83 #ifdef USE_SNAC_FOR_IMS
|
|
84 {
|
|
85 struct aim_snac_t snac;
|
|
86
|
|
87 snac.id = aim_snac_nextid;
|
|
88 snac.family = 0x0004;
|
|
89 snac.type = 0x0006;
|
|
90 snac.flags = 0x0000;
|
|
91
|
|
92 snac.data = malloc(strlen(destsn)+1);
|
|
93 memcpy(snac.data, destsn, strlen(destsn)+1);
|
|
94
|
|
95 aim_newsnac(&snac);
|
|
96 }
|
|
97
|
|
98 aim_cleansnacs(60); /* clean out all SNACs over 60sec old */
|
|
99 #endif
|
|
100
|
|
101 return (aim_snac_nextid++);
|
|
102 }
|
|
103
|
|
104 int aim_parse_incoming_im_middle(struct command_rx_struct *command)
|
|
105 {
|
|
106 int i = 0;
|
|
107 char *srcsn = NULL;
|
|
108 char *msg = NULL;
|
|
109 unsigned int msglen = 0;
|
|
110 int warninglevel = 0;
|
|
111 int tlvcnt = 0;
|
|
112 int class = 0;
|
|
113 ulong membersince = 0;
|
|
114 ulong onsince = 0;
|
|
115 int idletime = 0;
|
|
116 int isautoreply = 0;
|
|
117
|
|
118 i = 20;
|
|
119
|
|
120 srcsn = malloc(command->data[i] + 1);
|
|
121 memcpy(srcsn, &(command->data[i+1]), command->data[i]);
|
|
122 srcsn[(int)command->data[i]] = '\0';
|
|
123
|
|
124 i += (int) command->data[i] + 1; /* add SN len */
|
|
125
|
|
126 /* warning level */
|
|
127 warninglevel = (command->data[i] << 8);
|
|
128 warninglevel += (command->data[i+1]);
|
|
129 i += 2;
|
|
130
|
|
131 tlvcnt = ((command->data[i++]) << 8) & 0xFF00;
|
|
132 tlvcnt += (command->data[i++]) & 0x00FF;
|
|
133
|
|
134 /* a mini TLV parser */
|
|
135 {
|
|
136 int curtlv = 0;
|
|
137 int tlv1 = 0;
|
|
138
|
|
139 while (curtlv < tlvcnt)
|
|
140 {
|
|
141 if ((command->data[i] == 0x00) &&
|
|
142 (command->data[i+1] == 0x01) )
|
|
143 {
|
|
144 if (tlv1)
|
|
145 break;
|
|
146 /* t(0001) = class */
|
|
147 if (command->data[i+3] != 0x02)
|
|
148 printf("faim: userinfo: **warning: strange v(%x) for t(1)\n", command->data[i+3]);
|
|
149 class = ((command->data[i+4]) << 8) & 0xFF00;
|
|
150 class += (command->data[i+5]) & 0x00FF;
|
|
151 i += (2 + 2 + command->data[i+3]);
|
|
152 tlv1++;
|
|
153 }
|
|
154 else if ((command->data[i] == 0x00) &&
|
|
155 (command->data[i+1] == 0x02))
|
|
156 {
|
|
157 /* t(0002) = member since date */
|
|
158 if (command->data[i+3] != 0x04)
|
|
159 printf("faim: userinfo: **warning: strange v(%x) for t(2)\n", command->data[i+3]);
|
|
160
|
|
161 membersince = ((command->data[i+4]) << 24) & 0xFF000000;
|
|
162 membersince += ((command->data[i+5]) << 16) & 0x00FF0000;
|
|
163 membersince += ((command->data[i+6]) << 8) & 0x0000FF00;
|
|
164 membersince += ((command->data[i+7]) ) & 0x000000FF;
|
|
165 i += (2 + 2 + command->data[i+3]);
|
|
166 }
|
|
167 else if ((command->data[i] == 0x00) &&
|
|
168 (command->data[i+1] == 0x03))
|
|
169 {
|
|
170 /* t(0003) = on since date */
|
|
171 if (command->data[i+3] != 0x04)
|
|
172 printf("faim: userinfo: **warning: strange v(%x) for t(3)\n", command->data[i+3]);
|
|
173
|
|
174 onsince = ((command->data[i+4]) << 24) & 0xFF000000;
|
|
175 onsince += ((command->data[i+5]) << 16) & 0x00FF0000;
|
|
176 onsince += ((command->data[i+6]) << 8) & 0x0000FF00;
|
|
177 onsince += ((command->data[i+7]) ) & 0x000000FF;
|
|
178 i += (2 + 2 + command->data[i+3]);
|
|
179 }
|
|
180 else if ((command->data[i] == 0x00) &&
|
|
181 (command->data[i+1] == 0x04) )
|
|
182 {
|
|
183 /* t(0004) = idle time */
|
|
184 if (command->data[i+3] != 0x02)
|
|
185 printf("faim: userinfo: **warning: strange v(%x) for t(4)\n", command->data[i+3]);
|
|
186 idletime = ((command->data[i+4]) << 8) & 0xFF00;
|
|
187 idletime += (command->data[i+5]) & 0x00FF;
|
|
188 i += (2 + 2 + command->data[i+3]);
|
|
189 }
|
|
190 else
|
|
191 {
|
|
192 printf("faim: userinfo: **warning: unexpected TLV t(%02x%02x) l(%02x%02x)\n", command->data[i], command->data[i+1], command->data[i+2], command->data[i+3]);
|
|
193 i += (2 + 2 + command->data[i+3]);
|
|
194 }
|
|
195 curtlv++;
|
|
196 }
|
|
197 }
|
|
198
|
|
199 {
|
|
200 /* detect if this is an auto-response or not */
|
|
201 /* auto-responses can be detected by the presence of a *second* TLV with
|
|
202 t(0004), but of zero length (and therefore no value portion) */
|
|
203 struct aim_tlv_t *tsttlv = NULL;
|
|
204 tsttlv = aim_grabtlv((u_char *) &(command->data[i]));
|
|
205 if (tsttlv->type == 0x04)
|
|
206 isautoreply = 1;
|
|
207 aim_freetlv(&tsttlv);
|
|
208 }
|
|
209
|
|
210 i += 2;
|
|
211
|
|
212 i += 2; /* skip first msglen */
|
|
213 i += 7; /* skip garbage */
|
|
214 i -= 4;
|
|
215
|
|
216 /* oh boy is this terrible... this comes from a specific of the spec */
|
|
217 while(1)
|
|
218 {
|
|
219 if ( ( (command->data[i] == 0x00) &&
|
|
220 (command->data[i+1] == 0x00) &&
|
|
221 (command->data[i+2] == 0x00) &&
|
|
222 (command->data[i+3] == 0x00) ) &&
|
|
223 (i < command->commandlen) ) /* prevent infinity */
|
|
224 break;
|
|
225 else
|
|
226 i++;
|
|
227 }
|
|
228
|
|
229 i -= 2;
|
|
230
|
|
231 if ( (command->data[i] == 0x00) &&
|
|
232 (command->data[i+1] == 0x00) )
|
|
233 i += 2;
|
|
234
|
|
235 msglen = ( (( (unsigned int) command->data[i]) & 0xFF ) << 8);
|
|
236 msglen += ( (unsigned int) command->data[i+1]) & 0xFF; /* mask off garbage */
|
|
237 i += 2;
|
|
238
|
|
239 msglen -= 4; /* skip four 0x00s */
|
|
240 i += 4;
|
|
241
|
|
242 msg = malloc(msglen +1);
|
|
243
|
|
244 memcpy(msg, &(command->data[i]), msglen);
|
|
245 msg[msglen] = '\0';
|
|
246
|
|
247 i = (aim_callbacks[AIM_CB_INCOMING_IM])(command, srcsn, msg, warninglevel, class, membersince, onsince, idletime, isautoreply);
|
|
248
|
|
249 free(srcsn);
|
|
250 free(msg);
|
|
251
|
|
252 return i;
|
|
253 }
|