503
|
1 #include <faim/aim.h>
|
|
2
|
|
3 #include <sys/utsname.h> /* for aim_directim_initiate */
|
|
4 #include <arpa/inet.h> /* for inet_ntoa */
|
|
5
|
|
6 /* aim_msgcookies.c is mostly new. just look at the diff and replace yours, easiest. */
|
|
7
|
|
8 /*
|
|
9 function name where i had it
|
|
10 aim_send_im_direct aim_im.c
|
|
11 aim_directim_initiate aim_im.c
|
|
12 aim_filetransfer_accept aim_im.c
|
|
13 aim_getlisting aim_misc.c (?!) -- prototype function. can be ignored.
|
|
14 establish aim_misc.c
|
|
15 aim_get_command_rendezvous aim_rxqueue.c
|
|
16 oft_getfh aim_rxqueue.c
|
|
17 */
|
|
18
|
|
19 int aim_handlerendconnect(struct aim_session_t *sess, struct aim_conn_t *cur)
|
|
20 {
|
|
21 int acceptfd = 0;
|
|
22 rxcallback_t userfunc;
|
|
23 struct sockaddr cliaddr;
|
|
24 socklen_t clilen = sizeof(cliaddr);
|
|
25 int ret = 0;
|
|
26
|
|
27 /*
|
|
28 * Listener sockets only have incoming connections. No data.
|
|
29 */
|
|
30 if( (acceptfd = accept(cur->fd, &cliaddr, &clilen)) == -1)
|
|
31 return -1;
|
|
32
|
|
33 if (cliaddr.sa_family != AF_INET) /* just in case IPv6 really is happening */
|
|
34 return -1;
|
|
35
|
|
36 switch(cur->subtype) {
|
|
37 case AIM_CONN_SUBTYPE_OFT_DIRECTIM: {
|
|
38 struct aim_directim_priv *priv;
|
|
39
|
|
40 priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
|
|
41
|
|
42 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));
|
|
43
|
|
44 if(!cur->priv)
|
|
45 cur->priv = priv; /* what happens if there is one?! -- mid */
|
|
46
|
|
47 cur->type = AIM_CONN_TYPE_RENDEZVOUS;
|
|
48 close(cur->fd); /* should we really do this? seems like the client should decide. maybe clone the connection and keep the listener open. -- mid */
|
|
49 cur->fd = acceptfd;
|
|
50
|
|
51 if ( (userfunc = aim_callhandler(cur, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE)))
|
|
52 ret = userfunc(sess, NULL, cur);
|
|
53
|
|
54 break;
|
|
55 }
|
|
56 case AIM_CONN_SUBTYPE_OFT_GETFILE: {
|
|
57 struct aim_filetransfer_priv *priv;
|
|
58
|
|
59 priv->state = 0;
|
|
60
|
|
61 priv = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv));
|
|
62
|
|
63 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));
|
|
64
|
|
65 if(!cur->priv)
|
|
66 cur->priv = priv;
|
|
67
|
|
68 if ( (userfunc = aim_callhandler(cur, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE)))
|
|
69 ret = userfunc(sess, NULL, cur);
|
|
70 break;
|
|
71 }
|
|
72 default: {
|
|
73 /* XXX */
|
|
74 }
|
|
75 }
|
|
76 return ret;
|
|
77 }
|
|
78
|
|
79
|
|
80 /*
|
|
81 * aim_send_im_direct:
|
|
82 * sess - session
|
|
83 * conn - directim connection
|
|
84 * msg - null-terminated string to send
|
|
85 */
|
|
86
|
|
87 int aim_send_im_direct(struct aim_session_t *sess,
|
|
88 struct aim_conn_t *conn,
|
|
89 char *msg)
|
|
90 {
|
|
91 struct command_tx_struct *newpacket , *newpacket2;
|
|
92
|
|
93 /* newpacket contains a real header with data, newpacket2 is just a
|
|
94 null packet, with a cookie and a lot of 0x00s. newpacket is the
|
|
95 "i'm sending", newpacket2 is the "i'm typing".*/
|
|
96
|
|
97 /* uhm. the client should send those as two seperate things -- mid */
|
|
98
|
|
99 struct aim_directim_priv *priv = NULL;
|
|
100 int i;
|
|
101
|
|
102 if (strlen(msg) >= MAXMSGLEN)
|
|
103 return -1;
|
|
104
|
|
105 if (!sess || !conn || !(conn->type) || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !conn->priv) {
|
|
106 printf("faim: directim: invalid arguments\n");
|
|
107 return -1;
|
|
108 };
|
|
109
|
|
110 priv = (struct aim_directim_priv *)conn->priv;
|
|
111
|
|
112 /* NULLish Header */
|
|
113
|
|
114 if (!(newpacket2 = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0001, conn, 0))) {
|
|
115 printf("faim: directim: tx_new2 failed\n");
|
|
116 return -1;
|
|
117 }
|
|
118
|
|
119 newpacket2->lock = 1; /* lock struct */
|
|
120
|
|
121 memcpy(newpacket2->hdr.oft.magic, "ODC2", 4);
|
|
122 newpacket2->hdr.oft.hdr2len = 0x44;
|
|
123
|
|
124 if (!(newpacket2->hdr.oft.hdr2 = calloc(1,newpacket2->hdr.oft.hdr2len))) {
|
|
125 free(newpacket2);
|
|
126 return -1;
|
|
127 }
|
|
128
|
|
129 i = 0;
|
|
130 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0006);
|
|
131 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
132
|
|
133 i += aimutil_putstr(newpacket2->hdr.oft.hdr2+i, priv->cookie, 8);
|
|
134
|
|
135 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
136 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
137 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
138 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
139
|
|
140 i += aimutil_put32(newpacket2->hdr.oft.hdr2+i, 0x00000000);
|
|
141
|
|
142 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
143 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
144 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
145
|
|
146 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x000e);
|
|
147
|
|
148 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
149 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
150
|
|
151 i += aimutil_putstr(newpacket2->hdr.oft.hdr2+i, sess->logininfo.screen_name, strlen(sess->logininfo.screen_name));
|
|
152
|
|
153 i = 52; /* 0x34 */
|
|
154 i += aimutil_put8(newpacket2->hdr.oft.hdr2+i, 0x00); /* 53 */
|
|
155 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000); /* 55 */
|
|
156 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
157 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
158 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);/* 61 */
|
|
159 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
|
|
160 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);/* 65 */
|
|
161 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);/* end of hdr2 */
|
|
162
|
|
163 newpacket2->lock = 0;
|
|
164 newpacket2->data = NULL;
|
|
165
|
|
166 aim_tx_enqueue(sess, newpacket2);
|
|
167
|
|
168 /* Header packet */
|
|
169
|
|
170 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0001, conn, strlen(msg)))) {
|
|
171 printf("faim: directim: tx_new failed\n");
|
|
172 return -1;
|
|
173 }
|
|
174
|
|
175 newpacket->lock = 1; /* lock struct */
|
|
176
|
|
177 memcpy(newpacket->hdr.oft.magic, "ODC2", 4);
|
|
178 newpacket->hdr.oft.hdr2len = 0x54;
|
|
179
|
|
180 if (!(newpacket->hdr.oft.hdr2 = calloc(1,newpacket->hdr.oft.hdr2len))) {
|
|
181 free(newpacket);
|
|
182 return -1;
|
|
183 }
|
|
184
|
|
185 i = 0;
|
|
186 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0006);
|
|
187 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
188
|
|
189 i += aimutil_putstr(newpacket->hdr.oft.hdr2+i, priv->cookie, 8);
|
|
190
|
|
191 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
192 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
193 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
194 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
195
|
|
196 i += aimutil_put32(newpacket->hdr.oft.hdr2+i, strlen(msg));
|
|
197
|
|
198 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
199 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
200 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
201 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
202 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
203 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
204
|
|
205 i += aimutil_putstr(newpacket->hdr.oft.hdr2+i, sess->logininfo.screen_name, strlen(sess->logininfo.screen_name));
|
|
206
|
|
207 i = 52; /* 0x34 */
|
|
208 i += aimutil_put8(newpacket->hdr.oft.hdr2+i, 0x00); /* 53 */
|
|
209 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); /* 55 */
|
|
210 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
211 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
212 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* 61 */
|
|
213 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
|
|
214 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* 65 */
|
|
215 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* end of hdr2 */
|
|
216
|
|
217 /* values grabbed from a dump */
|
|
218 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0008); /* 69 */
|
|
219 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x000c);
|
|
220 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* 71 */
|
|
221 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x1466);/* 73 */
|
|
222 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0001);/* 73 */
|
|
223 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x2e0f);
|
|
224 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x393e);
|
|
225 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0xcac8);
|
|
226
|
|
227 memcpy(newpacket->data, msg, strlen(msg));
|
|
228
|
|
229 newpacket->lock = 0;
|
|
230
|
|
231 aim_tx_enqueue(sess, newpacket);
|
|
232
|
|
233 return 0;
|
|
234 }
|
|
235
|
|
236 /*
|
|
237 * aim_directim_intitiate:
|
|
238 * For those times when we want to open up the directim channel ourselves.
|
|
239 * sess is your session,
|
|
240 * conn is the BOS conn,
|
|
241 * priv is a dummy priv value (we'll let it get filled in later) (if
|
|
242 * you pass a NULL, we alloc one)
|
|
243 * destsn is the SN to connect to.
|
|
244 */
|
|
245
|
|
246
|
|
247 struct aim_conn_t *aim_directim_initiate(struct aim_session_t *sess,
|
|
248 struct aim_conn_t *conn,
|
|
249 struct aim_directim_priv *priv,
|
|
250 char *destsn)
|
|
251 {
|
|
252 struct command_tx_struct *newpacket;
|
|
253 struct aim_conn_t *newconn;
|
|
254
|
|
255 struct aim_msgcookie_t *cookie;
|
|
256
|
|
257 int curbyte, i, listenfd;
|
|
258 short port = 4443;
|
|
259
|
|
260 struct hostent *hptr;
|
|
261 struct utsname myname;
|
|
262
|
|
263 char cap[16];
|
|
264 char d[4]; /* XXX: IPv6. *cough* */
|
|
265
|
|
266 /*
|
|
267 * Open our socket
|
|
268 */
|
|
269
|
|
270 if( (listenfd = aim_listenestablish(port)) == -1)
|
|
271 return NULL;
|
|
272
|
|
273 /*
|
|
274 * get our local IP
|
|
275 */
|
|
276
|
|
277 if(uname(&myname) < 0)
|
|
278 return NULL;
|
|
279
|
|
280 if( (hptr = gethostbyname(myname.nodename)) == NULL)
|
|
281 return NULL;
|
|
282
|
|
283 memcpy(&d, hptr->h_addr_list[0], 4); /* XXX: this probably isn't quite kosher, but it works */
|
|
284
|
|
285 aim_putcap(cap, 16, AIM_CAPS_IMIMAGE);
|
|
286
|
|
287 /*
|
|
288 * create the OSCAR packet
|
|
289 */
|
|
290
|
|
291 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+8+2+1+strlen(destsn)+4+4+0x32)))
|
|
292 return NULL;
|
|
293
|
|
294 newpacket->lock = 1; /* lock struct */
|
|
295
|
|
296 curbyte = 0;
|
|
297 curbyte += aim_putsnac(newpacket->data+curbyte,
|
|
298 0x0004, 0x0006, 0x0000, sess->snac_nextid);
|
|
299
|
|
300 /*
|
|
301 * Generate a random message cookie
|
|
302 * This cookie needs to be alphanumeric and NULL-terminated to be TOC-compatible.
|
|
303 */
|
|
304 for (i=0;i<7;i++)
|
|
305 curbyte += aimutil_put8(newpacket->data+curbyte, 0x30 + ((u_char) random() % 20));
|
|
306 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
|
|
307
|
|
308 /*
|
|
309 * grab all the data for cookie caching.
|
|
310 */
|
|
311 cookie = (struct aim_msgcookie_t *)calloc(1, sizeof(struct aim_msgcookie_t));
|
|
312
|
|
313 memcpy(cookie->cookie, newpacket->data+curbyte-8, 8);
|
|
314 cookie->type = AIM_COOKIETYPE_OFTIM;
|
|
315
|
|
316 if(!priv)
|
|
317 priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
|
|
318
|
|
319 memcpy(priv->cookie, cookie, 8);
|
|
320 memcpy(priv->sn, destsn, sizeof(priv->sn));
|
|
321
|
|
322 cookie->data = priv;
|
|
323
|
|
324 aim_cachecookie(sess, cookie); /* cache da cookie */
|
|
325
|
|
326 /*
|
|
327 * Channel ID
|
|
328 */
|
|
329 curbyte += aimutil_put16(newpacket->data+curbyte,0x0002);
|
|
330
|
|
331 /*
|
|
332 * Destination SN (prepended with byte length)
|
|
333 */
|
|
334 curbyte += aimutil_put8(newpacket->data+curbyte,strlen(destsn));
|
|
335 curbyte += aimutil_putstr(newpacket->data+curbyte, destsn, strlen(destsn));
|
|
336
|
|
337 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
|
|
338 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
|
|
339
|
|
340 /*
|
|
341 * enTLV start
|
|
342 */
|
|
343 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
|
|
344 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0032);
|
|
345
|
|
346 /*
|
|
347 * Flag data / ICBM Parameters?
|
|
348 */
|
|
349 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
|
|
350 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
|
|
351
|
|
352 /*
|
|
353 * Cookie
|
|
354 */
|
|
355 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cookie, 8);
|
|
356
|
|
357 /*
|
|
358 * Capability String
|
|
359 */
|
|
360 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cap, 0x10);
|
|
361
|
|
362 /*
|
|
363 * 000a/0002 : 0001
|
|
364 */
|
|
365 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000a);
|
|
366 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
|
|
367 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
|
|
368
|
|
369 /*
|
|
370 * 0003/0004: IP address
|
|
371 */
|
|
372
|
|
373 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
|
|
374 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0004);
|
|
375
|
|
376 for(i = 0; i < 4; i++)
|
|
377 curbyte += aimutil_put8(newpacket->data+curbyte, d[i]); /* already in network byte order */
|
|
378
|
|
379 /*
|
|
380 * 0005/0002: Port
|
|
381 */
|
|
382
|
|
383 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
|
|
384 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
|
|
385 curbyte += aimutil_put16(newpacket->data+curbyte, port);
|
|
386
|
|
387 /*
|
|
388 * 000f/0000: umm.. dunno. Zigamorph[1]?
|
|
389 * [1]: see esr's TNHD.
|
|
390 */
|
|
391
|
|
392 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f);
|
|
393 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
|
|
394
|
|
395 printf("curbyte: 0x%x\n",curbyte);
|
|
396
|
|
397 newpacket->commandlen = curbyte;
|
|
398 newpacket->lock = 0;
|
|
399
|
|
400 aim_tx_enqueue(sess, newpacket);
|
|
401
|
|
402 /*
|
|
403 * allocate and set up our connection
|
|
404 */
|
|
405
|
|
406 i = fcntl(listenfd, F_GETFL, 0);
|
|
407 fcntl(listenfd, F_SETFL, i | O_NONBLOCK);
|
|
408
|
|
409 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL);
|
|
410 if (!newconn) {
|
|
411 perror("aim_newconn");
|
|
412 aim_conn_kill(sess, &newconn);
|
|
413 return NULL;
|
|
414 }
|
|
415
|
|
416 newconn->fd = listenfd;
|
|
417 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
|
|
418 newconn->priv = priv;
|
|
419 printf("faim: listening (fd = %d, unconnected)\n", newconn->fd);
|
|
420
|
|
421 /*
|
|
422 * XXX We need some way of closing the listener socket after
|
|
423 * n seconds of no connection. -- mid
|
|
424 */
|
|
425
|
|
426 #ifdef USE_SNAC_FOR_IMS
|
|
427 {
|
|
428 struct aim_snac_t snac;
|
|
429
|
|
430 snac.id = sess->snac_nextid;
|
|
431 snac.family = 0x0004;
|
|
432 snac.type = 0x0006;
|
|
433 snac.flags = 0x0000;
|
|
434
|
|
435 snac.data = malloc(strlen(destsn)+1);
|
|
436 memcpy(snac.data, destsn, strlen(destsn)+1);
|
|
437
|
|
438 aim_newsnac(sess, &snac);
|
|
439
|
|
440 aim_cleansnacs(sess, 60); /* clean out all SNACs over 60sec old */
|
|
441 }
|
|
442 #endif
|
|
443
|
|
444 return (newconn);
|
|
445 }
|
|
446
|
|
447
|
|
448 struct aim_conn_t *aim_directim_connect(struct aim_session_t *sess,
|
|
449 struct aim_conn_t *conn,
|
|
450 struct aim_directim_priv *priv )
|
|
451 {
|
|
452 struct aim_conn_t *newconn = NULL;;
|
|
453
|
|
454 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, priv->ip);
|
|
455 if (!newconn || (newconn->fd == -1)) {
|
|
456 printf("could not connect to %s\n", priv->ip);
|
|
457 perror("aim_newconn");
|
|
458 aim_conn_kill(sess, &newconn);
|
|
459 return NULL;
|
|
460 } else {
|
|
461 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
|
|
462 newconn->priv = priv;
|
|
463 printf("faim: connected to peer (fd = %d)\n", newconn->fd);
|
|
464 return newconn;
|
|
465 }
|
|
466 return newconn;
|
|
467 }
|
|
468
|
|
469 u_long aim_accepttransfer(struct aim_session_t *sess,
|
|
470 struct aim_conn_t *conn,
|
|
471 struct aim_conn_t *oftconn,
|
|
472 char *sn,
|
|
473 char *cookie,
|
|
474 unsigned short rendid)
|
|
475 {
|
|
476 struct command_tx_struct *newpacket, *newoft;
|
|
477 struct aim_fileheader_t *listingfh;
|
|
478 int curbyte, i;
|
|
479 /* now for the oft bits */
|
|
480
|
|
481 if(rendid == AIM_CAPS_GETFILE) {
|
|
482 printf("jbm: getfile request accept\n");
|
|
483 if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x1108, oftconn, 0))) {
|
|
484 printf("faim: accept_transfer: tx_new OFT failed\n");
|
|
485 return -1;
|
|
486 }
|
|
487
|
|
488 newoft->lock = 1;
|
|
489
|
|
490 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
|
|
491 newoft->hdr.oft.hdr2len = 0xf8; /* 0x100 - 8 */
|
|
492
|
|
493 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) {
|
|
494 free(newoft);
|
|
495 return -1;
|
|
496 }
|
|
497
|
|
498 listingfh = aim_getlisting(sess);
|
|
499
|
|
500 memcpy(listingfh->bcookie, cookie, 8);
|
|
501
|
|
502 curbyte = 0;
|
|
503
|
|
504 for(i = 0; i < 8; i++)
|
|
505 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, cookie[i]);
|
|
506 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->encrypt);
|
|
507 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->compress);
|
|
508 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totfiles);
|
|
509 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->filesleft);
|
|
510 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totparts);
|
|
511 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->partsleft);
|
|
512 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->totsize);
|
|
513 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->size);
|
|
514 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->modtime);
|
|
515 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->checksum);
|
|
516 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfrcsum);
|
|
517 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfsize);
|
|
518 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->cretime);
|
|
519 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfcsum);
|
|
520 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->nrecvd);
|
|
521 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->recvcsum);
|
|
522
|
|
523 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->idstring, 32);
|
|
524 curbyte += 32;
|
|
525
|
|
526 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->flags);
|
|
527 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lnameoffset);
|
|
528 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lsizeoffset);
|
|
529
|
|
530 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->dummy, 69);
|
|
531 curbyte += 69;
|
|
532
|
|
533 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->macfileinfo, 16);
|
|
534 curbyte += 16;
|
|
535
|
|
536 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nencode);
|
|
537 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nlanguage);
|
|
538
|
|
539 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->name, 64);
|
|
540 curbyte += 64;
|
|
541
|
|
542 free(listingfh);
|
|
543
|
|
544 newoft->lock = 0;
|
|
545 aim_tx_enqueue(sess, newoft);
|
|
546 printf("faim: getfile: OFT listing enqueued.\n");
|
|
547
|
|
548 }
|
|
549
|
|
550
|
|
551 if(!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+8+2+1+strlen(sn)+4+2+8+16)))
|
|
552 return -1;
|
|
553
|
|
554 newpacket->lock = 1;
|
|
555
|
|
556 curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid);
|
|
557 for (i = 0; i < 8; i++)
|
|
558 curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
|
|
559 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
|
|
560 curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sn));
|
|
561 curbyte += aimutil_putstr(newpacket->data+curbyte, sn, strlen(sn));
|
|
562 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
|
|
563 curbyte += aimutil_put16(newpacket->data+curbyte, 0x001a);
|
|
564 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002 /* accept */);
|
|
565 for (i = 0; i < 8; i++)
|
|
566 curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
|
|
567 curbyte += aim_putcap(newpacket->data+curbyte, 0x10, rendid);
|
|
568
|
|
569 newpacket->lock = 0;
|
|
570 aim_tx_enqueue(sess, newpacket);
|
|
571
|
|
572
|
|
573
|
|
574 return (sess->snac_nextid++);
|
|
575 }
|
|
576
|
|
577 /*
|
|
578 * aim_getlisting()
|
|
579 *
|
|
580 * Get file listing.txt info. where else to put it? i
|
|
581 * dunno. client-side issue for sure tho. for now we just side-step
|
|
582 * the issue with a nice default. =)
|
|
583 *
|
|
584 */
|
|
585
|
|
586 struct aim_fileheader_t *aim_getlisting(struct aim_session_t *sess)
|
|
587 {
|
|
588 struct aim_fileheader_t *fh;
|
|
589
|
|
590 if(!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t))))
|
|
591 return NULL;
|
|
592
|
|
593 fh->encrypt = 0x0000;
|
|
594 fh->compress = 0x0000;
|
|
595 fh->totfiles = 0x0001;
|
|
596 fh->filesleft = 0x0001;
|
|
597 fh->totparts = 0x0001;
|
|
598 fh->partsleft = 0x0001;
|
|
599 fh->totsize = 0x00000064;
|
|
600 fh->size = 0x00000024; /* ls -l listing.txt */
|
|
601 fh->modtime = (int)time(NULL); /*0x39441fb4; */
|
|
602 fh->checksum = 0xb8350000;
|
|
603 fh->rfcsum = 0x00000000;
|
|
604 fh->rfsize = 0x00000000;
|
|
605 fh->cretime = 0x00000000;
|
|
606 fh->rfcsum = 0x00000000;
|
|
607 fh->nrecvd = 0x00000000;
|
|
608 fh->recvcsum = 0x00000000;
|
|
609
|
|
610 memset(fh->idstring, 0, 32/*sizeof(fh->idstring)*/);
|
|
611 memcpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", 32/*sizeof(fh->idstring)*/);
|
|
612 memset(fh->idstring+strlen(fh->idstring), 0, 32-strlen(fh->idstring)); /* jbm hack */
|
|
613
|
|
614 fh->flags = 0x02;
|
|
615 fh->lnameoffset = 0x1a;
|
|
616 fh->lsizeoffset = 0x10;
|
|
617
|
|
618 memset(fh->dummy, 0, 69/*sizeof(fh->dummy)*/);
|
|
619 /* fh->dummy = ;*/
|
|
620
|
|
621 memset(fh->macfileinfo, 0, 16/*sizeof(fh->macfileinfo)*/);
|
|
622 /* fh->macfileinfo = ; */
|
|
623
|
|
624 fh->nencode = 0x0000;
|
|
625 fh->nlanguage = 0x0000;
|
|
626
|
|
627 memset(fh->name, 0, 64/*sizeof(fh->name)*/);
|
|
628 memcpy(fh->name, "listing.txt", 64 /*sizeof(fh->name)*/);
|
|
629 memset(fh->name+strlen(fh->name), 0, 64-strlen(fh->name)); /* jbm hack */
|
|
630
|
|
631 printf("jbm: fh name %s / %s\n", fh->name, (fh->name+(strlen(fh->name))));
|
|
632 return fh;
|
|
633 }
|
|
634
|
|
635 /*
|
|
636 * establish: create a listening socket on a port. you need to call
|
|
637 * accept() when it's connected.
|
|
638 * portnum is the port number to bind to.
|
|
639 * returns your fd
|
|
640 */
|
|
641
|
|
642 int aim_listenestablish(u_short portnum)
|
|
643 {
|
|
644 int listenfd;
|
|
645 const int on = 1;
|
|
646 struct addrinfo hints, *res, *ressave;
|
|
647 char serv[5];
|
|
648 sprintf(serv, "%d", portnum);
|
|
649 memset(&hints, 0, sizeof(struct addrinfo));
|
|
650 hints.ai_flags = AI_PASSIVE;
|
|
651 hints.ai_family = AF_UNSPEC;
|
|
652 hints.ai_socktype = SOCK_STREAM;
|
|
653 if (getaddrinfo(NULL/*any IP*/, serv, &hints, &res) != 0) {
|
|
654 perror("getaddrinfo");
|
|
655 return -1;
|
|
656 }
|
|
657 ressave = res;
|
|
658 do {
|
|
659 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
|
660 if (listenfd < 0)
|
|
661 continue;
|
|
662 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
|
663 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
|
|
664 break; /* success */
|
|
665 close(listenfd);
|
|
666 } while ( (res = res->ai_next) );
|
|
667 if (!res)
|
|
668 return -1;
|
|
669 if (listen(listenfd, 1024)!=0) {
|
|
670 perror("listen");
|
|
671 return -1;
|
|
672 }
|
|
673 freeaddrinfo(ressave);
|
|
674 return listenfd;
|
|
675 }
|
|
676
|
|
677 int aim_get_command_rendezvous(struct aim_session_t *sess, struct aim_conn_t *conn)
|
|
678 {
|
|
679
|
|
680 /* XXX: NOT THREAD SAFE RIGHT NOW. the locks are acting up. deal. -- jbm */
|
|
681
|
|
682 unsigned char hdrbuf1[6];
|
|
683 unsigned char *hdr = NULL;
|
|
684 int hdrlen, hdrtype;
|
|
685 int flags = 0;
|
|
686 rxcallback_t userfunc = NULL;
|
|
687
|
|
688
|
|
689 memset(hdrbuf1, 0, sizeof(hdrbuf1));
|
|
690
|
|
691 faim_mutex_lock(&conn->active); /* gets locked down for the entirety */
|
|
692
|
|
693 if ( (hdrlen = read(conn->fd, hdrbuf1, 6)) < 6) {
|
|
694 if(hdrlen < 0)
|
|
695 perror("read");
|
|
696 printf("faim: rend: read error (fd: %i) %02x%02x%02x%02x%02x%02x (%i)\n", conn->fd, hdrbuf1[0],hdrbuf1[1],hdrbuf1[0],hdrbuf1[0],hdrbuf1[0],hdrbuf1[0],hdrlen);
|
|
697 faim_mutex_unlock(&conn->active);
|
|
698 aim_conn_close(conn);
|
|
699 return -1;
|
|
700 }
|
|
701
|
|
702 hdrlen = aimutil_get16(hdrbuf1+4);
|
|
703
|
|
704 hdrlen -= 6;
|
|
705 if (!(hdr = malloc(hdrlen)))
|
|
706 return -1;
|
|
707
|
|
708 if (read(conn->fd, hdr, hdrlen) < hdrlen) {
|
|
709 perror("read");
|
|
710 printf("faim: rend: read2 error\n");
|
|
711 free(hdr);
|
|
712 faim_mutex_unlock(&conn->active);
|
|
713 aim_conn_close(conn);
|
|
714 return 0; /* see comment on previous read check */
|
|
715 }
|
|
716
|
|
717 hdrtype = aimutil_get16(hdr);
|
|
718
|
|
719 switch (hdrtype) {
|
|
720 case 0x0001: { /* directim */
|
|
721 int payloadlength = 0;
|
|
722 char *snptr = NULL;
|
|
723 struct aim_directim_priv *priv;
|
|
724 int i;
|
|
725
|
|
726 priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
|
|
727
|
|
728 payloadlength = aimutil_get32(hdr+22);
|
|
729 flags = aimutil_get16(hdr+32);
|
|
730 snptr = hdr+38;
|
|
731
|
|
732 strncpy(priv->sn, snptr, MAXSNLEN);
|
|
733
|
|
734 #if 0
|
|
735 printf("faim: OFT frame: %04x / %04x / %04x / %s\n", hdrtype, payloadlength, flags, snptr);
|
|
736 #endif
|
|
737
|
|
738 if (flags == 0x000e) {
|
|
739 faim_mutex_unlock(&conn->active);
|
|
740 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING)) )
|
|
741 return userfunc(sess, NULL, snptr);
|
|
742 } else if ((flags == 0x0000) && payloadlength) {
|
|
743 unsigned char *msg;
|
|
744
|
|
745 if(! (msg = calloc(1, payloadlength+1)) ) {
|
|
746 faim_mutex_unlock(&conn->active);
|
|
747 return 0;
|
|
748 }
|
|
749
|
|
750 if (recv(conn->fd, msg, payloadlength, MSG_WAITALL) < payloadlength) {
|
|
751 perror("read");
|
|
752 printf("faim: rend: read3 error\n");
|
|
753 free(msg);
|
|
754 faim_mutex_unlock(&conn->active);
|
|
755 aim_conn_close(conn);
|
|
756 return -1;
|
|
757 }
|
|
758 faim_mutex_unlock(&conn->active);
|
|
759 msg[payloadlength] = '\0';
|
|
760 #if 0
|
|
761 printf("faim: directim: %s/%04x/%04x/%s\n", snptr, payloadlength, flags, msg);
|
|
762 #endif
|
|
763
|
|
764 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) )
|
|
765 i = userfunc(sess, NULL, conn, snptr, msg);
|
|
766
|
|
767 free(msg);
|
|
768 return i;
|
|
769 }
|
|
770 break;
|
|
771 }
|
|
772 case 0x1209: { /* get file first */
|
|
773 struct aim_filetransfer_priv *ft;
|
|
774 struct aim_fileheader_t *fh;
|
|
775 struct aim_msgcookie_t *cook;
|
|
776
|
|
777 int commandlen;
|
|
778 char *data;
|
|
779
|
|
780 printf("faim: rend: fileget 0x1209\n");
|
|
781
|
|
782 if(hdrlen != 0x100)
|
|
783 printf("faim: fileget_command(1209): um. hdrlen != 0x100.. 0x%x\n", hdrlen);
|
|
784
|
|
785 if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
|
|
786 printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
|
|
787 faim_mutex_unlock(&conn->active);
|
|
788 return 0;
|
|
789 }
|
|
790
|
|
791 fh = aim_oft_getfh(hdr);
|
|
792
|
|
793 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
|
|
794
|
|
795 cook = aim_checkcookie(sess, ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
|
|
796
|
|
797 if(cook->data)
|
|
798 free(cook->data); /* XXX */
|
|
799
|
|
800 cook->data = ft;
|
|
801
|
|
802 aim_cachecookie(sess, cook);
|
|
803
|
|
804 commandlen = 36;
|
|
805
|
|
806 data = calloc(1, commandlen);
|
|
807 memcpy(data, "01/01/1999 00:00 100 file.txt\r\n", commandlen);
|
|
808
|
|
809 if (write(conn->fd, data, commandlen) != commandlen) {
|
|
810 perror("listing write error");
|
|
811 }
|
|
812 faim_mutex_unlock(&conn->active);
|
|
813
|
|
814 printf("jbm: hit end of 1209\n");
|
|
815
|
|
816 break;
|
|
817 }
|
|
818 case 0x120b: { /* get file second */
|
|
819 struct aim_filetransfer_priv *ft;
|
|
820 struct aim_msgcookie_t *cook;
|
|
821
|
|
822 struct aim_fileheader_t *fh;
|
|
823
|
|
824 printf("faim: rend: fileget 120b\n");
|
|
825
|
|
826 if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
|
|
827 printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
|
|
828 faim_mutex_unlock(&conn->active);
|
|
829 return 0;
|
|
830 }
|
|
831
|
|
832 if(hdrlen != 0x100)
|
|
833 printf("faim: fileget_command(120b): um. hdrlen != 0x100..\n");
|
|
834
|
|
835 fh = aim_oft_getfh(hdr);
|
|
836
|
|
837 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
|
|
838
|
|
839 cook = aim_checkcookie(sess, ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
|
|
840
|
|
841 if(cook->data)
|
|
842 free(cook->data); /* XXX: integrate cookie caching */
|
|
843
|
|
844 cook->data = ft;
|
|
845
|
|
846 aim_cachecookie(sess, cook);
|
|
847
|
|
848 faim_mutex_unlock(&conn->active);
|
|
849
|
|
850 break;
|
|
851 }
|
|
852 case 0x120c: { /* yet more get file */
|
|
853 struct aim_filetransfer_priv *ft;
|
|
854 struct aim_msgcookie_t *cook;
|
|
855 struct aim_fileheader_t *listingfh;
|
|
856 struct command_tx_struct *newoft;
|
|
857 int curbyte, i;
|
|
858
|
|
859 printf("faim: rend: fileget 120c\n");
|
|
860
|
|
861 if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
|
|
862 printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
|
|
863 faim_mutex_unlock(&conn->active);
|
|
864 return 0;
|
|
865 }
|
|
866
|
|
867 if(hdrlen != 0x100)
|
|
868 printf("faim: fileget_command(120c): um. hdrlen != 0x100..\n");
|
|
869
|
|
870 listingfh = aim_oft_getfh((char *)hdr);
|
|
871
|
|
872 memcpy(&(ft->fh), listingfh, sizeof(struct aim_fileheader_t));
|
|
873
|
|
874 cook = aim_checkcookie(sess, ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
|
|
875
|
|
876 if(cook->data)
|
|
877 free(cook->data); /* XXX */
|
|
878
|
|
879 cook->data = ft;
|
|
880
|
|
881 aim_cachecookie(sess, cook);
|
|
882
|
|
883 faim_mutex_unlock(&conn->active);
|
|
884
|
|
885 printf("faim: fileget: %s seems to want %s\n", ft->sn, ft->fh.name);
|
|
886
|
|
887 if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0101, conn, 0/*listingfh->size*/))) {
|
|
888 printf("faim: send_final_transfer: tx_new OFT failed\n");
|
|
889 return 0;
|
|
890 }
|
|
891
|
|
892 /* XXX: actually implement Real Handling of all this */
|
|
893
|
|
894 printf("jbm: listingfh->size: 0x%lx\n", listingfh->size);
|
|
895
|
|
896 newoft->lock = 1;
|
|
897
|
|
898 /* if(!(newoft->data = calloc(1, listingfh->size))) {
|
|
899 printf("newoft data malloc failed. bombing.\n");
|
|
900 return 0;
|
|
901 }*/
|
|
902
|
|
903 if(newoft->commandlen > 0) {
|
|
904 int i;
|
|
905 bzero(newoft->data, newoft->commandlen);
|
|
906 for(i = 0; i < newoft->commandlen; i++)
|
|
907 newoft->data[i] = 0x30 + (i%10);
|
|
908
|
|
909 // memcpy(newoft->data, "This has been a Test\r\n-josh\r\n", newoft->commandlen);
|
|
910 }
|
|
911
|
|
912 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
|
|
913 newoft->hdr.oft.hdr2len = 0xf8; /* 0x100 - 8 */
|
|
914
|
|
915 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) {
|
|
916 if(newoft->data)
|
|
917 free(newoft->data); /* XXX: make this into a destructor function */
|
|
918 free(newoft);
|
|
919 return 0;
|
|
920 }
|
|
921
|
|
922 memcpy(listingfh->bcookie, ft->fh.bcookie, 8);
|
|
923
|
|
924 curbyte = 0;
|
|
925
|
|
926 for(i = 0; i < 8; i++)
|
|
927 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->bcookie[i]);
|
|
928 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->encrypt);
|
|
929 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->compress);
|
|
930 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totfiles);
|
|
931 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->filesleft);
|
|
932 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totparts);
|
|
933 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->partsleft);
|
|
934 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->totsize);
|
|
935 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->size);
|
|
936 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->modtime);
|
|
937 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->checksum);
|
|
938 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfrcsum);
|
|
939 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfsize);
|
|
940 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->cretime);
|
|
941 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfcsum);
|
|
942 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, 0 /*listingfh->nrecvd*/);
|
|
943 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, 0/*listingfh->recvcsum*/);
|
|
944
|
|
945 strncpy(newoft->hdr.oft.hdr2+curbyte, listingfh->idstring, 32);
|
|
946 curbyte += 32;
|
|
947
|
|
948 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, 0x20 /*listingfh->flags */);
|
|
949 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lnameoffset);
|
|
950 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lsizeoffset);
|
|
951
|
|
952 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->dummy, 69);
|
|
953 curbyte += 69;
|
|
954
|
|
955 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->macfileinfo, 16);
|
|
956 curbyte += 16;
|
|
957
|
|
958 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nencode);
|
|
959 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nlanguage);
|
|
960
|
|
961 strncpy(newoft->hdr.oft.hdr2+curbyte, listingfh->name, 64);
|
|
962 curbyte += 64;
|
|
963
|
|
964 free(listingfh);
|
|
965
|
|
966 newoft->lock = 0;
|
|
967 aim_tx_enqueue(sess, newoft);
|
|
968 printf("jbm: OFT listing enqueued.\n");
|
|
969
|
|
970 break;
|
|
971 }
|
|
972 case 0x0202: { /* get file: ready to recieve data */
|
|
973 char *c;
|
|
974 int i;
|
|
975
|
|
976 struct aim_fileheader_t *fh;
|
|
977 fh = aim_oft_getfh((char *)hdr);
|
|
978
|
|
979 c = (char *)calloc(1, fh->size);
|
|
980
|
|
981 printf("looks like we're ready to send data.(oft 0x0202)\n");
|
|
982
|
|
983
|
|
984
|
|
985 for(i = 0; i < fh->size; i++)
|
|
986 c[i] = 0x30 + (i%10);
|
|
987
|
|
988 if ( (i = write(conn->fd, c, fh->size)) != fh->size ) {
|
|
989 printf("whoopsy, didn't write it all...\n");
|
|
990 }
|
|
991
|
|
992 faim_mutex_unlock(&conn->active);
|
|
993
|
|
994 break;
|
|
995 }
|
|
996 case 0x0204: { /* get file: finished. close it up */
|
|
997 printf("looks like we're done with a transfer (oft 0x0204)\n");
|
|
998 faim_mutex_unlock(&conn->active);
|
|
999 aim_conn_close(conn);
|
|
1000 break;
|
|
1001 }
|
|
1002 default: {
|
|
1003 printf("OFT frame: type %04x\n", hdrtype);
|
|
1004 /* data connection may be unreliable here */
|
|
1005 faim_mutex_unlock(&conn->active);
|
|
1006 break;
|
|
1007 }
|
|
1008 } /* switch */
|
|
1009
|
|
1010 free(hdr);
|
|
1011
|
|
1012 return 0;
|
|
1013 }
|
|
1014
|
|
1015 /*
|
|
1016 * this currently feeds totally bogus data
|
|
1017 */
|
|
1018
|
|
1019 struct aim_fileheader_t *aim_oft_getfh(char *hdr)
|
|
1020 {
|
|
1021 struct aim_fileheader_t *fh;
|
|
1022 int i, j;
|
|
1023
|
|
1024 if(!(fh = calloc(1, sizeof(struct aim_fileheader_t))))
|
|
1025 return NULL;
|
|
1026
|
|
1027 /* [0] and [1] are the type. we can ignore those here. */
|
|
1028
|
|
1029 i = 2;
|
|
1030
|
|
1031 for(j = 0; j < 8; j++, i++)
|
|
1032 fh->bcookie[j] = hdr[i];
|
|
1033 fh->encrypt = aimutil_get16(hdr+i);
|
|
1034 i += 2;
|
|
1035 fh->compress = aimutil_get16(hdr+i);
|
|
1036 i += 2;
|
|
1037 fh->totfiles = aimutil_get16(hdr+i);
|
|
1038 i += 2;
|
|
1039 fh->filesleft = aimutil_get16(hdr+i);
|
|
1040 i += 2;
|
|
1041 fh->totparts = aimutil_get16(hdr+i);
|
|
1042 i += 2;
|
|
1043 fh->partsleft = aimutil_get16(hdr+i);
|
|
1044 i += 2;
|
|
1045 fh->totsize = aimutil_get32(hdr+i);
|
|
1046 i += 4;
|
|
1047 fh->size = aimutil_get32(hdr+i);
|
|
1048 i += 4;
|
|
1049 fh->modtime = aimutil_get32(hdr+i);
|
|
1050 i += 4;
|
|
1051 fh->checksum = aimutil_get32(hdr+i);
|
|
1052 i += 4;
|
|
1053 fh->rfrcsum = aimutil_get32(hdr+i);
|
|
1054 i += 4;
|
|
1055 fh->rfsize = aimutil_get32(hdr+i);
|
|
1056 i += 4;
|
|
1057 fh->cretime = aimutil_get32(hdr+i);
|
|
1058 i += 4;
|
|
1059 fh->rfcsum = aimutil_get32(hdr+i);
|
|
1060 i += 4;
|
|
1061 fh->nrecvd = aimutil_get32(hdr+i);
|
|
1062 i += 4;
|
|
1063 fh->recvcsum = aimutil_get32(hdr+i);
|
|
1064 i += 4;
|
|
1065
|
|
1066 memcpy(fh->idstring, hdr+i, 32);
|
|
1067 i += 32;
|
|
1068
|
|
1069 fh->flags = aimutil_get8(hdr+i);
|
|
1070 i += 1;
|
|
1071 fh->lnameoffset = aimutil_get8(hdr+i);
|
|
1072 i += 1;
|
|
1073 fh->lsizeoffset = aimutil_get8(hdr+i);
|
|
1074 i += 1;
|
|
1075
|
|
1076 memcpy(fh->dummy, hdr+i, 69);
|
|
1077 i += 69;
|
|
1078
|
|
1079 memcpy(fh->macfileinfo, hdr+i, 16);
|
|
1080 i += 16;
|
|
1081
|
|
1082 fh->nencode = aimutil_get16(hdr+i);
|
|
1083 i += 2;
|
|
1084 fh->nlanguage = aimutil_get16(hdr+i);
|
|
1085 i += 2;
|
|
1086
|
|
1087 memcpy(fh->name, hdr+i, 64);
|
|
1088 i += 64;
|
|
1089
|
|
1090 return fh;
|
|
1091 }
|