comparison src/rvous.c @ 261:aebbe6ca6919

[gaim-migrate @ 271] Get File works. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Thu, 25 May 2000 04:15:46 +0000
parents 325d9804df10
children ced25773243c
comparison
equal deleted inserted replaced
260:325d9804df10 261:aebbe6ca6919
37 #include "gaim.h" 37 #include "gaim.h"
38 38
39 static void do_send_file(GtkWidget *, struct file_transfer *); 39 static void do_send_file(GtkWidget *, struct file_transfer *);
40 static void do_get_file (GtkWidget *, struct file_transfer *); 40 static void do_get_file (GtkWidget *, struct file_transfer *);
41 41
42 static int snpa = -1;
43
42 static void toggle(GtkWidget *w, int *m) 44 static void toggle(GtkWidget *w, int *m)
43 { 45 {
44 *m = !(*m); 46 *m = !(*m);
45 } 47 }
46 48
76 free_ft(ft); 78 free_ft(ft);
77 } 79 }
78 80
79 static void accept_callback(GtkWidget *widget, struct file_transfer *ft) 81 static void accept_callback(GtkWidget *widget, struct file_transfer *ft)
80 { 82 {
81 char *buf = g_malloc(BUF_LEN); 83 char buf[BUF_LEN];
82 char *fname = g_malloc(BUF_LEN); 84 char fname[BUF_LEN];
83 char *c; 85 char *c;
84 86
85 if (!strcmp(ft->UID, FILE_SEND_UID)) { 87 if (!strcmp(ft->UID, FILE_SEND_UID)) {
86 c = ft->filename + strlen(ft->filename); 88 c = ft->filename + strlen(ft->filename);
87 89
124 } 126 }
125 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(ft->window)->cancel_button), 127 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(ft->window)->cancel_button),
126 "clicked", GTK_SIGNAL_FUNC(cancel_callback), ft); 128 "clicked", GTK_SIGNAL_FUNC(cancel_callback), ft);
127 129
128 gtk_widget_show(ft->window); 130 gtk_widget_show(ft->window);
129
130 g_free(buf);
131 g_free(fname);
132 } 131 }
133 132
134 static int read_file_header(int fd, struct file_header *header) { 133 static int read_file_header(int fd, struct file_header *header) {
135 char buf[257]; 134 char buf[257];
136 int read_rv = read(fd, buf, 256); 135 int read_rv = read(fd, buf, 256);
136 if (read_rv < 0)
137 return read_rv;
137 memcpy(&header->magic, buf + 0, 4); 138 memcpy(&header->magic, buf + 0, 4);
138 memcpy(&header->hdrlen, buf + 4, 2); 139 memcpy(&header->hdrlen, buf + 4, 2);
139 memcpy(&header->hdrtype, buf + 6, 2); 140 memcpy(&header->hdrtype, buf + 6, 2);
140 memcpy(&header->bcookie, buf + 8, 8); 141 memcpy(&header->bcookie, buf + 8, 8);
141 memcpy(&header->encrypt, buf + 16, 2); 142 memcpy(&header->encrypt, buf + 16, 2);
200 return write(fd, buf, 256); 201 return write(fd, buf, 256);
201 } 202 }
202 203
203 static void do_get_file(GtkWidget *w, struct file_transfer *ft) 204 static void do_get_file(GtkWidget *w, struct file_transfer *ft)
204 { 205 {
205 char *send = g_malloc(256);
206 char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(ft->window)); 206 char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(ft->window));
207 char *buf; 207 char buf[BUF_LONG];
208 struct file_header *header = g_new0(struct file_header, 1); 208 char *buf2;
209 struct file_header header;
209 int read_rv; 210 int read_rv;
210 guint32 rcv; 211 guint32 rcv;
211 char *c; 212 char *c;
212 int cont = 1; 213 int cont = 1;
213 GtkWidget *fw = NULL, *fbar = NULL, *label = NULL; 214 GtkWidget *fw = NULL, *fbar = NULL, *label = NULL;
214 GtkWidget *button = NULL, *pct = NULL; 215 GtkWidget *button = NULL, *pct = NULL;
215 216
216 if (!(ft->f = fopen(file,"w"))) { 217 if (!(ft->f = fopen(file,"w"))) {
217 buf = g_malloc(BUF_LONG);
218 g_snprintf(buf, BUF_LONG / 2, "Error writing file %s", file); 218 g_snprintf(buf, BUF_LONG / 2, "Error writing file %s", file);
219 do_error_dialog(buf, "Error"); 219 do_error_dialog(buf, "Error");
220 g_free(buf);
221 g_free(header);
222 ft->accepted = 0; 220 ft->accepted = 0;
223 accept_callback(NULL, ft); 221 accept_callback(NULL, ft);
224 return; 222 return;
225 } 223 }
226 224
227 ft->accepted = 1; 225 ft->accepted = 1;
228 226
229 gtk_widget_destroy(ft->window); 227 gtk_widget_destroy(ft->window);
230 ft->window = NULL; 228 ft->window = NULL;
231 serv_rvous_accept(ft->user, ft->cookie, ft->UID); 229 serv_rvous_accept(ft->user, ft->cookie, ft->UID);
232 g_free(send);
233 230
234 231
235 ft->fd = connect_address(inet_addr(ft->ip), ft->port); 232 ft->fd = connect_address(inet_addr(ft->ip), ft->port);
236 233
237 if (ft->fd <= -1) { 234 if (ft->fd <= -1) {
238 g_free(header);
239 fclose(ft->f); 235 fclose(ft->f);
240 free_ft(ft); 236 free_ft(ft);
241 return; 237 return;
242 } 238 }
243 239
244 read_rv = read_file_header(ft->fd, header); 240 read_rv = read_file_header(ft->fd, &header);
245 if(read_rv < 0) { 241 if(read_rv < 0) {
246 close(ft->fd); 242 close(ft->fd);
247 fclose(ft->f); 243 fclose(ft->f);
248 g_free(header); 244 free_ft(ft);
249 free_ft(ft); 245 return;
250 return; 246 }
251 } 247
252 248 sprintf(debug_buff, "header length %d\n", header.hdrlen);
253 sprintf(debug_buff, "header length %d\n", header->hdrlen); 249 debug_print(debug_buff);
254 debug_print(debug_buff); 250
255 251 header.hdrtype = 0x202;
256 header->hdrtype = 0x202;
257 252
258 buf = frombase64(ft->cookie); 253 buf2 = frombase64(ft->cookie);
259 memcpy(header->bcookie, buf, 8); 254 memcpy(header.bcookie, buf2, 8);
260 g_free(buf); 255 snprintf(header.idstring, 32, "Gaim");
261 snprintf(header->idstring, 32, "Gaim"); 256 g_free(buf2);
262 header->encrypt = 0; header->compress = 0; 257 header.encrypt = 0; header.compress = 0;
263 header->totparts = 1; header->partsleft = 1; 258 header.totparts = 1; header.partsleft = 1;
264 259
265 sprintf(debug_buff, "sending confirmation\n"); 260 sprintf(debug_buff, "sending confirmation\n");
266 debug_print(debug_buff); 261 debug_print(debug_buff);
267 write_file_header(ft->fd, header); 262 write_file_header(ft->fd, &header);
268 263
269 buf = g_malloc(2048);
270 rcv = 0; 264 rcv = 0;
271 265
272 fw = gtk_dialog_new(); 266 fw = gtk_dialog_new();
273 buf = g_malloc(2048);
274 snprintf(buf, 2048, "Receiving %s from %s", ft->filename, ft->user); 267 snprintf(buf, 2048, "Receiving %s from %s", ft->filename, ft->user);
275 label = gtk_label_new(buf); 268 label = gtk_label_new(buf);
276 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->vbox), label, 0, 0, 5); 269 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->vbox), label, 0, 0, 5);
277 gtk_widget_show(label); 270 gtk_widget_show(label);
278 fbar = gtk_progress_bar_new(); 271 fbar = gtk_progress_bar_new();
309 } 302 }
310 gtk_widget_destroy(fw); 303 gtk_widget_destroy(fw);
311 fw = NULL; 304 fw = NULL;
312 fclose(ft->f); 305 fclose(ft->f);
313 close(ft->fd); 306 close(ft->fd);
314 g_free(buf);
315 g_free(header);
316 free_ft(ft); 307 free_ft(ft);
317 return; 308 return;
318 } 309 }
319 rcv += read_rv; 310 rcv += read_rv;
320 for (i = 0; i < read_rv; i++) 311 for (i = 0; i < read_rv; i++)
332 if (!cont) { 323 if (!cont) {
333 char *tmp = frombase64(ft->cookie); 324 char *tmp = frombase64(ft->cookie);
334 serv_rvous_cancel(ft->user, tmp, ft->UID); 325 serv_rvous_cancel(ft->user, tmp, ft->UID);
335 close(ft->fd); 326 close(ft->fd);
336 free_ft(ft); 327 free_ft(ft);
337 g_free(header);
338 return; 328 return;
339 } 329 }
340 330
341 sprintf(debug_buff, "Download complete.\n"); 331 sprintf(debug_buff, "Download complete.\n");
342 debug_print(debug_buff); 332 debug_print(debug_buff);
343 333
344 header->hdrtype = 0x402; 334 header.hdrtype = 0x402;
345 header->totparts = 0; header->partsleft = 0; 335 header.totparts = 0; header.partsleft = 0;
346 header->flags = 0; 336 header.flags = 0;
347 header->recvcsum = header->checksum; 337 header.recvcsum = header.checksum;
348 header->nrecvd = header->totsize; 338 header.nrecvd = header.totsize;
349 write_file_header(ft->fd, header); 339 write_file_header(ft->fd, &header);
350 close(ft->fd); 340 close(ft->fd);
351 341
352 g_free(buf);
353 g_free(header);
354 free_ft(ft); 342 free_ft(ft);
355 } 343 }
356 344
357 static void do_send_file(GtkWidget *w, struct file_transfer *ft) { 345 static void send_file_callback(gpointer data, gint source,
358 char *send = g_malloc(256); 346 GdkInputCondition condition) {
359 char *file = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(ft->window))); 347 struct file_transfer *ft = (struct file_transfer *)data;
360 char *buf; 348 struct file_header fhdr;
361 int read_rv; 349 int read_rv;
362 struct file_header *fhdr = g_new0(struct file_header, 1); 350 char buf[2048];
363 struct sockaddr_in sin;
364 guint32 rcv;
365 int cont;
366 char *c;
367 struct stat st;
368 struct tm *fortime;
369 GtkWidget *fw = NULL, *fbar = NULL, *label = NULL; 351 GtkWidget *fw = NULL, *fbar = NULL, *label = NULL;
370 GtkWidget *button = NULL, *pct = NULL; 352 GtkWidget *button = NULL, *pct = NULL;
371 353 int rcv, cont;
372 stat(file, &st); 354
373 if (!(ft->f = fopen(file, "r"))) { 355 gdk_input_remove(snpa);
374 buf = g_malloc(BUF_LONG); 356 snpa = -1;
375 g_snprintf(buf, BUF_LONG / 2, "Error reading file %s", file); 357
376 do_error_dialog(buf, "Error"); 358 if (condition & GDK_INPUT_EXCEPTION) {
377 g_free(buf); 359 fclose(ft->f);
378 ft->accepted = 0; 360 close(ft->fd);
379 accept_callback(NULL, ft); 361 free_ft(ft);
380 free_ft(ft); 362 return;
381 return; 363 }
382 } 364
383 365 /* OK, so here's what's going on: we need to send a file. The person
384 ft->accepted = 1; 366 * sends us a file_header, then we send a file_header, then they send
385 367 * us a file header, then we send the file, then they send a header,
386 gtk_widget_destroy(ft->window); 368 * and we're done. */
387 ft->window = NULL; 369
388 serv_rvous_accept(ft->user, ft->cookie, ft->UID); 370 /* we can do some neat tricks because the other person sends us back
389 g_free(send); 371 * all the information we need in the file_header */
390 372
391 373 read_rv = read_file_header(ft->fd, &fhdr);
392 374 if (read_rv < 0) {
393 ft->fd = connect_address(inet_addr(ft->ip), ft->port); 375 fclose(ft->f);
394 376 close(ft->fd);
395 if (ft->fd <= -1) { 377 free_ft(ft);
396 g_free(fhdr); 378 return;
397 free_ft(ft); 379 }
398 return; 380
399 } 381 if (ntohs(fhdr.hdrtype) != 0xc12) {
400 382 sprintf(debug_buff, "%s decided to cancel.\n", ft->user);
401 /* here's where we differ from do_get_file */
402 /* 1. build/send header
403 * 2. receive header
404 * 3. send listing file
405 * 4. receive header
406 *
407 * then we need to wait to actually send the file.
408 *
409 * 5. either (receive header) or (remote host cancels)
410 * 6. if received header, send file
411 * 7. ? haven't gotten this far yet
412 */
413
414 /* 1. build/send header */
415 c = file + strlen(file);
416 while (*(c - 1) != '/') c--;
417 buf = frombase64(ft->cookie);
418 sprintf(debug_buff, "Building header to send %s (cookie: %s)\n", file, buf);
419 debug_print(debug_buff);
420 fhdr->magic[0] = 'O'; fhdr->magic[1] = 'F';
421 fhdr->magic[2] = 'T'; fhdr->magic[3] = '2';
422 fhdr->hdrlen = htons(256);
423 fhdr->hdrtype = htons(0x1108);
424 snprintf(fhdr->bcookie, 8, "%s", buf);
425 g_free(buf);
426 fhdr->encrypt = 0;
427 fhdr->compress = 0;
428 fhdr->totfiles = htons(1);
429 fhdr->filesleft = htons(1);
430 fhdr->totparts = htons(1);
431 fhdr->partsleft = htons(1);
432 fhdr->totsize = htonl((long)st.st_size); /* combined size of all files */
433 /* size = strlen("mm/dd/yyyy hh:mm sizesize 'name'\r\n") */
434 fhdr->size = htonl(28 + strlen(c)); /* size of listing.txt */
435 fhdr->modtime = htonl(time(NULL)); /* time since UNIX epoch */
436 fhdr->checksum = htonl(0x89f70000); /* ? i don't think this matters */
437 fhdr->rfrcsum = 0;
438 fhdr->rfsize = 0;
439 fhdr->cretime = 0;
440 fhdr->rfcsum = 0;
441 fhdr->nrecvd = 0;
442 fhdr->recvcsum = 0;
443 snprintf(fhdr->idstring, 32, "OFT_Windows ICBMFT V1.1 32");
444 fhdr->flags = 0x02; /* don't ask me why */
445 fhdr->lnameoffset = 0x1A; /* ? still no clue */
446 fhdr->lsizeoffset = 0x10; /* whatever */
447 memset(fhdr->dummy, 0, 69);
448 memset(fhdr->macfileinfo, 0, 16);
449 fhdr->nencode = 0;
450 fhdr->nlanguage = 0;
451 snprintf(fhdr->name, 64, "listing.txt");
452 read_rv = write_file_header(ft->fd, fhdr);
453 if (read_rv <= -1) {
454 sprintf(debug_buff, "Couldn't write opening header\n");
455 debug_print(debug_buff); 383 debug_print(debug_buff);
456 g_free(fhdr); 384 fclose(ft->f);
457 close(ft->fd); 385 close(ft->fd);
458 free_ft(ft); 386 free_ft(ft);
459 return; 387 return;
460 } 388 }
461 389
462 /* 2. receive header */ 390 /* now we need to set the hdrtype to a certain value, but I don't know
463 sprintf(debug_buff, "Receiving header\n"); 391 * what that value is, and I don't happen to have a win computer to do
464 debug_print(debug_buff); 392 * my sniffing from :-P */
465 read_rv = read_file_header(ft->fd, fhdr); 393 fhdr.hdrtype = ntohs(0x101);
466 if (read_rv <= -1) { 394 fhdr.totfiles = 1;
467 sprintf(debug_buff, "Couldn't read header\n"); 395 fhdr.filesleft = 1;
468 debug_print(debug_buff); 396 fhdr.flags = 0x20;
469 g_free(fhdr); 397 write_file_header(ft->fd, &fhdr);
470 close(ft->fd); 398 read_file_header(ft->fd, &fhdr);
471 free_ft(ft); 399
472 return;
473 }
474
475 /* 3. qend listing file */
476 /* mm/dd/yyyy hh:mm sizesize name.ext\r\n */
477 /* creation date ^ */
478 sprintf(debug_buff, "Sending file\n");
479 debug_print(debug_buff);
480 buf = g_malloc(ft->size + 1);
481 fortime = localtime(&st.st_ctime);
482 snprintf(buf, ntohl(fhdr->size) + 1, "%2d/%2d/%4d %2d:%2d %8ld %s\r\n",
483 fortime->tm_mon + 1, fortime->tm_mday, fortime->tm_year + 1900,
484 fortime->tm_hour + 1, fortime->tm_min + 1,
485 st.st_size, c);
486 sprintf(debug_buff, "Sending listing.txt (%ld bytes) to %s\n",
487 ntohl(fhdr->size) + 1, ft->user);
488 debug_print(debug_buff);
489
490 read_rv = write(ft->fd, buf, ntohl(fhdr->size));
491 if (read_rv <= -1) {
492 sprintf(debug_buff, "Could not send file, wrote %d\n", rcv);
493 debug_print(debug_buff);
494 g_free(buf);
495 g_free(fhdr);
496 close(ft->fd);
497 free_ft(ft);
498 return;
499 }
500 g_free(buf);
501
502 /* 4. receive header */
503 sprintf(debug_buff, "Receiving closing header\n");
504 debug_print(debug_buff);
505 read_rv = read_file_header(ft->fd, fhdr);
506 if (read_rv <= -1) {
507 sprintf(debug_buff, "Couldn't read closing header\n");
508 debug_print(debug_buff);
509 g_free(fhdr);
510 close(ft->fd);
511 free_ft(ft);
512 return;
513 }
514
515 /* 5. wait to see if we're sending it */
516 fcntl(ft->fd, F_SETFL, O_NONBLOCK);
517 rcv = 0;
518 while (rcv != 256) {
519 int i;
520 read_rv = read_file_header(ft->fd, fhdr);
521 if(read_rv < 0) {
522 if (errno == EWOULDBLOCK) {
523 while(gtk_events_pending())
524 gtk_main_iteration();
525 continue;
526 }
527 fclose(ft->f);
528 close(ft->fd);
529 g_free(fhdr);
530 free_ft(ft);
531 return;
532 }
533 rcv += read_rv;
534 }
535
536 /* 6. send the file */
537 fw = gtk_dialog_new(); 400 fw = gtk_dialog_new();
538 buf = g_malloc(2048); 401 snprintf(buf, 2048, "Sending %s to %s", fhdr.name, ft->user);
539 snprintf(buf, 2048, "Sending %s to %s", fhdr->name, ft->user);
540 label = gtk_label_new(buf); 402 label = gtk_label_new(buf);
541 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->vbox), label, 0, 0, 5); 403 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->vbox), label, 0, 0, 5);
542 gtk_widget_show(label); 404 gtk_widget_show(label);
543 fbar = gtk_progress_bar_new(); 405 fbar = gtk_progress_bar_new();
544 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), fbar, 0, 0, 5); 406 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), fbar, 0, 0, 5);
545 gtk_widget_show(fbar); 407 gtk_widget_show(fbar);
546 pct = gtk_label_new("0 %"); 408 pct = gtk_label_new("0 %");
547 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), pct, 0, 0, 5); 409 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), pct, 0, 0, 5);
548 gtk_widget_show(pct); 410 gtk_widget_show(pct);
549 button = gtk_button_new_with_label("Cancel"); 411 button = gtk_button_new_with_label("Cancel");
550 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), button, 0, 0, 5); 412 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fw)->action_area), button, 0, 0, 5);
551 gtk_widget_show(button); 413 gtk_widget_show(button);
552 gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)toggle, &cont); 414 gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)toggle, &cont);
553 gtk_window_set_title(GTK_WINDOW(fw), "Gaim - File Transfer"); 415 gtk_window_set_title(GTK_WINDOW(fw), "Gaim - File Transfer");
554 gtk_widget_realize(fw); 416 gtk_widget_realize(fw);
555 aol_icon(fw->window); 417 aol_icon(fw->window);
556 gtk_widget_show(fw); 418 gtk_widget_show(fw);
557 419
558 sprintf(debug_buff, "Sending %s to %s (%d bytes)\n", fhdr->name, 420 sprintf(debug_buff, "Sending %s to %s (%d bytes)\n", fhdr.name,
559 ft->user, fhdr->totsize); 421 ft->user, fhdr.totsize);
560 debug_print(debug_buff); 422 debug_print(debug_buff);
561 423
562 rcv = 0; cont = 1; 424 rcv = 0; cont = 1;
563 while (rcv != fhdr->totsize && cont) { 425 while (rcv != ntohl(fhdr.totsize) && cont) {
564 int i; 426 int i;
565 float pcnt = ((float)rcv)/((float)fhdr->totsize); 427 float pcnt = ((float)rcv)/((float)ntohl(fhdr.totsize));
566 int remain = fhdr->totsize - rcv > 1024 ? 1024 : fhdr->totsize - rcv; 428 int remain = ntohl(fhdr.totsize) - rcv > 1024 ? 1024 :
567 for (i = 0; i < 1024; i++) 429 ntohl(fhdr.totsize) - rcv;
430 for (i = 0; i < remain; i++)
568 fscanf(ft->f, "%c", &buf[i]); 431 fscanf(ft->f, "%c", &buf[i]);
569 read_rv = write(ft->fd, buf, remain); 432 read_rv = write(ft->fd, buf, remain);
570 if (read_rv < 0) { 433 if (read_rv < 0) {
571 if (errno == EWOULDBLOCK) {
572 while (gtk_events_pending())
573 gtk_main_iteration();
574 continue;
575 }
576 fclose(ft->f); 434 fclose(ft->f);
577 gtk_widget_destroy(fw); 435 gtk_widget_destroy(fw);
578 fw = NULL; 436 fw = NULL;
579 fclose(ft->f); 437 fclose(ft->f);
580 close(ft->fd); 438 close(ft->fd);
581 g_free(buf);
582 g_free(fhdr);
583 free_ft(ft); 439 free_ft(ft);
584 return; 440 return;
585 } 441 }
586 rcv += read_rv; 442 rcv += read_rv;
587 gtk_progress_bar_update(GTK_PROGRESS_BAR(fbar), pcnt); 443 gtk_progress_bar_update(GTK_PROGRESS_BAR(fbar), pcnt);
588 sprintf(buf, "%d / %d K (%2.0f %%)", rcv/1024, ft->size/1024, 100*pcnt); 444 sprintf(buf, "%d / %d K (%2.0f %%)", rcv/1024,
445 ntohl(fhdr.totsize)/1024, 100*pcnt);
589 gtk_label_set_text(GTK_LABEL(pct), buf); 446 gtk_label_set_text(GTK_LABEL(pct), buf);
590 while(gtk_events_pending()) 447 while(gtk_events_pending())
591 gtk_main_iteration(); 448 gtk_main_iteration();
592 } 449 }
593 fclose(ft->f); 450 fclose(ft->f);
595 fw = NULL; 452 fw = NULL;
596 453
597 if (!cont) { 454 if (!cont) {
598 char *tmp = frombase64(ft->cookie); 455 char *tmp = frombase64(ft->cookie);
599 serv_rvous_cancel(ft->user, tmp, ft->UID); 456 serv_rvous_cancel(ft->user, tmp, ft->UID);
600 g_free(buf); 457 close(ft->fd);
601 close(ft->fd); 458 free_ft(ft);
602 free_ft(ft);
603 g_free(fhdr);
604 return; 459 return;
605 } 460 }
606 461
607 sprintf(debug_buff, "Upload complete.\n"); 462 sprintf(debug_buff, "Upload complete.\n");
608 debug_print(debug_buff); 463 debug_print(debug_buff);
609 464
610 /* 7. receive closing header */ 465 read_file_header(ft->fd, &fhdr);
611 466
612 /* done */
613 close(ft->fd); 467 close(ft->fd);
614 g_free(buf);
615 g_free(fhdr);
616 free_ft(ft); 468 free_ft(ft);
469 }
470
471 static void do_send_file(GtkWidget *w, struct file_transfer *ft) {
472 char *file = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(ft->window)));
473 char buf[BUF_LONG];
474 char *buf2;
475 int read_rv;
476 struct file_header fhdr;
477 struct sockaddr_in sin;
478 guint32 rcv;
479 int cont;
480 char *c;
481 struct stat st;
482 struct tm *fortime;
483
484 stat(file, &st);
485 if (!(ft->f = fopen(file, "r"))) {
486 g_snprintf(buf, BUF_LONG / 2, "Error reading file %s", file);
487 do_error_dialog(buf, "Error");
488 ft->accepted = 0;
489 accept_callback(NULL, ft);
490 free_ft(ft);
491 return;
492 }
493
494 ft->accepted = 1;
495 ft->filename = file;
496
497 gtk_widget_destroy(ft->window);
498 ft->window = NULL;
499 serv_rvous_accept(ft->user, ft->cookie, ft->UID);
500
501
502
503 ft->fd = connect_address(inet_addr(ft->ip), ft->port);
504
505 if (ft->fd <= -1) {
506 free_ft(ft);
507 return;
508 }
509
510 /* here's where we differ from do_get_file */
511 /* 1. build/send header
512 * 2. receive header
513 * 3. send listing file
514 * 4. receive header
515 *
516 * then we need to wait to actually send the file, if they want.
517 *
518 */
519
520 /* 1. build/send header */
521 c = file + strlen(file);
522 while (*(c - 1) != '/') c--;
523 buf2 = frombase64(ft->cookie);
524 sprintf(debug_buff, "Building header to send %s (cookie: %s)\n", file, buf2);
525 debug_print(debug_buff);
526 fhdr.magic[0] = 'O'; fhdr.magic[1] = 'F';
527 fhdr.magic[2] = 'T'; fhdr.magic[3] = '2';
528 fhdr.hdrlen = htons(256);
529 fhdr.hdrtype = htons(0x1108);
530 snprintf(fhdr.bcookie, 8, "%s", buf2);
531 g_free(buf2);
532 fhdr.encrypt = 0;
533 fhdr.compress = 0;
534 fhdr.totfiles = htons(1);
535 fhdr.filesleft = htons(1);
536 fhdr.totparts = htons(1);
537 fhdr.partsleft = htons(1);
538 fhdr.totsize = htonl((long)st.st_size); /* combined size of all files */
539 /* size = strlen("mm/dd/yyyy hh:mm sizesize 'name'\r\n") */
540 fhdr.size = htonl(28 + strlen(c)); /* size of listing.txt */
541 fhdr.modtime = htonl(time(NULL)); /* time since UNIX epoch */
542 fhdr.checksum = htonl(0x89f70000); /* ? i don't think this matters */
543 fhdr.rfrcsum = 0;
544 fhdr.rfsize = 0;
545 fhdr.cretime = 0;
546 fhdr.rfcsum = 0;
547 fhdr.nrecvd = 0;
548 fhdr.recvcsum = 0;
549 snprintf(fhdr.idstring, 32, "OFT_Windows ICBMFT V1.1 32");
550 fhdr.flags = 0x02; /* don't ask me why */
551 fhdr.lnameoffset = 0x1A; /* ? still no clue */
552 fhdr.lsizeoffset = 0x10; /* whatever */
553 memset(fhdr.dummy, 0, 69);
554 memset(fhdr.macfileinfo, 0, 16);
555 fhdr.nencode = 0;
556 fhdr.nlanguage = 0;
557 snprintf(fhdr.name, 64, "listing.txt");
558 read_rv = write_file_header(ft->fd, &fhdr);
559 if (read_rv <= -1) {
560 sprintf(debug_buff, "Couldn't write opening header\n");
561 debug_print(debug_buff);
562 close(ft->fd);
563 free_ft(ft);
564 return;
565 }
566
567 /* 2. receive header */
568 sprintf(debug_buff, "Receiving header\n");
569 debug_print(debug_buff);
570 read_rv = read_file_header(ft->fd, &fhdr);
571 if (read_rv <= -1) {
572 sprintf(debug_buff, "Couldn't read header\n");
573 debug_print(debug_buff);
574 close(ft->fd);
575 free_ft(ft);
576 return;
577 }
578
579 /* 3. send listing file */
580 /* mm/dd/yyyy hh:mm sizesize name.ext\r\n */
581 /* creation date ^ */
582 sprintf(debug_buff, "Sending file\n");
583 debug_print(debug_buff);
584 fortime = localtime(&st.st_ctime);
585 snprintf(buf, ntohl(fhdr.size) + 1, "%2d/%2d/%4d %2d:%2d %8ld %s\r\n",
586 fortime->tm_mon + 1, fortime->tm_mday, fortime->tm_year + 1900,
587 fortime->tm_hour + 1, fortime->tm_min + 1,
588 st.st_size, c);
589 sprintf(debug_buff, "Sending listing.txt (%ld bytes) to %s\n",
590 ntohl(fhdr.size) + 1, ft->user);
591 debug_print(debug_buff);
592
593 read_rv = write(ft->fd, buf, ntohl(fhdr.size));
594 if (read_rv <= -1) {
595 sprintf(debug_buff, "Could not send file, wrote %d\n", rcv);
596 debug_print(debug_buff);
597 close(ft->fd);
598 free_ft(ft);
599 return;
600 }
601
602 /* 4. receive header */
603 sprintf(debug_buff, "Receiving closing header\n");
604 debug_print(debug_buff);
605 read_rv = read_file_header(ft->fd, &fhdr);
606 if (read_rv <= -1) {
607 sprintf(debug_buff, "Couldn't read closing header\n");
608 debug_print(debug_buff);
609 close(ft->fd);
610 free_ft(ft);
611 return;
612 }
613
614 snpa = gdk_input_add(ft->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
615 send_file_callback, ft);
616
617 } 617 }
618 618
619 void accept_file_dialog(struct file_transfer *ft) 619 void accept_file_dialog(struct file_transfer *ft)
620 { 620 {
621 GtkWidget *accept, *info, *warn, *cancel; 621 GtkWidget *accept, *info, *warn, *cancel;