Mercurial > pidgin
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; |