comparison src/toc.c @ 1457:c6f9d0cdaa00

[gaim-migrate @ 1467] all of toc in one file; rewritten file transfer. no get file yet; just send file. but why would you want to send files to people anyway? ;) committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Thu, 01 Feb 2001 11:29:15 +0000
parents f16e17d42b43
children d6340f73e94b
comparison
equal deleted inserted replaced
1456:6650776468b3 1457:c6f9d0cdaa00
44 #include "pixmaps/aol_icon.xpm" 44 #include "pixmaps/aol_icon.xpm"
45 #include "pixmaps/away_icon.xpm" 45 #include "pixmaps/away_icon.xpm"
46 #include "pixmaps/dt_icon.xpm" 46 #include "pixmaps/dt_icon.xpm"
47 #include "pixmaps/free_icon.xpm" 47 #include "pixmaps/free_icon.xpm"
48 48
49 #define REVISION "gaim:$Revision: 1445 $" 49 #define REVISION "gaim:$Revision: 1467 $"
50 50
51 #define TYPE_SIGNON 1 51 #define TYPE_SIGNON 1
52 #define TYPE_DATA 2 52 #define TYPE_DATA 2
53 #define TYPE_ERROR 3 53 #define TYPE_ERROR 3
54 #define TYPE_SIGNOFF 4 54 #define TYPE_SIGNOFF 4
66 #define STATE_OFFLINE 0 66 #define STATE_OFFLINE 0
67 #define STATE_FLAPON 1 67 #define STATE_FLAPON 1
68 #define STATE_SIGNON_REQUEST 2 68 #define STATE_SIGNON_REQUEST 2
69 #define STATE_ONLINE 3 69 #define STATE_ONLINE 3
70 #define STATE_PAUSE 4 70 #define STATE_PAUSE 4
71
72 #define VOICE_UID "09461341-4C7F-11D1-8222-444553540000"
73 #define FILE_SEND_UID "09461343-4C7F-11D1-8222-444553540000"
74 #define IMAGE_UID "09461345-4C7F-11D1-8222-444553540000"
75 #define B_ICON_UID "09461346-4C7F-11D1-8222-444553540000"
76 #define STOCKS_UID "09461347-4C7F-11D1-8222-444553540000"
77 #define FILE_GET_UID "09461348-4C7F-11D1-8222-444553540000"
78 #define GAMES_UID "0946134a-4C7F-11D1-8222-444553540000"
79
80 struct ft_request {
81 struct gaim_connection *gc;
82 char *user;
83 char UID[2048];
84 char *cookie;
85 char *ip;
86 int port;
87 char *message;
88 char *filename;
89 int files;
90 int size;
91 };
71 92
72 struct toc_data { 93 struct toc_data {
73 int toc_fd; 94 int toc_fd;
74 int seqno; 95 int seqno;
75 int state; 96 int state;
96 #define USEROPT_SOCKSPORT 3 117 #define USEROPT_SOCKSPORT 3
97 #define USEROPT_PROXYTYPE 4 118 #define USEROPT_PROXYTYPE 4
98 119
99 static void toc_callback(gpointer, gint, GdkInputCondition); 120 static void toc_callback(gpointer, gint, GdkInputCondition);
100 static unsigned char *roast_password(char *); 121 static unsigned char *roast_password(char *);
122 static void accept_file_dialog(struct ft_request *);
101 123
102 /* ok. this function used to take username/password, and return 0 on success. 124 /* ok. this function used to take username/password, and return 0 on success.
103 * now, it takes username/password, and returns NULL on error or a new gaim_connection 125 * now, it takes username/password, and returns NULL on error or a new gaim_connection
104 * on success. */ 126 * on success. */
105 static void toc_login(struct aim_user *user) 127 static void toc_login(struct aim_user *user)
159 gdk_input_remove(gc->inpa); 181 gdk_input_remove(gc->inpa);
160 gc->inpa = -1; 182 gc->inpa = -1;
161 close(((struct toc_data *)gc->proto_data)->toc_fd); 183 close(((struct toc_data *)gc->proto_data)->toc_fd);
162 } 184 }
163 185
164 int sflap_send(struct gaim_connection *gc, char *buf, int olen, int type) 186 static int sflap_send(struct gaim_connection *gc, char *buf, int olen, int type)
165 { 187 {
166 int len; 188 int len;
167 int slen = 0; 189 int slen = 0;
168 struct sflap_hdr hdr; 190 struct sflap_hdr hdr;
169 char obuf[MSG_LEN]; 191 char obuf[MSG_LEN];
335 /* Client sends TOC toc_init_done message */ 357 /* Client sends TOC toc_init_done message */
336 debug_printf("* Client sends TOC toc_init_done message\n"); 358 debug_printf("* Client sends TOC toc_init_done message\n");
337 g_snprintf(snd, sizeof snd, "toc_init_done"); 359 g_snprintf(snd, sizeof snd, "toc_init_done");
338 sflap_send(gc, snd, -1, TYPE_DATA); 360 sflap_send(gc, snd, -1, TYPE_DATA);
339 361
340 g_snprintf(snd, sizeof snd, "toc_set_caps %s %s", 362 g_snprintf(snd, sizeof snd, "toc_set_caps %s", FILE_SEND_UID);
341 FILE_SEND_UID, FILE_GET_UID);
342 sflap_send(gc, snd, -1, TYPE_DATA); 363 sflap_send(gc, snd, -1, TYPE_DATA);
343 364
344 return; 365 return;
345 } 366 }
346 367
559 if (!strcmp(uuid, FILE_SEND_UID)) { 580 if (!strcmp(uuid, FILE_SEND_UID)) {
560 /* they want us to get a file */ 581 /* they want us to get a file */
561 int unk[4], i; 582 int unk[4], i;
562 char *messages[4], *tmp, *name; 583 char *messages[4], *tmp, *name;
563 int subtype, files, totalsize = 0; 584 int subtype, files, totalsize = 0;
564 struct file_transfer *ft; 585 struct ft_request *ft;
565 586
566 for (i = 0; i < 4; i++) { 587 for (i = 0; i < 4; i++) {
567 sscanf(strtok(NULL, ":"), "%d", &unk[i]); 588 sscanf(strtok(NULL, ":"), "%d", &unk[i]);
568 if (unk[i] == 10001) 589 if (unk[i] == 10001)
569 break; 590 break;
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]);
636 g_free(tmp); 661 g_free(tmp);
637 for (i--; i >= 0; i--) 662 for (i--; i >= 0; i--)
638 g_free(messages[i]); 663 g_free(messages[i]);
639 664
640 accept_file_dialog(ft); 665 accept_file_dialog(ft);
666 */
641 } else if (!strcmp(uuid, VOICE_UID)) { 667 } else if (!strcmp(uuid, VOICE_UID)) {
642 /* oh goody. voice over ip. fun stuff. */ 668 /* oh goody. voice over ip. fun stuff. */
643 } else if (!strcmp(uuid, B_ICON_UID)) { 669 } else if (!strcmp(uuid, B_ICON_UID)) {
644 /* buddy icon... */ 670 /* buddy icon... */
645 } else if (!strcmp(uuid, IMAGE_UID)) { 671 } else if (!strcmp(uuid, IMAGE_UID)) {
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 }