| 586 return; |
607 return; |
| 587 } |
608 } |
| 588 |
609 |
| 589 name = tmp + 8; |
610 name = tmp + 8; |
| 590 |
611 |
| 591 ft = g_new0(struct file_transfer, 1); |
612 ft = g_new0(struct ft_request, 1); |
| 592 ft->cookie = g_strdup(cookie); |
613 ft->cookie = g_strdup(cookie); |
| 593 ft->ip = g_strdup(pip); |
614 ft->ip = g_strdup(pip); |
| 594 ft->port = port; |
615 ft->port = port; |
| 595 if (i) |
616 if (i) |
| 596 ft->message = g_strdup(messages[0]); |
617 ft->message = g_strdup(messages[0]); |
| 597 else |
618 else |
| 598 ft->message = NULL; |
619 ft->message = NULL; |
| 599 ft->filename = g_strdup(name); |
620 ft->filename = g_strdup(name); |
| 600 ft->user = g_strdup(user); |
621 ft->user = g_strdup(user); |
| 601 ft->size = totalsize; |
622 ft->size = totalsize; |
| |
623 ft->files = files; |
| 602 g_snprintf(ft->UID, sizeof(ft->UID), "%s", FILE_SEND_UID); |
624 g_snprintf(ft->UID, sizeof(ft->UID), "%s", FILE_SEND_UID); |
| 603 ft->gc = gc; |
625 ft->gc = gc; |
| 604 |
626 |
| 605 g_free(tmp); |
627 g_free(tmp); |
| 606 for (i--; i >= 0; i--) |
628 for (i--; i >= 0; i--) |
| 607 g_free(messages[i]); |
629 g_free(messages[i]); |
| 608 |
630 |
| |
631 debug_printf("English translation of RVOUS_PROPOSE: %s requests Send File (i.e." |
| |
632 " send a file to you); %s:%d (verified_ip:port), %d files at" |
| |
633 " total size of %ld bytes.\n", user, vip, port, files, totalsize); |
| 609 accept_file_dialog(ft); |
634 accept_file_dialog(ft); |
| 610 } else if (!strcmp(uuid, FILE_GET_UID)) { |
635 } else if (!strcmp(uuid, FILE_GET_UID)) { |
| 611 /* they want us to send a file */ |
636 /* they want us to send a file |
| 612 int unk[4], i; |
637 int unk[4], i; |
| 613 char *messages[4], *tmp; |
638 char *messages[4], *tmp; |
| 614 struct file_transfer *ft; |
639 struct ft_request *ft; |
| 615 |
640 |
| 616 for (i = 0; i < 4; i++) { |
641 for (i = 0; i < 4; i++) { |
| 617 sscanf(strtok(NULL, ":"), "%d", unk + i); |
642 sscanf(strtok(NULL, ":"), "%d", unk + i); |
| 618 if (unk[i] == 10001) |
643 if (unk[i] == 10001) |
| 619 break; |
644 break; |
| 620 messages[i] = frombase64(strtok(NULL, ":")); |
645 messages[i] = frombase64(strtok(NULL, ":")); |
| 621 } |
646 } |
| 622 tmp = frombase64(strtok(NULL, ":")); |
647 tmp = frombase64(strtok(NULL, ":")); |
| 623 |
648 |
| 624 ft = g_new0(struct file_transfer, 1); |
649 ft = g_new0(struct ft_request, 1); |
| 625 ft->cookie = g_strdup(cookie); |
650 ft->cookie = g_strdup(cookie); |
| 626 ft->ip = g_strdup(pip); |
651 ft->ip = g_strdup(pip); |
| 627 ft->port = port; |
652 ft->port = port; |
| 628 if (i) |
653 if (i) |
| 629 ft->message = g_strdup(messages[0]); |
654 ft->message = g_strdup(messages[0]); |
| 1217 ret->chat_leave = toc_chat_leave; |
1243 ret->chat_leave = toc_chat_leave; |
| 1218 ret->chat_whisper = toc_chat_whisper; |
1244 ret->chat_whisper = toc_chat_whisper; |
| 1219 ret->chat_send = toc_chat_send; |
1245 ret->chat_send = toc_chat_send; |
| 1220 ret->keepalive = toc_keepalive; |
1246 ret->keepalive = toc_keepalive; |
| 1221 } |
1247 } |
| |
1248 |
| |
1249 /********* |
| |
1250 * RVOUS ACTIONS |
| |
1251 ********/ |
| |
1252 |
| |
1253 struct file_header { |
| |
1254 char magic[4]; /* 0 */ |
| |
1255 short hdrlen; /* 4 */ |
| |
1256 short hdrtype; /* 6 */ |
| |
1257 char bcookie[8]; /* 8 */ |
| |
1258 short encrypt; /* 16 */ |
| |
1259 short compress; /* 18 */ |
| |
1260 short totfiles; /* 20 */ |
| |
1261 short filesleft; /* 22 */ |
| |
1262 short totparts; /* 24 */ |
| |
1263 short partsleft; /* 26 */ |
| |
1264 long totsize; /* 28 */ |
| |
1265 long size; /* 32 */ |
| |
1266 long modtime; /* 36 */ |
| |
1267 long checksum; /* 40 */ |
| |
1268 long rfrcsum; /* 44 */ |
| |
1269 long rfsize; /* 48 */ |
| |
1270 long cretime; /* 52 */ |
| |
1271 long rfcsum; /* 56 */ |
| |
1272 long nrecvd; /* 60 */ |
| |
1273 long recvcsum; /* 64 */ |
| |
1274 char idstring[32]; /* 68 */ |
| |
1275 char flags; /* 100 */ |
| |
1276 char lnameoffset; /* 101 */ |
| |
1277 char lsizeoffset; /* 102 */ |
| |
1278 char dummy[69]; /* 103 */ |
| |
1279 char macfileinfo[16]; /* 172 */ |
| |
1280 short nencode; /* 188 */ |
| |
1281 short nlanguage; /* 190 */ |
| |
1282 char name[64]; /* 192 */ |
| |
1283 /* 256 */ |
| |
1284 }; |
| |
1285 |
| |
1286 struct file_transfer { |
| |
1287 struct file_header hdr; |
| |
1288 |
| |
1289 struct gaim_connection *gc; |
| |
1290 |
| |
1291 char *user; |
| |
1292 char *cookie; |
| |
1293 char *ip; |
| |
1294 int port; |
| |
1295 long size; |
| |
1296 |
| |
1297 GtkWidget *window; |
| |
1298 FILE *file; |
| |
1299 int recvsize; |
| |
1300 |
| |
1301 gint inpa; |
| |
1302 }; |
| |
1303 |
| |
1304 static void toc_get_file(gpointer a, struct file_transfer *ft) { |
| |
1305 char *dirname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(ft->window)); |
| |
1306 |
| |
1307 if (file_is_dir(dirname, ft->window)) |
| |
1308 return; |
| |
1309 gtk_widget_destroy(ft->window); |
| |
1310 } |
| |
1311 |
| |
1312 static void debug_header(struct file_transfer *ft) { |
| |
1313 struct file_header *f = (struct file_header *)ft; |
| |
1314 debug_printf("TOC FT HEADER:\n" |
| |
1315 "\t%s %d 0x%04x\n" |
| |
1316 "\t%s %d %d\n" |
| |
1317 "\t%d %d %d %d %ld %ld\n" |
| |
1318 "\t%ld %ld %ld %ld %ld %ld %ld %ld\n" |
| |
1319 "\t%s\n" |
| |
1320 "\t0x%02x, 0x%02x, 0x%02x\n" |
| |
1321 "\t%s %s\n" |
| |
1322 "\t%d %d\n" |
| |
1323 "\t%s\n", |
| |
1324 f->magic, ntohs(f->hdrlen), f->hdrtype, |
| |
1325 f->bcookie, ntohs(f->encrypt), ntohs(f->compress), |
| |
1326 ntohs(f->totfiles), ntohs(f->filesleft), ntohs(f->totparts), |
| |
1327 ntohs(f->partsleft), ntohl(f->totsize), ntohl(f->size), |
| |
1328 ntohl(f->modtime), ntohl(f->checksum), ntohl(f->rfrcsum), ntohl(f->rfsize), |
| |
1329 ntohl(f->cretime), ntohl(f->rfcsum), ntohl(f->nrecvd), |
| |
1330 ntohl(f->recvcsum), |
| |
1331 f->idstring, |
| |
1332 f->flags, f->lnameoffset, f->lsizeoffset, |
| |
1333 f->dummy, f->macfileinfo, |
| |
1334 ntohs(f->nencode), ntohs(f->nlanguage), |
| |
1335 f->name); |
| |
1336 } |
| |
1337 |
| |
1338 static void toc_send_file_callback(gpointer data, gint source, GdkInputCondition cond) { |
| |
1339 char buf[BUF_LONG]; |
| |
1340 int rt, i; |
| |
1341 |
| |
1342 struct file_transfer *ft = data; |
| |
1343 |
| |
1344 if (cond & GDK_INPUT_EXCEPTION) { |
| |
1345 gdk_input_remove(ft->inpa); |
| |
1346 close(source); |
| |
1347 g_free(ft->user); |
| |
1348 g_free(ft->ip); |
| |
1349 g_free(ft->cookie); |
| |
1350 fclose(ft->file); |
| |
1351 g_free(ft); |
| |
1352 return; |
| |
1353 } |
| |
1354 |
| |
1355 if (ft->hdr.hdrtype != 0x202) { |
| |
1356 char *buf = frombase64(ft->cookie); |
| |
1357 |
| |
1358 read(source, ft, 8); |
| |
1359 read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); |
| |
1360 debug_header(ft); |
| |
1361 |
| |
1362 ft->hdr.hdrtype = 0x202; |
| |
1363 memcpy(ft->hdr.bcookie, buf, 8); |
| |
1364 g_free(buf); |
| |
1365 ft->hdr.encrypt = 0; ft->hdr.compress = 0; |
| |
1366 debug_header(ft); |
| |
1367 write(source, ft, 256); |
| |
1368 |
| |
1369 return; |
| |
1370 } |
| |
1371 |
| |
1372 rt = read(source, buf, MIN(ntohl(ft->hdr.size) - ft->recvsize, 1024)); |
| |
1373 if (rt < 0) { |
| |
1374 do_error_dialog("File transfer failed; other side probably canceled.", "Error"); |
| |
1375 gdk_input_remove(ft->inpa); |
| |
1376 close(source); |
| |
1377 g_free(ft->user); |
| |
1378 g_free(ft->ip); |
| |
1379 g_free(ft->cookie); |
| |
1380 fclose(ft->file); |
| |
1381 g_free(ft); |
| |
1382 return; |
| |
1383 } |
| |
1384 ft->recvsize += rt; |
| |
1385 for (i = 0; i < rt; i++) |
| |
1386 fprintf(ft->file, "%c", buf[i]); |
| |
1387 |
| |
1388 if (ft->recvsize == ntohl(ft->hdr.size)) { |
| |
1389 ft->hdr.hdrtype = 0x402; |
| |
1390 ft->hdr.filesleft = htons(ntohs(ft->hdr.filesleft) - 1); |
| |
1391 ft->hdr.partsleft = htons(ntohs(ft->hdr.partsleft) - 1); |
| |
1392 ft->hdr.recvcsum = ft->hdr.checksum; /* uh... */ |
| |
1393 ft->hdr.nrecvd = htons(ntohs(ft->hdr.nrecvd) + 1); |
| |
1394 ft->hdr.flags = 0; |
| |
1395 write(source, ft, 256); |
| |
1396 ft->recvsize = 0; |
| |
1397 if (ft->hdr.filesleft != 0) { |
| |
1398 char *msg = g_strdup_printf("%s tried to send you more than one file, but" |
| |
1399 " currently that is not possible.", ft->user); |
| |
1400 do_error_dialog(msg, "Error"); |
| |
1401 g_free(msg); |
| |
1402 } |
| |
1403 gdk_input_remove(ft->inpa); |
| |
1404 close(source); |
| |
1405 g_free(ft->user); |
| |
1406 g_free(ft->ip); |
| |
1407 g_free(ft->cookie); |
| |
1408 fclose(ft->file); |
| |
1409 g_free(ft); |
| |
1410 } |
| |
1411 } |
| |
1412 |
| |
1413 static void toc_send_file(gpointer a, struct file_transfer *old_ft) { |
| |
1414 struct file_transfer *ft; |
| |
1415 char *dirname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(old_ft->window)); |
| |
1416 int fd; |
| |
1417 struct aim_user *user; |
| |
1418 char *buf; |
| |
1419 |
| |
1420 if (file_is_dir(dirname, old_ft->window)) |
| |
1421 return; |
| |
1422 ft = g_new0(struct file_transfer, 1); |
| |
1423 ft->file = fopen(dirname, "w"); |
| |
1424 if (!ft->file) { |
| |
1425 do_error_dialog(_("Could not open file for writing!"), _("Error")); |
| |
1426 g_free(ft); |
| |
1427 gtk_widget_destroy(old_ft->window); |
| |
1428 return; |
| |
1429 } |
| |
1430 |
| |
1431 ft->cookie = g_strdup(old_ft->cookie); |
| |
1432 ft->user = g_strdup(old_ft->user); |
| |
1433 ft->ip = g_strdup(old_ft->ip); |
| |
1434 ft->port = old_ft->port; |
| |
1435 ft->gc = old_ft->gc; |
| |
1436 user = ft->gc->user; |
| |
1437 gtk_widget_destroy(old_ft->window); |
| |
1438 |
| |
1439 buf = g_strdup_printf("toc_rvous_accept %s %s %s", ft->user, ft->cookie, FILE_SEND_UID); |
| |
1440 sflap_send(ft->gc, buf, -1, TYPE_DATA); |
| |
1441 g_free(buf); |
| |
1442 |
| |
1443 fd = |
| |
1444 proxy_connect(ft->ip, ft->port, |
| |
1445 user->proto_opt[USEROPT_SOCKSHOST], |
| |
1446 atoi(user->proto_opt[USEROPT_SOCKSPORT]), |
| |
1447 atoi(user->proto_opt[USEROPT_PROXYTYPE])); |
| |
1448 if (fd < 0) { |
| |
1449 do_error_dialog(_("Could not connect for transfer!"), _("Error")); |
| |
1450 g_free(ft->cookie); |
| |
1451 g_free(ft->user); |
| |
1452 g_free(ft->ip); |
| |
1453 g_free(ft); |
| |
1454 return; |
| |
1455 } |
| |
1456 |
| |
1457 ft->inpa = gdk_input_add(fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, toc_send_file_callback, ft); |
| |
1458 } |
| |
1459 |
| |
1460 static void cancel_callback(gpointer a, struct file_transfer *ft) { |
| |
1461 gtk_widget_destroy(ft->window); |
| |
1462 if (a == ft->window) { |
| |
1463 g_free(ft->cookie); |
| |
1464 g_free(ft->user); |
| |
1465 g_free(ft->ip); |
| |
1466 g_free(ft); |
| |
1467 } |
| |
1468 } |
| |
1469 |
| |
1470 static void toc_accept_ft(gpointer a, struct ft_request *fr) { |
| |
1471 GtkWidget *window; |
| |
1472 char buf[BUF_LEN]; |
| |
1473 |
| |
1474 struct file_transfer *ft = g_new0(struct file_transfer, 1); |
| |
1475 ft->gc = fr->gc; |
| |
1476 ft->user = g_strdup(fr->user); |
| |
1477 ft->cookie = g_strdup(fr->cookie); |
| |
1478 ft->ip = g_strdup(fr->ip); |
| |
1479 ft->port = fr->port; |
| |
1480 |
| |
1481 ft->window = window = gtk_file_selection_new(_("Gaim - Save As...")); |
| |
1482 g_snprintf(buf, sizeof(buf), "%s/%s", g_get_home_dir(), fr->filename ? fr->filename : ""); |
| |
1483 gtk_file_selection_set_filename(GTK_FILE_SELECTION(window), buf); |
| |
1484 gtk_signal_connect(GTK_OBJECT(window), "destroy", |
| |
1485 GTK_SIGNAL_FUNC(cancel_callback), ft); |
| |
1486 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(ft->window)->cancel_button), "clicked", |
| |
1487 GTK_SIGNAL_FUNC(cancel_callback), ft); |
| |
1488 |
| |
1489 if (!strcmp(fr->UID, FILE_SEND_UID)) |
| |
1490 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(window)->ok_button), "clicked", |
| |
1491 GTK_SIGNAL_FUNC(toc_send_file), ft); |
| |
1492 else |
| |
1493 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(window)->ok_button), "clicked", |
| |
1494 GTK_SIGNAL_FUNC(toc_get_file), ft); |
| |
1495 |
| |
1496 gtk_widget_show(window); |
| |
1497 } |
| |
1498 |
| |
1499 static void toc_reject_ft(gpointer a, struct ft_request *ft) { |
| |
1500 g_free(ft->user); |
| |
1501 g_free(ft->filename); |
| |
1502 g_free(ft->ip); |
| |
1503 g_free(ft->cookie); |
| |
1504 if (ft->message) |
| |
1505 g_free(ft->message); |
| |
1506 g_free(ft); |
| |
1507 } |
| |
1508 |
| |
1509 static void accept_file_dialog(struct ft_request *ft) { |
| |
1510 char buf[BUF_LONG]; |
| |
1511 if (!strcmp(ft->UID, FILE_SEND_UID)) { |
| |
1512 /* holy crap. who the fuck would transfer gigabytes through AIM?! */ |
| |
1513 static char *sizes[4] = { "bytes", "KB", "MB", "GB" }; |
| |
1514 float size = ft->size; |
| |
1515 int index = 0; |
| |
1516 while ((index < 4) && (size > 1024)) { |
| |
1517 size /= 1024; |
| |
1518 index++; |
| |
1519 } |
| |
1520 g_snprintf(buf, sizeof(buf), _("%s requests %s to accept %d file%s: %s (%.2f %s)%s%s"), |
| |
1521 ft->user, ft->gc->username, ft->files, (ft->files == 1) ? "" : "s", |
| |
1522 ft->filename, size, sizes[index], (ft->message) ? "\n" : "", |
| |
1523 (ft->message) ? ft->message : ""); |
| |
1524 } else { |
| |
1525 g_snprintf(buf, sizeof(buf), _("%s requests you to send them a file"), ft->user); |
| |
1526 } |
| |
1527 do_ask_dialog(buf, ft, toc_accept_ft, toc_reject_ft); |
| |
1528 } |