diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -1,9 +1,29 @@ syntax: glob +.vs +*.pdb +*.obj +*.user +*.VC.db +*.asm + Linux/Aspell/data Linux/Aspell/dict Linux/Debug Linux/Release -*.asm Linux/*.idx Linux/ScribeOptions_*.bak + +src\Resource.res + +x64ReleaseNoOptimize* +x64Release* +x64Debug* + +test\Html\*.html +test\Html\*.jpg +test\Html\*.png +test\Html\*.gif + +Help\scripting\*.html +Help\scripting\*.css \ No newline at end of file diff --git a/resources/Scribe.lr8 b/resources/Scribe.lr8 --- a/resources/Scribe.lr8 +++ b/resources/Scribe.lr8 @@ -1,5230 +1,5231 @@ - + - + + diff --git a/resources/resdefs.h b/resources/resdefs.h --- a/resources/resdefs.h +++ b/resources/resdefs.h @@ -1,1284 +1,1285 @@ // Generated by LgiRes // This file generated by LgiRes #define L_FUI_NEW -912 #define L_FUI_LEGEND -911 #define L_FUI_NOT -910 #define L_FUI_OPTIONS -909 #define L_FUI_CONFIGURE -908 #define L_FUI_MOVE_DOWN -907 #define L_FUI_MOVE_UP -906 #define L_FUI_DELETE -905 #define L_FUI_OR -904 #define L_FUI_AND -903 #define L_FUI_NEW_OR -902 #define L_FUI_NEW_AND -901 #define L_FUI_NEW_CONDITION -900 #define L_STORE_RESTART -803 #define L_STORE_MISMATCH -802 #define L_STORE_OS_ERR -801 #define L_STORE_WRITE_ERR -800 #define L_TOOLBAR_SHOW_TEXT -700 #define L_FR_SELECTION_ONLY -608 #define L_FR_REPLACE_WITH -607 #define L_FR_REPLACE_ALL -606 #define L_FR_REPLACE -605 #define L_FR_MATCH_CASE -604 #define L_FR_MATCH_WORD -603 #define L_FR_FIND_NEXT -602 #define L_FR_FIND_WHAT -601 #define L_FR_FIND -600 #define L_COLOUR_NONE -550 #define L_CHANGE_CHARSET -505 #define L_VIEW_IMAGES -504 #define L_VIEW_IN_DEFAULT_BROWSER -503 #define L_COPY_SOURCE -502 #define L_VIEW_SOURCE -501 #define L_COPY_LINK_LOCATION -500 #define L_FONTUI_UNDERLINE -407 #define L_FONTUI_TITLE -406 #define L_FONTUI_STYLE -405 #define L_FONTUI_PTSIZE -404 #define L_FONTUI_PREVIEW -403 #define L_FONTUI_ITALIC -402 #define L_FONTUI_FACE -401 #define L_FONTUI_BOLD -400 #define L_TEXTCTRL_TAB_SIZE -214 #define L_TEXTCTRL_INDENT_SIZE -213 #define L_TEXTCTRL_HARD_TABS -212 #define L_TEXTCTRL_SHOW_WHITESPACE -211 #define L_TEXTCTRL_UNDO -210 #define L_TEXTCTRL_REDO -209 #define L_TEXTCTRL_PASTE -208 #define L_TEXTCTRL_OPENURL -207 #define L_TEXTCTRL_GOTO_LINE -206 #define L_TEXTCTRL_FIXED -205 #define L_TEXTCTRL_EMAIL_TO -204 #define L_TEXTCTRL_CUT -203 #define L_TEXTCTRL_COPYLINK -202 #define L_TEXTCTRL_COPY -201 #define L_TEXTCTRL_AUTO_INDENT -200 #define IDS_ERROR_ESMTP_UNSUPPORTED_AUTHS -101 #define IDS_ERROR_ESMTP_NO_AUTHS -100 #define L_BTN_CANCEL -51 #define L_BTN_OK -50 #define FIELD_FLAGS 1 #define FIELD_TO 2 #define FIELD_CC 3 #define FIELD_FROM 4 #define FIELD_REPLY 5 #define FIELD_SUBJECT 6 #define FIELD_TEXT 7 #define FIELD_MESSAGE_ID 8 #define FIELD_DATE_RECEIVED 9 #define FIELD_INTERNET_HEADER 10 #define FIELD_FIRST_NAME 11 #define FIELD_LAST_NAME 12 #define FIELD_EMAIL 13 #define FIELD_HOME_STREET 14 #define FIELD_HOME_SUBURB 15 #define FIELD_HOME_POSTCODE 16 #define FIELD_HOME_STATE 17 #define FIELD_HOME_COUNTRY 18 #define FIELD_WORK_PHONE 19 #define FIELD_HOME_PHONE 20 #define FIELD_HOME_MOBILE 21 #define FIELD_HOME_IM 22 #define FIELD_HOME_FAX 23 #define FIELD_HOME_WEBPAGE 24 #define FIELD_NICK 25 #define FIELD_SPOUSE 26 #define FIELD_NOTE 27 #define FIELD_PLUGIN_ASSOC 28 #define FIELD_SIZE 29 #define FIELD_DATE_SENT 30 #define FIELD_COLUMN 31 #define FIELD_BCC 32 #define FIELD_MIME_TYPE 33 #define FIELD_PRIORITY 34 #define FIELD_FOLDER_OPEN 35 #define FIELD_CODE_PAGE 36 #define FIELD_MARK_COLOUR 37 #define FIELD_ALTERNATE_HTML 38 #define FIELD_CONTENT_ID 39 #define FIELD_FILTER_NAME 40 #define FIELD_CONDITION 41 #define FIELD_ACTION 42 #define FIELD_COND_FIELD 43 #define FIELD_COND_OPERATOR 44 #define FIELD_COND_VALUE 45 #define FIELD_ACT_TYPE 46 #define FIELD_ACT_ARG 47 #define FIELD_DIGEST_INDEX 48 #define FIELD_COMBINE_OP 49 #define FIELD_FILTER_INDEX 50 #define FIELD_FILTER_INCOMING 55 #define FIELD_FILTER_OUTGOING 56 #define FIELD_FILTER_INTERNAL 59 #define FIELD_CAL_SUBJECT 62 #define FIELD_CAL_LOCATION 63 #define FIELD_CAL_REMINDER_TIME 64 #define FIELD_CAL_REMINDER_ACTION_dep 65 #define FIELD_CAL_REMINDER_ARG_dep 66 #define FIELD_CAL_SHOW_TIME_AS 67 #define FIELD_CAL_RECUR_FREQ 68 #define FIELD_CAL_RECUR_INTERVAL 69 #define FIELD_CAL_RECUR_FILTER_DAYS 70 #define FIELD_CAL_RECUR_FILTER_MONTHS 71 #define FIELD_CAL_RECUR_FILTER_YEARS 72 #define FIELD_CAL_NOTES 73 #define FIELD_CAL_START_UTC 76 #define FIELD_CAL_END_UTC 77 #define FIELD_CAL_RECUR_FILTER_POS 78 #define FIELD_CAL_RECUR_END_DATE 79 #define FIELD_CAL_RECUR_END_COUNT 80 #define FIELD_CAL_RECUR_END_TYPE 81 #define FIELD_CAL_RECUR 82 #define IDC_COLOUR 83 #define FIELD_ATTENDEE_NAME 85 #define FIELD_ATTENDEE_EMAIL 86 #define FIELD_ATTENDEE_ATTENDENCE 87 #define FIELD_ATTENDEE_NOTE 88 #define FIELD_ATTENDEE_RESPONSE 89 #define FIELD_WORK_STREET 90 #define FIELD_WORK_SUBURB 91 #define FIELD_WORK_POSTCODE 92 #define FIELD_WORK_STATE 93 #define FIELD_WORK_COUNTRY 94 #define FIELD_WORK_MOBILE 95 #define FIELD_WORK_IM 96 #define FIELD_WORK_FAX 97 #define FIELD_WORK_WEBPAGE 98 #define FIELD_COMPANY 99 #define FIELD_LABEL 110 #define IDM_SAVE 113 #define FIELD_TITLE 114 #define FIELD_SERVER_UID 117 #define FIELD_GROUP_NAME 120 #define FIELD_GROUP_LIST 123 #define FIELD_FROM_CONTACT_NAME 126 #define IDS_ENCRYPTION_SUPPORT 150 #define FIELD_DATE_MODIFIED 162 #define FIELD_IMAP_SEQ 167 #define FIELD_RECEIVED_DOMAIN 170 #define IDD_FILTER_ITEMS 175 #define IDC_SIGNATURE_TAB 184 #define IDC_RESET_REPLY 186 #define IDC_SIG 187 #define IDC_RESET_FORWARD 189 #define IDS_205 205 #define IDS_SAVE_ITEM 208 #define IDS_DESCRIPTIVE_NAME 209 #define IDS_ERROR_SOFTWARE_UPDATE 210 #define IDS_211 211 #define IDS_235 235 #define IDC_SUB_FOLDERS 275 #define IDM_FEEDBACK 287 #define IDM_SCRIBE_LINK 291 #define IDM_INSCRIBE_LINK 292 #define IDM_FAQ 293 #define IDC_READ 316 #define IDD_SUB_FOLDERS 317 #define IDC_HAS_TEMPLATES 322 #define IDC_INBOX 324 #define IDC_OUTBOX 325 #define IDM_PAGE_SETUP 326 #define IDC_TRASH 327 #define IDC_CONTACT_FLD 328 #define IDS_DEBUG 329 #define IDC_SET_INBOX 330 #define IDC_SET_OUTBOX 331 #define IDC_SET_SENT 332 #define IDC_SET_TRASH 333 #define IDC_SET_CONTACTS 334 #define IDC_SET_FILTERS 335 #define IDC_MAX_SIZE 342 #define IDC_CONFIRM_DEL 343 #define IDS_CONTENT_ID 344 #define IDC_BOLD_UNREAD 346 #define IDC_GRID_LINES 347 #define IDC_TITLE 348 #define IDC_PREVIEW_LINES 349 #define IDC_SET_TEMPLATES 350 #define IDC_351 351 #define IDC_SMTP_AUTH 353 #define IDC_FILTERS_FLD 354 #define IDS_RETRY 355 #define IDS_FOLDER_PROPERTIES_COMPACT 356 #define IDC_HAS_SPAM 357 #define IDS_CALENDAR 359 #define IDS_NO_LOG 360 #define IDC_REC_TYPE 362 #define IDS_FIND 363 #define IDS_NO_ITEMS 364 #define IDS_RECEIVE_ALL_ACCOUNTS 365 #define IDS_NO_ITEMS_IN_FOLDER 366 #define IDS_PREVIEW_ON_SERVER 367 #define IDS_RECEIVE_MAIL 368 #define IDS_NO_TEMPLATES 369 #define IDC_STOP_FILTERING 370 #define IDS_NEW_EMAIL 371 #define IDS_EXIT 372 #define IDS_MARK_ALL_SEND 373 #define IDS_MARK 374 #define IDS_SELECT_MARKED 375 #define IDS_PRIORITY 376 #define IDS_HIGH 377 #define IDS_NORMAL 378 #define IDS_LOW 379 #define IDS_NEW_CONTACT 380 #define IDS_RECEIVE 381 #define IDC_LIMIT_TO 382 #define IDS_PRINT 383 #define IDS_CAL_SDAY_SUN 384 #define IDS_SAVE_CLOSE 385 #define IDS_FILTER 386 #define IDS_PREV_MSG 387 #define IDS_NEXT_MSG 388 #define IDS_CONDITIONS 390 #define IDS_ACTIONS 391 #define IDS_DETAIL 392 #define IDS_FIELDS 393 #define IDS_FILE_NAME 394 #define IDS_MIME_TYPE 395 #define IDS_PREVIEW 396 #define IDS_ERROR_FOLDERS_VERSION 397 #define IDS_ERROR_FOLDERS_STATUS 398 #define IDS_EXPORT 399 #define IDS_STATUS 400 #define IDD_STATUS 401 #define IDS_402 402 #define IDC_ACC_LIST 403 #define IDC_404 404 #define IDC_IN_FOLDER 406 #define IDS_407 407 #define IDS_408 408 #define IDC_STATUS_TXT 409 #define IDC_OP_TXT 410 #define IDS_411 411 #define IDC_EMAIL_TXT 412 #define IDC_EMAIL_PROG 413 #define IDD_MAIL_PROPERTIES 414 #define IDC_STOP 415 #define IDC_SEND_LOG 416 #define IDC_OP_PROG 417 #define IDC_SET_IN 418 #define IDS_HIDE_GNUPG 419 #define IDS_RESIZE 420 #define IDS_COPY_FOLDER 421 #define IDS_GNUPG_ATTACH_PUB_KEY 422 #define IDS_GNUPG_SIGN 423 #define IDS_GNUPG_ENCRYPT 424 #define IDS_GNUPG_DECRYPT 425 #define IDS_GNUPG_ERR_NOMSG 426 #define IDC_CLEAR_KEYWORDS 436 #define IDS_MONTH 437 #define IDC_BAYES_TABLE 439 #define IDS_HIGH_PRIORITY 440 #define IDD_ACCOUNT 441 #define IDS_443 443 #define IDS_444 444 #define IDS_445 445 #define IDC_MAIL_DESCRIPTION 448 #define IDC_SENT 449 #define IDC_RECEIVED 450 #define IDC_FORWARDED 451 #define IDC_REPLIED 452 #define IDC_HAS_ATTACH 453 #define IDC_MARKED 455 #define IDC_READY_SEND 456 #define IDC_OPEN_INSPECTOR 457 #define IDC_CREATED 459 #define IDD_NO_FOLDER 460 #define IDC_MESSAGE 462 #define IDS_470 470 #define IDC_CREATE_FOLDER 471 #define IDS_472 472 #define IDS_475 475 #define IDC_ACCOUNT 476 #define IDC_ACCOUNT_NAME 477 #define IDC_SMTP_PASSWORD 478 #define IDC_EXISTING 486 #define IDC_FOLDER_HISTORY 487 #define IDS_488 488 #define IDS_ASK_TNEF_DECODE 495 #define IDC_RECEIVE_TABLE 500 #define IDC_SEND_SSL 501 #define IDS_OK 502 #define IDC_NEW_FOLDER 503 #define IDC_EXISTING_FOLDER 504 #define IDC_BROWSE_NEW 505 #define IDC_BROWSE_EXISTING 506 #define IDS_YEAR 507 #define IDC_TEXT 508 #define IDC_SEARCH 509 #define IDS_510 510 #define IDC_BAYES_MODE 511 #define IDC_REPEATS 512 #define IDS_YEARS 513 #define IDS_CANCEL 514 #define IDS_SAVE 515 #define IDS_EMAIL 516 #define IDS_REPLY 517 #define IDS_REPLYALL 518 #define IDS_FORWARD 519 #define IDC_SIG_HTML 520 #define IDS_TO 521 #define IDC_DEFAULT_ALT 522 #define IDS_COMPACT_TESTING_DLG 523 #define IDS_FOLDER_COMPACT_ERR_DLG 524 #define IDS_COULDNT_OPEN 525 #define IDC_SEARCH_SUB 526 #define IDC_FIND_CASE 527 #define IDC_FIND_WORD 528 #define IDS_ATTACH_FILE 529 #define IDC_CTRLS_TABLE 530 #define IDC_MAIL_FIELD 531 #define IDC_CONTACT 532 #define IDM_BAYES_STATS 533 #define IDS_EDIT 534 #define IDC_ID_TABLE 535 #define IDC_CONTACT_FIELD 536 #define IDC_ACTION 537 #define IDS_REMOVE 538 #define IDM_UNIT_TESTS 539 #define IDC_LAYOUT 540 #define IDC_TABS 541 #define IDC_275 542 #define IDC_FIRST 543 #define IDS_544 544 #define IDC_OUT_FOLDER 545 #define IDC_SET_OUT 546 #define IDD_PAGE_SETUP 547 #define IDC_PREVIEW 548 #define IDS_ATTACH_WARNING_DLG 549 #define IDC_BROWSE_FONT 550 #define IDS_MAIL_PROPS_DLG 551 #define IDS_552 552 #define IDS_553 553 #define IDS_554 554 #define IDS_555 555 #define IDC_LEFT 556 #define IDC_TOP 557 #define IDC_RIGHT 558 #define IDC_BOTTOM 559 #define IDS_MAIL_PROPS 560 #define IDC_CUSTOM_FIELDS 561 #define IDS_ADD_CONTACTS 562 #define IDS_SUBFLD_NAME_CLASH 563 #define IDC_TREE 564 #define IDS_ERROR_NO_RECIPIENTS 565 #define IDC_USER_PASS_CONFIRM 566 #define IDS_SAVE_ATTACHMENT_AS 567 #define IDS_NO_CONNECTION_TO_SERVER 568 #define IDS_SERVER_ERROR_MSG 569 #define IDS_NO_SMTP_SERVER_SETTINGS 570 #define IDS_ASK_ABOUT_OPTIONS 571 #define IDS_THIS_WEEK 572 #define IDS_UPDATE_PERIOD 573 #define IDS_HEX_LOG 574 #define IDS_OPEN 575 #define IDS_BYTE_LOG 576 #define IDC_CALENDER 577 #define IDS_WINDOWS_SSL_INSTALL 578 #define IDC_KEYWORDS 579 #define IDC_PATH 580 #define IDC_UNREAD 581 #define IDC_LOCATION 582 #define IDS_ADDRESS 583 #define IDS_POPUP 584 #define IDC_PARAM_LABEL 585 #define IDC_DIR 586 #define IDS_LOW_PRIORITY 587 #define IDD_CAL 588 #define IDD_CAL_REMOTE 589 #define IDC_590 590 #define IDS_ADD_CAL 591 #define IDS_ADD_CAL_POPUP 592 #define IDS_SET_READ 593 #define IDS_SET_UNREAD 594 #define IDS_PROPERTIES 595 #define IDS_SUBJECT 596 #define IDS_OPTIONS 597 #define IDS_SMTP 598 #define IDS_SIZE 599 #define IDS_DATE 600 #define IDS_SAVEAS 601 #define IDS_EMPTY 602 #define IDS_ERROR_FOLDERS_DONT_EXIST 603 #define IDS_ERROR_CANT_OPEN_FOLDERS 604 #define IDS_ENTER_FILE_NAME_FOR_FOLDERS 605 #define IDS_SEND_MAIL 606 #define IDS_NEW 607 #define IDS_APPOINTMENT 608 #define IDS_CAL_EVENT 609 #define IDS_CONTACT 610 #define IDS_CREATESUBFOLDER 611 #define IDS_612 612 #define IDS_CAL_VIEW 613 #define IDS_MINUTES 614 #define IDS_HOUR 615 #define IDS_HOURS 616 #define IDS_DAY 617 #define IDS_DAYS 618 #define IDS_FREE 619 #define IDS_TENTATIVE 620 #define IDS_BUSY 621 #define IDS_OUT_OF_OFFICE 622 #define IDS_DOWNLOAD 623 #define IDS_READ_RECEIPT 624 #define IDS_CAL_SDAY_MON 625 #define IDS_RENAMEFOLDER 626 #define IDC_FOLDER_MSG 627 #define IDC_PASS 628 #define IDS_629 629 #define IDS_630 630 #define IDS_631 631 #define IDD_FOLDER_PROPS 632 #define IDS_FIRST 633 #define IDS_LOCAL_CONTACTS 634 #define IDC_ACCOUNT_TBL 635 #define IDS_MOVE_ERROR 636 #define IDS_MESSAGE 637 #define IDS_ACTION 638 #define IDS_MSGS_ERROR 639 #define IDS_CAL_LMONTH_OCT 640 #define IDC_ACCOUNTS_READ 641 #define IDS_CONFIGURE 642 #define IDS_ERROR_FILE_OVERWRITE 643 #define IDC_INTERNAL_FILTERING 644 #define IDC_STORE2_KEEP 645 #define IDS_ERROR_CANT_READ 646 #define IDC_FOLDER_WRITE 647 #define IDS_ERROR_FILE_EXISTS 648 #define IDD_BAYES_SETTINGS 649 #define IDC_USER_LEVEL_PSW 650 #define IDC_USER_PASS 651 #define IDS_ERROR_FOLDERS_ALREADY_EXIST 652 #define IDC_APW_USER 653 #define IDC_COMPACT_MS 654 #define IDD_FIND 655 #define IDC_DEF_SEND 656 #define IDC_TOOLBAR_TEXT 657 #define IDS_ADD 658 #define IDM_SAVEAS 659 #define IDC_URL 660 #define IDC_SUBJECT 661 #define IDD_MAIL_FIELDS 662 #define IDD_KEY 663 #define IDC_LABEL 664 #define IDS_147 665 #define IDC_SENT_DATE 666 #define IDS_148 667 #define IDC_RECEIVED_DATE 668 #define IDD_FILTER 669 #define IDC_PRIVACY_TYPE 670 #define IDS_671 671 #define IDM_NO_IDENTITIES 672 #define IDD_FILTER_ACTION 673 #define IDD_NEWFOLDER_F 674 #define IDD_FILES_IMPORT 675 #define IDS_ADD_LOCAL_CAL_FOLDER 676 #define IDC_UI_FNT_SIZE 677 #define IDC_UI_LANG 678 #define IDS_ERROR_LR8_FAILURE 679 #define IDC_REC_8BIT_CS 680 #define IDC_CLIENT 681 #define IDC_BLINK 682 #define IDC_FOLDER_READ 683 #define IDC_ACCOUNTS_WRITE 684 #define IDC_CUSTOM_TABLE 685 #define IDC_APR_USER 686 #define IDC_NAME_TABLE 687 #define IDC_USER 688 #define IDC_APR_ADMIN 689 #define IDC_APW_NONE 690 #define IDS_ADD_CAL_URL 691 #define IDC_REMINDER_VALUE 692 #define IDS_LIKE 693 #define IDC_PREVIEW_READ 694 #define IDS_ASK_USER_PASS 695 #define IDD_FILTER_SAVE_ATTACH 696 #define IDM_HELP 697 #define IDC_TYPES 698 #define IDC_OTHER_TABLE 699 #define IDC_BROWSE_DIR 700 #define IDC_ONLY_SEND_THIS 701 #define IDC_GROUPS_FLD 702 #define IDC_SET_GROUPS 703 #define IDS_CC 704 #define IDS_RECIPIENTS 705 #define IDS_TEXT 706 #define IDS_ATTACHMENTS 707 #define IDS_INTERNETHEADER 708 #define IDS_FOLDER_PROPERTIES_DLG 709 #define IDS_TOMORROW 710 #define IDS_NEXT_WEEK 711 #define IDC_FILES 712 #define IDC_PICK_FILES 713 #define IDC_USAGE 714 #define IDC_START_TIME 715 #define IDS_ABOUT 716 #define IDC_COLLECT_SUB_MAIL 717 #define IDS_NO_MAIL_TO_FILTER 718 #define IDS_FORWARD_PREFIX 719 #define IDS_REPLY_PREFIX 720 #define IDS_SPAM 721 #define IDS_SEARCH 722 #define IDS_ITEM_FILTER 723 #define IDD_WEBDAV_PROPS 724 #define IDC_725 725 #define IDM_IMPORT_EML 726 #define IDC_CONTACTS_URL 727 #define IDS_DELETE_FOLDER_DLG 728 #define IDS_1035 729 #define IDS_SET_DEFAULT 730 #define IDC_HTML_FONT 731 #define IDC_SET_HTML_FONT 732 #define IDS_APPEARANCE 733 #define IDS_UPDATE 734 #define IDC_EDIT_REPLY 735 #define IDC_EDIT_FORWARD 736 #define IDC_CALENDAR_URL 737 #define IDC_APW_ADMIN 738 #define IDS_ERROR_EXE_FILE 739 #define IDC_USERNAME 740 #define IDS_FROM 741 -#define IDC_PASSWORD 742 #define IDC_DATE_FORMAT 743 #define IDS_1034 744 #define IDS_SORT_SUBFOLDERS 745 #define IDC_DESC 746 #define IDC_948 747 #define IDS_LOADING 748 #define IDS_MOVE_FOLDER 749 #define IDC_FILTER_INDEX 750 #define IDC_FILTER_UP 751 #define IDC_FILTER_DOWN 752 #define IDM_SCRIPT_BREAK_ON_WARN 753 #define IDS_MOVE_ATTACH 754 #define IDS_ERROR_WONT_OVERWRITE_FOLDERS 755 #define IDS_NEXT_FOLDER 756 #define IDC_BAYES_READ 757 #define IDM_DELETE 758 #define IDS_SUB_FOLDER 759 #define IDS_WEEK 760 #define IDS_ERROR_READONLY_FOLDERS 761 #define IDC_TIMEZONE 762 #define IDC_LOCALTIME 763 #define IDC_HIDE_ID 764 #define IDS_SOFTWARE_UPDATE_DOWNLOAD 765 #define IDD_FILTER_SCRIPT 766 #define IDC_SCRIPT 767 #define IDS_ASK_DUPE_CONTACT 768 #define IDS_PERM_DEL_ATTACHMENTS 769 #define IDC_HTTP_PROXY 770 #define IDC_PICK_TZ 771 #define IDS_THREAD 772 #define IDS_SOFTWARE_CURRENT 773 #define IDS_TRANSLATION_AUTHORS 774 #define IDD_CSV_IMPORT 775 #define IDC_THEME 776 #define IDS_BCC 777 #define IDS_CLICK_TO_ADD 778 #define IDS_779 779 #define IDC_BROWSE_THEMES 780 #define IDD_OUTLOOK_EXPORT 781 #define IDS_SUMMARY 782 #define IDC_BROWSE_FOLDER 783 #define IDS_MERGE_TEMPLATE 784 #define IDS_MERGE_FILE 785 #define IDS_COPY 786 #define IDD_SETTINGS 787 #define IDS_DELETE_SYS_FOLDER 788 #define IDS_789 789 #define IDS_CAL_SDAY_TUE 790 #define IDS_791 791 #define IDS_792 792 #define IDS_793 793 #define IDS_794 794 #define IDS_MBOX_IMPORT 795 #define IDC_SET_READ 796 #define IDS_CAL_SDAY_WED 797 #define IDS_CAL_SDAY_THU 798 #define IDS_CAL_SDAY_FRI 799 #define IDS_CAL_SDAY_SAT 800 #define IDS_CAL_LDAY_SUN 801 #define IDS_CAL_LDAY_MON 802 #define IDS_CAL_LDAY_TUE 803 #define IDS_CAL_LDAY_WED 804 #define IDS_CAL_LDAY_THU 805 #define IDS_CAL_LDAY_FRI 806 #define IDS_CAL_LDAY_SAT 807 #define IDS_CAL_SMONTH_JAN 808 #define IDS_CAL_SMONTH_FEB 809 #define IDS_CAL_SMONTH_MAR 810 #define IDS_CAL_SMONTH_APR 811 #define IDS_CHANGED 812 #define IDS_CAL_SMONTH_MAY 813 #define IDS_CAL_SMONTH_JUN 814 #define IDS_CAL_SMONTH_JUL 815 #define IDS_CAL_SMONTH_AUG 816 #define IDS_CAL_SMONTH_SEP 817 #define IDS_CAL_SMONTH_OCT 818 #define IDS_CAL_SMONTH_NOV 819 #define IDS_CAL_SMONTH_DEC 820 #define IDS_CAL_LMONTH_JAN 821 #define IDS_EVENT_DUE 822 #define IDC_BAYES_THRESHOLD 823 #define IDS_CAL_LMONTH_FEB 824 #define IDS_CAL_LMONTH_MAR 825 #define IDS_CAL_LMONTH_APR 826 #define IDS_CAL_LMONTH_MAY 827 #define IDS_CAL_LMONTH_JUN 828 #define IDS_CAL_LMONTH_JUL 829 #define IDS_CAL_LMONTH_AUG 830 #define IDC_PREVIEW_SECONDS 831 #define IDS_CAL_LMONTH_SEP 832 #define IDC_SOCKS5_PASSWORD 833 #define IDS_CAL_LMONTH_NOV 834 #define IDS_CAL_LMONTH_DEC 835 #define IDC_RECEIVE_SSL 836 #define IDC_SEND_CHARSET1 837 #define IDC_SEND_CHARSET2 838 #define IDS_DELETE_ASK 839 #define IDS_DONT_ADJUST_TZ 840 #define IDC_DELETE_AFTER 841 #define IDC_HTML_IMAGES 842 #define IDC_AUTO_DELETE_EXE 843 #define IDD_GROUP 844 #define IDC_SEND_AUTH_TYPE 845 #define IDM_HOMEPAGE 846 #define IDC_GROUP_NAME 847 #define IDC_GROUP_LIST 848 #define IDC_START_DATE 849 #define IDC_850 850 #define IDS_TODAY 851 #define IDC_REC_ASCII_CP 852 #define IDS_FOLDER_OUTBOX 853 #define IDS_FOLDER_SENT 854 #define IDS_780 855 #define IDS_FOLDER_FILTERS 856 #define IDS_FOLDER_CONTACTS 857 #define IDS_ATTACHMENTS_NAME 858 #define IDS_ATTACHMENTS_DATA 859 #define IDS_ANYWHERE 860 #define IDS_TODO 861 #define IDS_FOLDER_TEMPLATES 862 #define IDS_FOLDER_GROUPS 863 #define IDS_FOLDER_CALENDAR 864 #define IDS_DEFAULT_CHARSET_RECEIVE 865 #define IDS_DUE 866 #define IDS_CLICK_TO_CREATE 867 #define IDC_REPEAT 868 #define IDS_1101 869 #define IDS_ERROR_ALREADY_ONLINE 870 #define IDS_NOT_LOADED 871 #define IDC_SHOW_LOCATION 872 #define IDS_ERROR_MAPI_NOT_INSTALLED 873 #define IDC_CALENDAR 874 #define IDS_PLUGINS_NO_CONF 875 #define IDC_TAB1 876 #define IDC_TAB2 877 #define IDC_CHECK_EVERY 878 #define IDS_1116 879 #define IDC_FILTER_ACTIONS 880 #define IDC_LOGIN 881 #define IDC_MSG_STORE 882 #define IDC_SRC_FOLDERS 883 #define IDC_FOLDER 884 #define IDS_ADD_ALL_CONTACTS 885 #define IDS_MAPI_LOGIN_FAILED 886 #define IDS_ACCSTAT_IDLE 887 #define IDS_BROWSE_FOLDER 888 #define IDS_3 889 #define IDS_ASK_ADMIN_PASS 890 #define IDS_LINKS 891 #define IDC_EXTRA_HEADERS 892 #define IDC_FORMAT 893 #define IDM_TABLE2 894 #define IDC_RECEIVE_AUTH_TYPE 895 #define IDS_896 896 #define IDC_SUSPECT_FOLDER 897 #define IDM_SET_UNREAD 898 #define IDS_HTML_TAGS 899 #define IDC_PROGRESS_TBL 900 #define IDS_DELETE 901 #define IDC_SET_SUSPECT_FOLDER 902 #define IDC_SEND_TABLE 903 #define IDS_838 904 #define IDC_TEMPLATE 905 #define IDS_1082 906 #define IDC_TXT_DAYS 907 #define IDC_FOLDERS 908 #define IDD_SECURITY 909 #define IDS_9 910 #define IDS_REMOVE_DUPES 911 #define IDC_SHOW_TOTALS 912 #define IDC_913 913 #define IDC_REMINDER_TYPE 914 #define IDS_ALWAYS_SHOW_REMOTE_CONTENT 915 #define IDC_TXT_SIZE 916 #define IDS_ERROR_FILE_EMPTY 917 #define IDC_REMINDER_PARAM 918 #define IDC_REMINDER_UNIT 919 #define IDD_EML_IMPORT 920 #define IDC_HOME_TABLE 921 #define IDC_APR_NONE 922 #define IDS_OPEN_CONTACT 923 #define IDS_THREAD_SELECT 924 #define IDS_THREAD_DELETE 925 #define IDS_THREAD_IGNORE 926 #define IDS_NONE 927 #define IDS_ALL 928 #define IDS_CONVERT_SELECTION 929 #define IDS_MULTIPLE_ITEMS 930 #define IDC_GROUP 931 #define IDC_MAPPING 932 #define IDS_933 933 #define IDS_934 934 #define IDC_TAB 935 #define IDC_HAS_FILTERS 936 #define IDC_MODE 937 #define IDC_MERGE 938 #define IDC_APPEND 939 #define IDC_CHECK_DEFAULT 940 #define IDC_EVERY 941 #define IDC_LOAD 942 #define IDS_ERROR_CANT_WRITE 943 #define IDS_944 944 #define IDS_SAVE_TO_OUTBOX 945 #define IDS_INC_BETA 946 #define IDS_947 947 #define IDC_TIME_TYPE 948 #define IDS_FOLDER_TRASH 949 #define IDD_FILES_EXPORT 950 #define IDS_1022 951 #define IDC_END_DATE 952 #define IDC_HAM 953 #define IDC_SPAM 954 #define IDC_FALSE_NEG 955 #define IDC_FALSE_POS 956 #define IDC_EFFICIENCY 957 #define IDS_RECEIPT_ASK 958 #define IDS_ERROR_NO_HELP 959 #define IDC_END_TIME 960 #define IDC_869 961 #define IDS_ERROR_CONNECTION 962 #define IDS_CREATE_FOLDER 963 #define IDC_ALL_DAY 964 #define IDC_DEF_REPLYALL_SETTING 965 #define IDS_DEFAULT_CHARSET_SEND 966 #define IDC_WEDNESDAY 967 #define IDS_WARN_NO_SECURITY 968 #define IDC_969 969 #define IDC_LAUNCH_HELP 970 #define IDC_THURSDAY 971 #define IDD_LANG 972 #define IDC_LANG 973 #define IDC_FRIDAY 974 #define IDS_975 975 #define IDS_976 976 #define IDD_FILTER_REPLY 977 #define IDD_FILTER_FORWARD 978 #define IDC_SATURDAY 979 #define IDC_SUNDAY 980 #define IDC_REC_PORT 981 #define IDS_INSPECT 982 #define IDS_FOLDER_INBOX 983 #define IDC_OCCURRENCES 984 #define IDC_CONFIGURE_REMOTE_CONTENT 985 #define IDC_TABLE3 986 #define IDC_BLACKLIST 987 #define IDC_ATTACHMENTS 988 #define IDS_GNUPG_ERR_NO_BOUNDARY 989 #define IDS_GNUPG_ERR_NO_MIME 990 #define IDS_ASK_FORWARD_ATTACHMENTS 991 #define IDC_ALL 992 #define IDC_MARK_REPLIED 993 #define IDC_MARK_FORWARDED 994 #define IDS_BOUNCE 995 #define IDS_REMOVE_WHITELIST 996 #define IDC_UNDELETE 997 #define IDS_ERROR_NO_CONFIG_SEND 998 #define IDS_ERROR_NO_CONFIG_RECEIVE 999 #define IDC_MAIL 1000 #define IDC_CONTACTS 1001 #define IDC_NAME 1002 #define IDC_TYPE 1003 #define IDC_EMAIL 1004 #define IDS_SEND 1005 #define IDC_REPLY_TO 1006 #define IDC_NICK 1007 #define IDM_SCRIBE_FAQ 1008 #define IDC_SPOUSE 1009 #define IDC_HAS_CAL_EVENTS 1010 #define IDC_QUOTE_STR 1011 #define IDC_WRAP_COLS 1012 #define IDS_ASK_DELETE_DUPES 1013 #define IDS_GNUPG_ERR_NO_RECIP 1014 #define IDC_START_IN 1015 #define IDC_SET_START_IN 1016 #define IDM_LAYOUT4 1017 #define IDC_DOWN 1018 #define IDM_REFRESH 1019 #define IDS_ERROR_REG_WRITE 1020 #define IDS_ERROR_NEED_INSTALL 1021 #define IDC_SMTP_SERVER 1022 #define IDC_SMTP_NAME 1023 #define IDC_REC_SERVER 1024 #define IDC_REC_NAME 1025 #define IDC_REC_PASSWORD 1026 #define IDC_REC_CHECK 1027 #define IDC_POP3_LEAVE 1028 #define IDS_ERROR_SERVER_CONNECT 1029 #define IDC_LAST 1030 #define IDC_QUOTE 1031 #define IDC_HOME_FAX 1032 #define IDC_HOME_STREET 1033 #define IDC_ACCOUNTS 1034 #define IDC_HOME_SUBURB 1035 #define IDC_FONT 1036 #define IDC_DESCRIPTION 1037 #define IDC_NEW_MAIL_SOUND 1038 #define IDS_MAIL_MESSAGE 1039 #define IDC_SMTP_DOMAIN 1040 #define IDC_HOME_STATE 1041 #define IDC_REPLYWITHSIG 1042 #define IDC_HOME_COUNTRY 1043 #define IDS_POP3 1044 #define IDC_HOME_PHONE 1045 #define IDC_HOME_MOBILE 1046 #define IDC_HOME_IM 1047 #define IDC_HOME_WEBPAGE 1048 #define IDC_NOTE 1049 #define IDC_DEFAULT 1050 #define IDC_TRAY 1051 #define IDS_DELETEFOLDER 1052 #define IDC_CHECKDIALUP 1053 #define IDC_SET_FONT 1054 #define IDC_POP3_ON_START 1055 #define IDC_LIST 1056 #define IDC_START_WEEK 1057 #define IDC_REFRESH 1058 #define IDS_COPY_PATH 1059 #define IDC_SET_SOUND 1060 #define IDS_OE_IMPORT 1061 #define IDS_1062 1062 #define IDM_MENU_1063 1063 #define IDC_DEL_SRC_FOLDER 1064 #define IDC_PICK_FOLDER 1065 #define IDC_WRAP 1066 #define IDC_NO_SPAM_TRASH 1067 #define IDC_ADD 1068 #define IDC_MSG 1069 #define IDC_KEY 1070 #define IDC_DONT_WARN 1071 #define ID_YES 1072 #define ID_NO 1073 #define IDC_REGISTER_CLIENT 1074 #define IDC_SOCKS5_SERVER 1075 #define IDC_SOCKS5_USER 1076 #define IDC_REMINDER_ADD 1077 #define IDC_USE_TEMPLATE 1078 #define IDC_SET_FOLDER 1079 #define IDC_REMINDERS 1080 #define IDC_AVAILABLE_TYPE 1081 #define IDC_AVAILABLE 1082 #define IDS_ERROR_NO_SPACE 1083 #define IDC_TEMPLATES 1084 #define IDS_RECEIPT_BODY 1085 #define IDS_SPAM_PROB 1086 #define IDS_IS_WHITELIST 1087 #define IDC_BUSY 1088 #define IDS_ERROR_MAPI_DEFAULT 1089 #define IDS_ERROR_SOFTWARE_KEY 1090 #define IDM_MANAGE_MAIL_STORES 1091 #define IDC_PUBLIC 1092 #define IDC_PRIVATE 1093 #define IDC_NEW_FILTER_ACTION 1094 #define IDC_DELETE_FILTER_ACTION 1095 #define IDS_MAIL 1096 #define IDC_RADIO1 1097 #define IDC_RADIO2 1098 #define IDC_DEF_ACTION 1099 #define IDC_WORK_COUNTRY 1100 #define IDC_WORK_PHONE 1101 #define IDC_WORK_MOBILE 1102 #define IDC_WORK_IM 1103 #define IDC_WORK_STATE 1104 #define IDC_WORK_POSTCODE 1105 #define IDC_WORK_STREET 1106 #define IDC_WORK_FAX 1107 #define IDC_WORK_SUBURB 1108 #define IDC_HOME_POSTCODE 1109 #define IDC_COMPANY 1110 #define IDC_WORK_WEBPAGE 1111 #define IDC_SOCKS5 1112 #define IDC_DELETE 1113 #define IDS_MAIL_MERGE_Q 1114 #define IDC_ADD_SRC_FOLDER 1115 #define IDC_PROPERTIES 1116 #define IDD_OUTLOOK_ADD_FLD 1117 #define IDS_ASK_FOLDER_PASS 1118 #define IDC_DEF_SEND_TXT 1119 #define IDS_ERROR_SCRIPT_COMPILE 1120 #define IDS_ANY 1121 #define IDS_ERROR_NOTHING_TO_UPGRADE 1122 #define IDC_PAGE_ALL 1123 #define IDC_SAVE 1124 #define IDC_PAGE_RANGES 1125 #define IDS_PASSWORD_SAVED 1126 #define IDS_RESIZE_JPEG_QUAL 1127 #define IDC_TXT_MIN 1128 #define IDC_TXT_DOWNLOAD 1129 #define IDC_TXT_KBS 1130 #define IDM_SCRIPTING_CONSOLE 1131 #define IDD_PRINT_PREVIEW 1132 #define IDC_SAVE_IMG 1133 #define IDS_ACCSTAT_SETUP 1134 #define IDS_ACCSTAT_CONNECT 1135 #define IDS_ACCSTAT_TRANS 1136 #define IDS_ACCSTAT_WAIT 1137 #define IDS_ACCSTAT_DELETING 1138 #define IDS_ACCSTAT_FINISHED 1139 #define IDS_ACCSTAT_CANCELLED 1140 #define IDS_ERROR 1141 #define IDS_ENTER_KEY 1142 #define IDM_SCRIPT_DEBUG 1143 #define IDC_UPDATE 1144 #define IDC_1145 1145 #define IDS_CONTAINS 1146 #define IDS_STARTS_WITH 1147 #define IDS_ENDS_WITH 1148 #define IDS_SERVER 1149 #define IDS_1150 1150 #define IDM_MENU_1151 1151 #define IDS_TIME 1152 #define IDM_HTML_EDITOR 1153 #define IDS_ERROR_MAPI_INIT_FAILED 1154 #define IDD_CAL_RECUR 1155 #define IDS_WEEKS 1156 #define IDC_REMOVE_FILES 1157 #define IDC_SHOW_EXTRA 1158 #define IDC_IMAGE 1159 #define IDC_GUEST_ENTRY 1160 #define IDC_ADD_GUEST 1161 #define IDS_MISSING_PARENT 1162 #define IDS_ORIGINAL_MESSAGE 1163 #define IDS_PORTABLE_Q 1164 #define IDC_TABLE 1165 #define IDS_NO_EVENTS 1166 #define IDS_UNREAD_MAIL 1167 #define IDS_1168 1168 #define IDC_SHOW_ADDR 1169 #define IDS_AND_OPERATOR 1170 #define IDS_OR_OPERATOR 1171 #define IDS_MEMBER_OF_GROUP 1172 #define IDS_ACTION_MOVE_FOLDER 1173 #define IDS_ACTION_SOUND 1174 #define IDS_ACTION_OPEN 1175 #define IDS_ACTION_EXECUTE 1176 #define IDS_ACTION_SET_COLOUR 1177 #define IDS_ACTION_SET_LABEL 1178 #define IDS_ACTION_EMPTY_FOLDER 1179 #define IDS_ACTION_MARK_SPAM 1180 #define IDS_ACTION_SAVE_ATTACHMENTS 1181 #define IDS_ACTION_DELETE_ATTACHMENTS 1182 #define IDS_ACTION_CREATE_FOLDER 1183 #define IDS_SELECT_FOLDER 1184 #define IDC_BAYES_INCREMENTAL 1185 #define IDC_BAYES_DEBUG 1186 #define IDC_IMG_NOTES_TBL 1187 #define IDC_WORK_TABLE 1188 #define IDC_OUTGOING 1189 #define IDS_ERROR_FILE_DOESNT_EXIST 1190 #define IDS_ERROR_FOLDER_DOESNT_EXIST 1191 #define IDS_IMPORT 1192 #define IDD_SCRIBE_EXPORT 1193 #define IDC_INCOMING 1194 #define IDM_MENU_1195 1195 #define IDC_DEST 1196 #define IDC_SET_DEST 1197 #define IDC_HAS_GROUPS 1198 #define IDC_CAL_URL 1199 #define IDC_SPAM_FLD 1200 #define IDC_SET_SPAM 1201 #define IDC_SPAM_FOLDER 1202 #define IDC_SET_SPAM_FOLDER 1203 +#define IDC_PASSWORD 1204 #define IDS_ERROR_PRINT_FAILED 1214 #define IDS_ASK_ACCOUNT_PASSWORD 1215 #define IDS_SELECT_IO 1216 #define IDC_GUESTS 1217 #define IDS_DONT_SHOW_AGAIN 1218 #define IDS_INSTALL 1219 #define IDC_1220 1220 #define IDS_EDIT_MAIL_STORES 1224 #define IDS_ERROR_CANT_CREATE_FOLDER 1225 #define IDS_ERROR_CANT_CREATE_DB 1226 #define IDS_SHOW_CONSOLE 1227 #define IDC_STATUS 1228 #define IDS_SELECT_ACCOUNT 1229 #define IDS_1235 1235 #define IDC_MONDAY 1238 #define IDC_TUESDAY 1239 #define IDS_MONTHS 1246 #define IDC_NEVER 1249 #define IDC_1250 1250 #define IDC_AFTER 1251 #define IDC_AFTER_COUNT 1252 #define IDC_1254 1254 #define IDC_ON 1255 #define IDC_ON_DATE 1256 #define IDC_SUMMARY 1258 #define IDS_ALWAYS_SHOW 1260 #define IDS_OPEN_SOURCE 1262 #define IDS_DEFAULT 1263 #define IDS_IMPORT_SETTINGS_Q 1264 #define IDS_IMPORT_SETTINGS_DONE 1265 #define IDS_DELETE_ATTACHMENTS 1266 #define IDS_LANGUAGE 1267 #define IDS_1268 1268 #define IDS_SHOW_REMOTE_CONTENT 1274 #define IDC_DELETE_DAYS 1275 #define IDS_RESIZE_IMGS 1277 #define IDD_REMOTE_CONTENT 1279 #define IDC_WHITELIST 1282 #define IDS_REMOTE_CONTENT_MSG 1287 #define IDS_GNUPG_ERR_SAVE_FAILED 1291 #define IDS_MESSAGES_SENT 1293 #define IDS_MAIL_MERGE_EMPTY 1294 #define IDS_GNUPG_ERR_NO_OUTPUT 1295 #define IDS_FILTER_MAILINGLIST 1299 #define IDC_ADVANCED 1300 #define IDS_ACTION_COPY 1301 #define IDC_PAGE_PARTIAL 1302 #define IDD_CSV_EXPORT 1304 #define IDS_1305 1305 #define IDS_EXPORT_MSG 1312 #define IDS_MARK_ALL_READ 1313 #define IDD_MANAGE_FOLDERS 1314 #define IDC_MS_TBL 1315 #define IDC_OPEN_MS 1316 #define IDC_CLOSE_MS 1317 #define IDC_CREATE_MS 1318 #define IDC_CONVERT_MS 1320 #define IDC_REPAIR_MS 1321 #define IDC_MAIL_STORES 1324 #define IDS_1325 1325 #define IDS_1326 1326 #define IDC_MSG_ID 1327 #define IDC_FILTER 1328 #define IDS_GNUPG_ERR_WRONG_SEGS 1329 #define IDS_RELATIVE_TIMES 1333 #define IDS_1335 1335 #define IDS_CHECKING_OBJECTS 1336 #define IDS_ERROR_FOLDER_NOT_LOADED 1337 #define IDS_1338 1338 #define IDS_1339 1339 #define IDS_1340 1340 #define IDS_1341 1341 #define IDD_REPLICATE 1342 #define IDC_SRC 1346 #define IDC_DST 1348 #define IDM_CHECK_UPDATE 1350 #define IDS_1353 1353 #define IDS_1354 1354 #define IDS_ERROR_FONT_SETTINGS 1356 #define IDC_SEC_AUTH 1357 #define IDC_EDIT_CONTROL 1359 #define IDC_DELETE_LARGER 1360 #define IDC_DELETE_SIZE 1361 #define IDC_CLEAR 1364 #define IDS_ADD_TO_CAL 1367 #define IDS_ADD_TO_DICTIONARY 1368 #define IDS_ERROR_CANT_ADD_DICT 1370 #define IDS_SPELL_CHECK 1371 #define IDS_SPELL_DICT 1372 #define IDS_MAILSTORE_UPGRADE_Q 1373 #define IDS_ERROR_IMPORT 1374 #define IDS_ERROR_REPLICATION_FAILED 1375 #define IDS_ERROR_IMPORT_COUNT 1388 #define IDS_GNUPG_ERR_NOT_INSTALLED 1458 #define IDD_FOLDER_SELECT 1469 #define IDS_REPARSE 1471 #define IDD_FOLDER_FORMAT 1472 +#define IDS_GNUPG_PSW_PROMPT 1473 #define IDC_V1 1481 #define IDC_V2 1482 #define IDC_UP 1483 #define IDS_GROWL_SUPPORT 1485 #define IDS_GROWL 1486 #define IDC_MSG_DEL_ACTION 1487 #define IDC_MSG_DEL_NEXT 1488 #define IDC_MSG_DEL_CLOSE 1489 #define IDC_MSG_DEL_PREV 1490 #define IDC_RECEIVE_LOG 1514 #define IDS_EMAIL_PROGRESS 1516 #define IDS_COPY_LOG_TO_CLIP 1517 #define IDC_SMTP_PORT 1519 #define IDS_RESIZE_MAX_PX 1522 #define IDS_RESIZING 1523 #define IDS_RESIZE_MAX_SIZE 1524 #define IDS_UPGRADE_KEY 1525 #define IDC_UPGRADE 1526 #define IDS_MAIL2_DEPRECATED 1527 #define IDS_SSL_DEBUG 1528 #define IDS_CONSOLE 1529 #define IDC_SPELL_LANG 1531 #define IDC_WIDTH 1535 #define IDC_SLIDE 1537 #define IDC_BAYES_DELETE_ON_SERVER 1541 #define IDC_BAYES_DELETE_ATTACHMENTS 1543 #define IDC_TENTATIVE 1548 #define IDS_DELETING 1549 #define IDS_DONT_SHOW_EMOJI 1550 #define IDS_HELP 1551 #define IDS_DESKTOP 1552 #define IDS_PORTABLE 1553 #define IDC_BTNS_TABLE 1556 #define IDS_GNUPG_CHECKING 1558 #define IDS_GNUPG_ERR_NO_SIGN_ENC 1561 #define IDS_GNUPG_ERR_CANT_START 1565 #define IDS_GNUPG_ERR_CODE 1568 #define IDS_GNUPG_ERR_NO_CONTENT 1570 #define IDS_GNUPG_ERR_READ_FAIL 1572 #define IDS_GNUPG_ERR_NO_MAIL 1574 #define IDS_GNUPG_ERR_NO_ROOT 1578 #define IDS_GNUPG_ERR_WRONG_MIME 1580 #define IDS_GNUPG_ERR_NO_ENC_MIME 1581 #define IDS_GNUPG_ERR_NO_ID 1582 #define IDS_GNUPG_DECRYPT_CANCEL 1583 #define IDS_GNUPG_ERR_NO_DATA 1584 #define IDS_GNUPG_ERR_DECRYPT_FAIL 1585 #define IDS_GNUPG_ERR_NO_SENDER_EMAIL 1586 #define IDS_GNUPG_ERR_NO_PRIV_KEY 1587 #define IDS_GNUPG_ERR_NO_PUB_KEY 1588 #define IDS_GNUPG_ERR_IMPORT_FAIL 1589 #define IDS_GNUPG_ERR_SIGN_ENC_CANCEL 1590 #define IDS_GNUPG_ERR_TEMP_WRITE 1591 #define IDS_GNUPG_ERR_EXPORT_TEMP 1592 #define IDS_GNUPG_ERR_NEW_ATTACH_FAIL 1593 #define IDS_GNUPG_ERR_REPARENT 1594 #define IDS_GNUPG_ERR_RECIP_NO_EMAIL 1595 #define IDS_GNUPG_ERR_WRITE 1596 #define IDS_GNUPG_ERR_ENCRYPT_FAIL 1597 #define IDS_GNUPG_ERR_ONE_OR_MORE 1598 #define IDS_GNUPG_DECRYPT_OK 1599 #define IDS_GNUPG_ENCRYPTED 1600 #define IDS_GNUPG_ENCRYPTED_AND_SIGNED 1601 #define IDS_GNUPG_SIGNED 1602 #define IDS_GNUPG_GOOD_SIG 1603 #define IDS_GNUPG_BAD_SIG 1604 #define IDS_GNUPG_SIG_MSG 1605 #define IDS_GNUPG_SIG_NO_ID 1606 #define IDS_GNUPG_ERR_INVALID_DECRYPTION 1607 #define IDS_GNUPG_CHECK_MSG 1608 #define IDS_SHOW_SCRIPT_DEBUGGER 1609 #define IDC_ACC_LOG 1613 #define IDC_1615 1615 #define IDC_1616 1616 #define IDS_SHOW_SIZE_IN_KIB 1617 #define IDS_GNUPG_GET_GPG 1619 #define IDC_START_REL 1620 #define IDC_END_REL 1621 #define IDS_YESTERDAY 1622 #define IDC_1626 1626 #define IDS_MBOX_SELECT_FOLDER 2000 #define IDS_MBOX_READING 2001 #define IDS_MBOX_EXPORT 2002 #define IDS_MBOX_EXPORT_FOLDER 2003 #define IDS_MBOX_WRITING 2004 #define IDS_STORE2_ERROR_COMPACT 2005 #define IDS_STORE2_DISCARD_FIX 2006 #define IDS_STORE2_SAVE_DEBUG 2007 #define IDS_NAME 2008 #define IDS_NO_MAIL_TO_SEND 2009 #define IDS_NO_OUTGOING_FOLDER 2010 #define IDS_ERROR_NO_NAME_EMAIL 2011 #define IDS_APPNAME 2012 #define IDS_SURNAME 2013 #define IDC_SET_CALENDER 2014 #define IDC_NEW_MAIL_NOTIFY 2015 #define IDD_NEW_MAIL_NOTIFY 2016 #define IDC_NEW_MAIL 2017 #define IDC_REMEMBER_PSW 2020 #define IDS_36 2021 #define IDS_37 2022 #define IDC_OPEN 2023 #define IDC_GLYPH_SUB 2031 #define IDC_FILTERS 2032 #define IDD_OUTLOOK_IMPORT 2040 #define IDD_WARN_DEFAULT 2041 #define IDC_POP_RECIP 2042 #define IDD_ADDCONTACT 2043 #define IDD_CONTACT 2044 #define IDD_FOLDER_NAME 2045 #define IDD_POPVIEW 2047 #define IDC_FPR_NONE 3000 #define IDC_FPR_USER 3001 #define IDC_FPR_ADMIN 3002 #define IDC_FPW_NONE 3003 #define IDC_FPW_USER 3004 #define IDC_FPW_ADMIN 3005 #define IDM_BOUNCE 40000 #define IDM_SOFTWARE_KEY 40001 #define IDM_UPGRADE_MAIL_STORES 40002 #define IDM_OPTIONS 40004 #define IDM_PRINT 40005 #define IDM_PRINTSETUP 40006 #define IDM_EXIT 40007 #define IDM_NEW_EMAIL 40008 #define IDM_REPLY 40009 #define IDM_REPLY_ALL 40010 #define IDM_FORWARD 40011 #define IDM_SEND_MAIL 40012 #define IDM_NEW_CONTACT 40014 #define IDM_ABOUT 40019 #define IDM_IMPORT_NS_CONTACTS 40020 #define IDM_IMPORT_OUTLOOK_PAB 40025 #define IDM_IMPORT_OUTLOOK_ITEMS 40027 #define IDM_NEW_FILTER 40038 #define IDM_IMPORT_TEXT_MBOX 40047 #define IDM_EXPORT_TEXT_MBOX 40048 #define IDM_IMP_MBX_EMAIL 40049 #define IDM_IMP_DBX_EMAIL 40050 #define IDM_NEW_DRAFT 40060 #define IDM_NO_TEMPLATES 40061 #define IDM_FILTER_CURRENT_FOLDER 41010 #define IDM_IMP_EUDORA_ADDR 41043 #define IDM_IMP_MOZILLA_ADDR 41045 #define IDM_FIND 41055 #define IDM_IMPORT_CSV 41065 #define IDM_WORK_OFFLINE 41075 #define IDM_EXPORT_CSV 41085 #define IDM_NEW_GROUP 41095 #define IDM_SECURITY 41105 #define IDM_BAYES_SETTINGS 41116 #define IDM_BAYES_CHECK 41117 #define IDM_BUILD_BAYES_DB 41118 #define IDM_LOGOUT 41129 #define IDM_FOLDERS_DOWN_LEFT 41142 #define IDM_PREVIEW_ALONG_BOTTOM 41143 #define IDM_LAYOUT1 41144 #define IDM_LAYOUT2 41145 #define IDM_LAYOUT3 41146 #define IDM_EXPORT_OUTLOOK_ITEMS 41147 #define IDM_CRASH 41148 #define IDM_TUTORIALS 41149 #define IDM_DEBUG_INFO 41150 #define IDM_VERSION_HISTORY 41151 #define IDM_MEMECODE 41152 #define IDM_SET_READ 41155 #define IDM_IMP_MOZILLA_MAIL 41156 #define IDM_DEBUG_FILTERS 41157 #define IDM_FILTERS_DISABLE 41158 #define IDM_DUMP_MEM 41159 #define IDM_FILTER_SELECTION 41160 #define IDM_EXPORT_SCRIBE 41161 #define IDM_TOOLS_MENU 41163 #define IDM_REPLICATE 41164 #define IDM_EXPORT 41165 #define IDM_COPY 'copy' #define IDM_CUT 'cut ' #define IDM_PASTE 'past' diff --git a/src/Encryption/GnuPG.cpp b/src/Encryption/GnuPG.cpp --- a/src/Encryption/GnuPG.cpp +++ b/src/Encryption/GnuPG.cpp @@ -1,1973 +1,1980 @@ /* https://lists.gnupg.org/pipermail/gnupg-users/2011-November/043223.html gpg --list-packets ? Mime hierarchy: Signed: multipart/signed "This is an OpenPGP/MIME signed message (RFC 4880 and 3156)" { multipart/mixed text/plain Body of the message } application/pgp-signature "-----BEGIN PGP SIGNATURE-----" Signed, key attached: multipart/signed "This is an OpenPGP/MIME signed message (RFC 4880 and 3156)" { multipart/mixed text/plain Body of the message application/pgp-keys "-----BEGIN PGP PUBLIC KEY BLOCK-----" } application/pgp-signature "-----BEGIN PGP SIGNATURE-----" Signed, HTML, attachment, key: multipart/signed { multipart/mixed multipart/mixed multipart/alternative text/plain text/html application/octet-stream application/pgp-keys } application/pgp-signature Encrypted: multipart/encrypted application/pgp-encrypted application/octet-stream { multipart/mixed multipart/mixed text/plain } Encrypted + key attached: multipart/encrypted application/pgp-encrypted application/octet-stream { multipart/mixed multipart/mixed text/plain application/pgp-keys } */ #include "lgi/common/Lgi.h" #include "Scribe.h" #include "GnuPG.h" #include "lgi/common/TextLabel.h" #include "lgi/common/Button.h" #include "lgi/common/CheckBox.h" #include "lgi/common/Combo.h" #include "lgi/common/Css.h" #include "lgi/common/ThreadEvent.h" #include "lgi/common/SubProcess.h" #include "ScribeListAddr.h" #include "Store3Common.h" #include "lgi/common/LgiRes.h" #include "resdefs.h" #include "lgi/common/CssTools.h" ////////////////////////////////////////////////////////////////////////////////////////// enum Ctrls { IDC_SIGN = 700, IDC_ENCRYPT, IDC_ATTACH_PUB_KEY, IDC_DECRYPT, IDC_INSTALL }; static LColour cGood (0, 204, 0); static LColour cWarn (255, 154, 0); static LColour cError (255, 0, 0); static LColour cTxt (L_TEXT); #define cDefaultListItemColour 0 #define PANEL_BORDER_PX 2 static const char *GpgInstall = "https://www.gnupg.org/download/index.en.html"; static const char *GpgBin = "gpg" LGI_EXECUTABLE_EXT; static LString GpgBinPath; #define SECONDS * 1000 #define MINUTES * 60 #define GPG_KEY_STALE_TIMEOUT (10 MINUTES) #define DecryptStatus(val) \ { \ if (callback) callback(val); \ return; \ } typedef LArray KeyArr; typedef LAutoPtr KeyArrAuto; struct GpgJob { enum JobType { JobGetKeys, JobCheckSig, JobDecrypt, } Type; LViewI *Owner; GpgJob(JobType t) { Type = t; Owner = NULL; } // Get keys: LAutoPtr Emails; // Check sig: LAutoStreamI Msg; LMessage::Param UserValue; // Decrypt LString Password; }; struct LTempFile : public LFile { LString Path; LTempFile(const char *path) { if (Open(path, O_READ)) { Path = path; } } ~LTempFile() { if (Path) { Close(); FileDev->Delete(Path, false); } } }; struct GpgConnectorPriv : public LThread, public LMutex { LThreadEvent Event; private: bool Loop; KeyArr Keys; LArray Work; uint64 KeysTs; public: GpgConnectorPriv() : LThread("GpgConnectorPrivThread"), LMutex("GpgConnectorPrivMutex") { Loop = true; KeysTs = 0; Run(); } ~GpgConnectorPriv() { Loop = false; Event.Signal(); while (!IsExited()) LSleep(1); } void AddWork(GpgJob *j) { if (Lock(_FL)) { Work.Add(j); Unlock(); } } private: LString RunGpg(const char *Args) { LString Output; LSubProcess p(GpgBinPath, Args); if (p.Start(true, false)) { char Buf[256]; while (true) { ssize_t r = p.Read(&Buf, sizeof(Buf)-1); if (r > 0) { Buf[r] = 0; Output += Buf; } else break; } } return Output; } void ParseKeys(KeyArr &k, LString &str) { bool GotDash = false; LString::Array a = str.Split(EOL_SEQUENCE); LString KeyId; for (unsigned i=0; i 0) { if (b[0].Equals("sec") || b[0].Equals("pub")) { if (b.Length() == 4) KeyId = b[2]; } else if (b[0].Equals("uid")) { LString Nm = Ln(21, -1).Strip(); LAutoString Name, Addr; DecodeAddrName(Nm, Name, Addr, NULL); if (ValidStr(Name) && ValidStr(Addr)) { GpgConnector::KeyInfo &Cur = k.New(); Cur.KeyId = KeyId; Cur.Name = Name; Cur.Email = Addr; } else LgiTrace("%s:%i - Error parsing '%s'\n", _FL, Nm.Get()); } } } else if (stristr(Ln, "--------")) { GotDash = true; } } } bool GetKeys() { uint64 Now = LCurrentTime(); if (Now - KeysTs > GPG_KEY_STALE_TIMEOUT) { KeysTs = Now; LString s = RunGpg("-k"); if (s) ParseKeys(Keys, s); s = RunGpg("-K"); if (s) { KeyArr Priv; ParseKeys(Priv, s); LHashTbl, GpgConnector::KeyInfo*> Hash; for (auto &k: Keys) { if (k.Email) Hash.Add(k.Email, &k); else LgiTrace("%s:%i - No email for key?\n", _FL); } for (unsigned i=0; iFlags |= GPG_HAS_PRIV_KEY; } } } return Keys.Length() > 0; } bool Save(const char *Path, LString &s) { LFile f; if (!f.Open(Path, O_WRITE)) return false; f.SetSize(0); return f.Write(s, s.Length()) == s.Length(); } bool Save(const char *Path, LStreamI *s) { LFile f; if (!f.Open(Path, O_WRITE)) return false; f.SetSize(0); LCopyStreamer Cp; int64 SrcSz = s->GetSize(); int64 Copied = Cp.Copy(s, &f); return SrcSz == Copied; } void CheckSignature(LViewI *Owner, LAutoStreamI UserMsg, LMessage::Param UserVal) { LString Msg; int64 Sz = 0; int64 Rd = 0; ptrdiff_t HdrSize = 0; LString Start; LArray Segs; LMime Tmp; LString Hdrs; char *Boundary = NULL; LAutoPtr Resp(new GpgSigCheckResponse); if (!Resp) return; // Not much else we can do. Resp->UserValue = UserVal; if (!UserMsg) { Resp->Error.Printf(LLoadString(IDS_GNUPG_ERR_NOMSG)); goto OnSigCheckError; } // We have to parse out just the part of the email that is signed. And we // can't use the LMime class because that would decode it too much and lose // the exact formatting. Read the whole thing into memory and find the MIME // boundary. Sz = UserMsg->GetSize(); UserMsg->SetPos(0); if (!Msg.Length((int)Sz)) { Resp->Error.Printf("Can't size string to " LPrintfInt64, Sz); goto OnSigCheckError; } for (int64 i=0; iRead(Msg.Get() + i, Msg.Length() - i); if (Rd <= 0) { Resp->Error.Printf("Read error: i=%i, Rd=%i, Sz=" LPrintfInt64, i, Rd, Sz); goto OnSigCheckError; } i += Rd; } HdrSize = Msg.Find("\r\n\r\n"); Hdrs = Msg(0, HdrSize); Tmp.SetHeaders(Hdrs); Boundary = Tmp.GetBoundary(); if (!Boundary) { Resp->Error = LLoadString(IDS_GNUPG_ERR_NO_BOUNDARY); goto OnSigCheckError; } // Now look through the message and find all the segments... Start.Printf("\r\n--%s", Boundary); for (ptrdiff_t i = 0; i < (ptrdiff_t)Msg.Length(); ) { ptrdiff_t Next = Msg.Find(Start, i); if (Next > 0) { // Is it an end or starting boundary? ptrdiff_t k = Next + Start.Length(); LString Chars = Msg(k, k + 2); bool IsEnd = Chars == "--"; if (IsEnd) { if (Segs.Length() == 0) { Resp->Error = LLoadString(IDS_GNUPG_ERR_NO_MIME); goto OnSigCheckError; } Segs.Last().Len = Next - Segs.Last().Start; i = k + 2; } else { if (Segs.Length() > 0) { // Finish last segment Segs.Last().Len = Next - Segs.Last().Start; } char *m = Msg; while (IsWhiteSpace(m[k])) k++; LRange &r = Segs.New(); r.Start = k; r.Len = 0; i = k; } } else break; } if (Segs.Length() == 2) { // char *m = Msg; LRange &Body = Segs[0]; LRange &Sig = Segs[1]; // Get the 2 parts from the whole message.. LString SignedText = Msg(Body.Start, Body.Start + Body.Len); LString Signature = Msg(Sig.Start, Sig.Start + Sig.Len); ptrdiff_t Break = Signature.Find("\r\n\r\n"); if (Break > 0) Signature = Signature(Break + 4, -1); // Save them to files: LFile::Path TextPath = ScribeTempPath(), SigPath = ScribeTempPath(); TextPath += "signed.txt"; SigPath += "signature.txt"; if (!Save(TextPath, SignedText) || !Save(SigPath, Signature)) { Resp->Error = LLoadString(IDS_GNUPG_ERR_SAVE_FAILED); goto OnSigCheckError; } // Now call GnuPG to verify the signature... LString Args; Args.Printf("--verify \"%s\" \"%s\"", SigPath.GetFull().Get(), TextPath.GetFull().Get()); LString Output = RunGpg(Args); if (Output) { LString::Array a = Output.SplitDelimit("\n"); for (unsigned i=0; i= 0) { LString::Array w = Line.SplitDelimit(" "); // Check if the signature is good... if (w.Length() > 2) Resp->SignatureMatch = w[1].Lower() == "good"; // Get identity... w = Line.SplitDelimit("\""); if (w.Length() >= 2 && w[1].Find("@") >= 0) { Resp->Identity = w[1]; } } else if (Line.Lower().Find("signature made") >= 0) { // Get date... LString::Array w = Line.SplitDelimit(" "); int MadeIdx = -1; LString::Array DateParts; for (unsigned i=0; i 0) Resp->TimeStamp.SetDate(w[i]); else if (w[i].Find(":") > 0) { Resp->TimeStamp.SetTime(w[i]); MadeIdx = -1; } else if (w[i].Lower() == "made") MadeIdx = i; else if (MadeIdx >= 0 && (int)i > MadeIdx) DateParts.New() = w[i]; } if (Resp->TimeStamp.Year() == 0 && DateParts.Length() > 0) { LString s = LString(" ").Join(DateParts); Resp->TimeStamp.SetDate(s); } } } } else { Resp->Error = LLoadString(IDS_GNUPG_ERR_NO_OUTPUT); } #ifndef _DEBUG // Clean up temporary files... FileDev->Delete(TextPath, false); FileDev->Delete(SigPath, false); #endif printf("Txt=%s\nSig=%s\n", (const char*)TextPath, (const char*)SigPath); } else { Resp->Error.Printf(LLoadString(IDS_GNUPG_ERR_WRONG_SEGS), Segs.Length()); } OnSigCheckError: Owner->PostEvent(M_GNUPG_SIG_CHECK, (LMessage::Param) Resp.Release()); } void Decrypt(GpgJob *j) { LAutoPtr Resp(new GpgDecryptResponse); if (!Resp || !j) return; Resp->UserValue = j->UserValue; LFile::Path InPath = ScribeTempPath(); InPath += "encrypted.txt"; LFile::Path OutPath = ScribeTempPath(); OutPath += "decrypted.txt"; if (!Save(InPath, j->Msg)) { Resp->Error = "Failed to save file for decrypting."; } else { LString Args; Args.Printf("--batch --passphrase-fd 0 --output \"%s\" --decrypt \"%s\"", OutPath.GetFull().Get(), InPath.GetFull().Get()); LSubProcess Proc(GpgBinPath, Args); if (!Proc.Start(true, true)) { Resp->Error = "Can't start the GnuPG sub-process."; } else { char Buf[256]; LVariant v; if (Proc.GetValue(LDomPropToString(StreamReadable), v) && v.CastInt32() != 0) { ssize_t r = Proc.Read(Buf, sizeof(Buf)-1); Buf[MAX(r, 0)] = 0; } LString PswStr; PswStr.Printf("%s\n", j->Password.Get()); ssize_t w = Proc.Write(PswStr.Get(), PswStr.Length()); if (w < 0) { ssize_t r = Proc.Read(Buf, sizeof(Buf)-1); Buf[MAX(r, 0)] = 0; Resp->Error = Buf[0] ? Buf : "Can't write to the GnuPG sub-process."; } else { ssize_t r = Proc.Read(Buf, sizeof(Buf)-1); Buf[MAX(r, 0)] = 0; int Result = Proc.Wait(); LFile *f; if (Result) { if (Buf[0]) Resp->Error = Buf[0]; else Resp->Error.Printf("GnuPG encryption process failed with code: %i", Result); } else if ( !Resp->Data.Reset(f = new LTempFile(OutPath)) || !f->IsOpen()) { Resp->Data.Reset(); Resp->Error.Printf("Decrypt failed: Can't open '%s' for reading.", OutPath.GetFull().Get()); } else { // Success? } } } } // Clean up input file (encrypted) // The output file will be deleted by the M_GNUPG_DECRYPT handler. if (LFileExists(InPath)) { FileDev->Delete(InPath, false); } j->Owner->PostEvent(M_GNUPG_DECRYPT, (LMessage::Param) Resp.Release()); } int Main() { LThreadEvent::WaitStatus s; while ((s = Event.Wait()) == LThreadEvent::WaitSignaled) { if (!Loop) break; LAutoPtr j; if (Lock(_FL)) { if (Work.Length()) { j.Reset(Work[0]); Work.DeleteAt(0, true); } Unlock(); } if (j) { switch (j->Type) { case GpgJob::JobGetKeys: { if (Keys.Length() == 0) GetKeys(); LHashTbl,bool> Map; for (unsigned i=0; iEmails->Length(); i++) { Map.Add((*j->Emails)[i], true); } KeyArrAuto Inf(new KeyArr); for (unsigned i=0; iNew(); out.Email = in.Email.Get(); out.Name = in.Name.Get(); out.KeyId = in.KeyId.Get(); out.Flags = in.Flags; } j->Owner->PostEvent(M_GNUPG_KEY_INFO, 0, (LMessage::Param)Inf.Release()); break; } case GpgJob::JobCheckSig: { CheckSignature(j->Owner, j->Msg, j->UserValue); break; } case GpgJob::JobDecrypt: { Decrypt(j); break; } default: { LAssert(!"Invalid type."); break; } } } } return 0; } }; bool GpgConnector::IsInstalled() { #ifdef WINNATIVE char *Str = NULL; errno_t Err = _dupenv_s(&Str, NULL, "PATH"); if (Err) { LgiTrace("%s:%i - _dupenv_s failed with %i\n", _FL, Err); return false; } LString Path = Str; free(Str); #else LString Path = getenv("PATH"); #ifdef MAC Path += LGI_PATH_SEPARATOR"/opt/local/bin"; #endif #endif LString::Array Parts = Path.Split(LGI_PATH_SEPARATOR); for (unsigned i = 0; i < Parts.Length(); i++) { LFile::Path p(Parts[i]); p += GpgBin; if (p.IsFile()) { GpgBinPath = p; return true; } } return false; } GpgConnector::GpgConnector() { d = new GpgConnectorPriv; } GpgConnector::~GpgConnector() { delete d; } bool GpgConnector::GetKeyInfo(LViewI *Target, LString::Array &Emails) { if (!Target #if LGI_VIEW_HANDLE || !Target->Handle() #endif ) { LAssert(!"Invalid target."); return false; } if (!d->Lock(_FL)) return false; GpgJob *j = new GpgJob(GpgJob::JobGetKeys); if (j) { j->Emails.Reset(new LString::Array(Emails)); j->Owner = Target; d->AddWork(j); } d->Unlock(); return d->Event.Signal(); } bool GpgConnector::CheckSignature(LViewI *Target, LAutoStreamI Rfc822Msg, LMessage::Param UserVal) { if (!Target #if LGI_VIEW_HANDLE || !Target->Handle() #endif ) { LAssert(!"Invalid target."); return false; } if (!d->Lock(_FL)) return false; GpgJob *j = new GpgJob(GpgJob::JobCheckSig); if (j) { j->Owner = Target; j->Msg = Rfc822Msg; j->UserValue = UserVal; d->AddWork(j); } d->Unlock(); return d->Event.Signal(); } bool GpgConnector::Decrypt(LViewI *Target, LAutoStreamI Data, LString Password, LMessage::Param UserVal) { if (!Target #if LGI_VIEW_HANDLE || !Target->Handle() #endif ) { LAssert(!"Invalid target."); return false; } if (!d->Lock(_FL)) return false; GpgJob *j = new GpgJob(GpgJob::JobDecrypt); if (j) { j->Owner = Target; j->Msg = Data; j->Password = Password; j->UserValue = UserVal; d->AddWork(j); } d->Unlock(); return d->Event.Signal(); } //////////////////////////////////////////////////////////////////////////////////////////////// struct MailUiGpgPriv { struct UserPassword { uint64 Ts; LString Email; LString Password; }; // Objs ScribeWnd *App; MailUi *Ui; // UI LCheckBox *Enc; LCheckBox *Sign; LCheckBox *Attach; LTextLabel *Msg; KeyArrAuto Inf; LTableLayout *Table; LButton *Decrypt, *Install; // Options bool WritingEmail; bool Encrypted; bool Signed; // Passwords LArray Psw; MailUiGpgPriv(ScribeWnd *app, MailUi *ui, bool writingEmail) { App = app; Ui = ui; Enc = NULL; Sign = NULL; Attach = NULL; Msg = NULL; Table = NULL; Decrypt = NULL; Install = NULL; WritingEmail = writingEmail; Encrypted = false; Signed = false; } AddressList *GetAddrLst() { AddressList *AddrLst = NULL; Ui->GetViewById(IDC_TO, AddrLst); return AddrLst; } void NotInstalled() { SetError(LLoadString(IDS_GNUPG_ERR_NOT_INSTALLED)); if (Install) Install->Visible(true); if (Enc) Enc->Enabled(false); if (Sign) Sign->Enabled(false); if (Attach) Attach->Enabled(false); } void Set(const char *Str, LColour &Col) { if (!Msg || !Table) { LgiTrace("%s:%i - Can't set message.\n", _FL); return; } Msg->GetCss(true)->Color(Col); Msg->Name(Str); LNotification note(LNotifyTableLayoutRefresh); Table->OnNotify(Msg, note); } void SetError(const char *Str) { Set(Str, cError); } void SetWarning(const char *Str) { Set(Str, cWarn); } void SetStatus(const char *Str) { Set(Str, cTxt); } void SetSuccess(const char *Str) { Set(Str, cGood); } void GetPassword(LViewI *Parent, LString Addr, std::function Callback) { for (unsigned i=0; iDoModal([this, Dlg, Addr, Callback](auto dlg, auto ctrlId) + auto p = Parent->GetGView(); + auto Dlg = new LInput(Parent, "", Msg, LLoadString(IDC_PASSWORD), true); + Dlg->DoModal([this, Dlg, Addr, Callback](auto dlg, auto ok) { - if (ctrlId) + if (ok) { UserPassword &p = Psw.New(); p.Email = Addr; p.Password = Dlg->GetStr(); p.Ts = LCurrentTime(); if (Callback) Callback(p.Password); } delete dlg; }); } }; LCss::Len Px(int px) { return LCss::Len(LCss::LenPx, (float)px); } MailUiGpg::MailUiGpg(ScribeWnd *App, MailUi *Ui, int ColX1, int ColX2, bool WritingEmail) { d = new MailUiGpgPriv(App, Ui, WritingEmail); int TextY = 6; #ifdef MAC int ChkY = 1; #else int ChkY = 6; #endif if (AddView(d->Table = new LTableLayout(50))) { Mail *m = Ui->GetItem(); LDataI *obj = m ? m->GetObject() : NULL; int x = 0; LTextLabel *Txt; auto *c = d->Table->GetCell(x++, 0); c->Position(LCss::PosAbsolute); c->Left(Px(ColX1 - PANEL_BORDER_PX)); c->Top(Px(TextY - PANEL_BORDER_PX)); c->Add(Txt = new LTextLabel(IDC_STATIC, ColX1, TextY, -1, -1, "GnuPG:")); if (WritingEmail) { c = d->Table->GetCell(x++, 0); c->Position(LCss::PosAbsolute); c->Left(Px(ColX2 - PANEL_BORDER_PX + 1)); c->Top(Px(ChkY - PANEL_BORDER_PX)); c->Add(d->Enc = new LCheckBox(IDC_ENCRYPT, 0, 0, -1, -1, LLoadString(IDS_GNUPG_ENCRYPT))); c = d->Table->GetCell(x++, 0); c->PaddingTop(Px(ChkY - PANEL_BORDER_PX)); c->Add(d->Sign = new LCheckBox(IDC_SIGN, 0, 0, -1, -1, LLoadString(IDS_GNUPG_SIGN))); c = d->Table->GetCell(x++, 0); c->PaddingTop(Px(ChkY - PANEL_BORDER_PX)); c->Add(d->Attach = new LCheckBox(IDC_ATTACH_PUB_KEY, 0, 0, -1, -1, LLoadString(IDS_GNUPG_ATTACH_PUB_KEY))); } else { c = d->Table->GetCell(x++, 0); c->Position(LCss::PosAbsolute); c->Left(Px(ColX2 - PANEL_BORDER_PX + 1)); if (c->Add(d->Decrypt = new LButton(IDC_DECRYPT, 0, 0, -1, -1, LLoadString(IDS_GNUPG_DECRYPT)))) { LDataPropI *seg = obj ? obj->GetObj(FIELD_MIME_SEG) : NULL; auto mimeType = seg ? seg->GetStr(FIELD_MIME_TYPE) : NULL; if (mimeType) { d->Signed = !_stricmp(mimeType, sMultipartSigned); d->Encrypted = !_stricmp(mimeType, sMultipartEncrypted); } d->Decrypt->Enabled(d->Encrypted); } } c = d->Table->GetCell(x++, 0); c->PaddingTop(Px(TextY - PANEL_BORDER_PX)); c->PaddingLeft(LCss::Len(LCss::LenEm, 1.0f)); c->Add(d->Msg = new LTextLabel(IDC_MSG, 0, 0, 300, -1, "...")); c = d->Table->GetCell(x++, 0); c->TextAlign(LCss::AlignRight); if ((d->Install = new LButton(IDC_INSTALL, 0, 0, -1, -1, LLoadString(IDS_GNUPG_GET_GPG)))) { d->Install->Visible(false); c->Add(d->Install); } if (d->Encrypted) { d->SetWarning("Message is encrypted."); } } } MailUiGpg::~MailUiGpg() { delete d; if (GetParent()) { LNotification note(LNotifyItemDelete); GetParent()->OnNotify(this, note); } } void MailUiGpg::OnRecipientChange() { if (!d->WritingEmail || !d->Enc || !d->Sign) return; // Don't care... AddressList *AddrLst = d->GetAddrLst(); if (!AddrLst) { d->SetError("No AddressList."); return; } GpgConnector *Gpg = d->App->GetGpgConnector(); if (!Gpg) { d->NotInstalled(); return; } List a; if (!AddrLst->GetAll(a)) { d->SetStatus(LLoadString(IDS_GNUPG_ERR_NO_RECIP)); return; } if (d->Enc->Value() || d->Sign->Value()) { // Do we have public keys for each of the recipients? d->SetWarning(LLoadString(IDS_GNUPG_CHECKING)); LString::Array Emails; for (auto i: a) { if (i->sAddr) Emails.New() = i->sAddr; } LCombo *cbo; if (d->Ui->GetViewById(IDC_FROM, cbo)) { const char *Frm = cbo->Name(); LAutoString Name, Email; DecodeAddrName(Frm, Name, Email, NULL); if (Email) Emails.New() = Email; } Gpg->GetKeyInfo(this, Emails); } else { d->SetStatus(LLoadString(IDS_GNUPG_ERR_NO_SIGN_ENC)); // Revert list items to no colour... for (auto i: a) { i->SetInt(FIELD_COLOUR, cDefaultListItemColour); i->Update(); } } } // This gets all the events from MailUi::OnNotify as well as any events // from MailUiGpg's child controls. // \returns non-zero if further processing in MailUi::OnNotify should be blocked. int MailUiGpg::OnNotify(LViewI *Ctrl, LNotification n) { switch (Ctrl->GetId()) { case IDC_TO: { switch (n.Type) { case LNotifyItemInsert: case LNotifyItemDelete: // Recipients changed... check for keys... OnRecipientChange(); break; default: break; } break; } case IDC_ENCRYPT: case IDC_SIGN: { OnRecipientChange(); break; } case IDC_DECRYPT: { Decrypt(NULL); break; } case IDC_INSTALL: { LExecute(GpgInstall); break; } } return 0; } void DeleteChildSegments(LDataPropI *d) { LDataIt It = d->GetList(FIELD_MIME_SEG); for (unsigned i=0; iLength(); ) { LDataPropI *c = (*It)[i]; DeleteChildSegments(c); LDataI *cdi = dynamic_cast(c); if (cdi) { // This deletes the on disk representation. cdi->Delete(); // This removes the object from the segment tree and // frees the memory delete cdi; } else { LgiTrace("%s:%i - DeleteChildSegments: Wrong object type.\n", _FL); LAssert(0); i++; // Skip this? Maybe we should break? } } } LString MailUiGpg::GetPublicKey(const char *Email) { LString s; if (Email) { LString Args; Args.Printf("-a --export %s", Email); LSubProcess Proc(GpgBinPath, Args); if (!Proc.Start(true, false)) { d->SetError(LLoadString(IDS_GNUPG_ERR_CANT_START)); return 1; } ssize_t r; char Buf[256] = ""; while ((r = Proc.Read(Buf, sizeof(Buf)-1)) > 0) { Buf[r] = 0; s += Buf; } int Result = Proc.Wait(); if (Result) { LString Msg; Msg.Printf(LLoadString(IDS_GNUPG_ERR_CODE), Result); d->SetError(Buf[0] ? Buf : Msg); s.Empty(); } } return s; } bool MailUiGpg::ReadFile(LArray &Data, const char *Path) { LFile f; if (!f.Open(Path, O_READ)) { LString s; s.Printf(LLoadString(IDS_ERROR_CANT_READ), Path); d->SetError(s); return false; } if (f.GetSize() < 0) { LString s; s.Printf(LLoadString(IDS_GNUPG_ERR_NO_CONTENT), Path); d->SetError(s); return false; } if (!Data.Length((uint32_t)f.GetSize())) { d->SetError("Memory alloc failed."); return 1; } if (f.Read(&Data[0], Data.Length()) != Data.Length()) { LString s; s.Printf(LLoadString(IDS_GNUPG_ERR_READ_FAIL), Path); d->SetError(s); return false; } return true; } void MailUiGpg::Decrypt(std::function callback) { // Get the connector... GpgConnector *Conn = d->App->GetGpgConnector(); if (!Conn) { d->NotInstalled(); DecryptStatus(1); } // Find the right attachment... Mail *m = d->Ui->GetItem(); if (!m) { d->SetError(LLoadString(IDS_GNUPG_ERR_NO_MAIL)); DecryptStatus(1); } LDataPropI *Root = m->GetObject()->GetObj(FIELD_MIME_SEG); if (!Root) { d->SetError(LLoadString(IDS_GNUPG_ERR_NO_ROOT)); DecryptStatus(1); } auto Mt = Root->GetStr(FIELD_MIME_TYPE); if (!Mt || _stricmp(Mt, sMultipartEncrypted)) { d->SetError(LLoadString(IDS_GNUPG_ERR_WRONG_MIME)); DecryptStatus(1); } LDataI *EncryptedObj = NULL; LArray Objs; if (!m->GetAttachmentObjs(Objs)) DecryptStatus(1); for (unsigned i=0; iGetStr(FIELD_MIME_TYPE); if (Mt && !_stricmp(Mt, sAppOctetStream)) { EncryptedObj = Objs[i]; break; } } if (!EncryptedObj) { d->SetError(LLoadString(IDS_GNUPG_ERR_NO_ENC_MIME)); DecryptStatus(1); } // Get the password for decryption... LHashTbl,ScribeAccount*> Map; for (auto a : *m->App->GetAccounts()) { LVariant v = a->Identity.Email(); if (v.Str()) { char *Email = v.Str(); if (Email) Map.Add(Email, a); } } LDataIt ToLst = m->GetTo(); LString::Array ToEmail; if (ToLst) { for (LDataPropI *t = ToLst->First(); t; t = ToLst->Next()) { auto Email = t->GetStr(FIELD_EMAIL); if (Email) { if (Map.Find(Email)) ToEmail.New() = Email; } } } if (ToEmail.Length() == 0) { d->SetError(LLoadString(IDS_GNUPG_ERR_NO_ID)); DecryptStatus(1); } d->GetPassword(d->Ui, ToEmail[0], [this, callback, EncryptedObj, Conn, m](auto Pass) { if (!Pass) { d->SetWarning(LLoadString(IDS_GNUPG_DECRYPT_CANCEL)); DecryptStatus(1); } // Send the file to by decrypted... LAutoStreamI Data = EncryptedObj->GetStream(_FL); if (!Data) { d->SetError(LLoadString(IDS_GNUPG_ERR_NO_DATA)); DecryptStatus(1); } if (!Conn->Decrypt(this, Data, Pass, (LMessage::Param) m)) { d->SetError(LLoadString(IDS_GNUPG_ERR_DECRYPT_FAIL)); DecryptStatus(1); } DecryptStatus(0); }); } void MailUiGpg::SignEncrypt(bool uSign, bool uEncrypt, bool uAttachPublicKey, std::function callback) { // Save the message normally Mail *m = d->Ui->GetItem(); bool IsInPublicFolder = m->GetFolder() && m->GetFolder()->IsPublicFolders(); if (IsInPublicFolder) { LDateTime n; n.SetNow(); m->SetDateSent(&n); m->Update(); } d->Ui->OnDataEntered(); d->Ui->OnSave(); LDataI *Root = dynamic_cast(m->GetObject()->GetObj(FIELD_MIME_SEG)); if (!Root) { d->SetError(LLoadString(IDS_GNUPG_ERR_NO_ROOT)); DecryptStatus(1); } // Check that the send has a private key setup... LString FromEmail = m->GetFromStr(FIELD_EMAIL); if (!FromEmail) { d->SetError(LLoadString(IDS_GNUPG_ERR_NO_SENDER_EMAIL)); DecryptStatus(1); } LString PrivKeyId; if (d->Inf) { for (unsigned i=0; iInf->Length(); i++) { GpgConnector::KeyInfo &ki = (*d->Inf)[i]; if (!_stricmp(ki.Email, FromEmail)) { PrivKeyId = ki.KeyId; break; } } } if (!PrivKeyId) { LString s; s.Printf(LLoadString(IDS_GNUPG_ERR_NO_PRIV_KEY), FromEmail.Get()); d->SetError(s); DecryptStatus(1); } if (uAttachPublicKey) { LString PubKey = GetPublicKey(FromEmail); if (!PubKey) { LString s; s.Printf(LLoadString(IDS_GNUPG_ERR_NO_PUB_KEY), FromEmail.Get()); d->SetError(s); DecryptStatus(1); } Attachment *a = new Attachment(m->App); if (a) { LAutoStreamI Data(new LMemStream(PubKey, PubKey.Length())); if (Data) { if (!a->ImportStream("public-key.asc", "application/pgp-keys", Data)) { d->SetError(LLoadString(IDS_GNUPG_ERR_IMPORT_FAIL)); DecryptStatus(1); } else { m->AttachFile(a); } } else { d->SetError("Allocation failed."); DecryptStatus(1); } } } // Re-write the MIME hierarchy to have the message and attachments encrypted // 1) Get the password d->GetPassword(d->Ui, FromEmail.Get(), [this, callback, InputRoot=Root, uSign, uEncrypt, m, PrivKeyId](auto Psw) { LDataI *LocalRoot = InputRoot; if (!Psw) { d->SetStatus(LLoadString(IDS_GNUPG_ERR_SIGN_ENC_CANCEL)); DecryptStatus(1); } // 1) Export the message to a file: const char *BaseName = "encrypted.asc"; LFile::Path p = ScribeTempPath(); p += BaseName; LFile f; if (!f.Open(p, O_READWRITE)) { d->SetError(LLoadString(IDS_GNUPG_ERR_TEMP_WRITE)); DecryptStatus(1); } f.SetSize(0); f.SetPos(0); LMime Mime(ScribeTempPath()); Store3ToLMime(&Mime, LocalRoot); if (!Mime.GetBoundary()) { // No boundary... so set it and propagate the change back char b[64]; CreateMimeBoundary(b, sizeof(b)); Mime.SetBoundary(b); LocalRoot->SetStr(FIELD_INTERNET_HEADER, Mime.GetHeaders()); // If we don't do this then LMime will create it again later // when we actually go to send the message, but it will be // different then and the signing will fail. } if (!Mime.Text.Encode.Push(&f)) { d->SetError(LLoadString(IDS_GNUPG_ERR_EXPORT_TEMP)); DecryptStatus(1); } #if 1 if (uSign) { // Remove any white space from the end of the file... this is // to make sure the signing process is standardized. See // https://www.ietf.org/rfc/rfc3156.txt // Part 5: OpenPGP signed data // This is probably not very efficient but it's usually only the // 2 bytes: "\r\n" int64 Size, Pos; while ( (Size = f.GetSize()) > 0) { Pos = f.SetPos(Size-1); if (Pos != Size - 1) break; char c; ssize_t Rd = f.Read(&c, 1); if (Rd == 1 && strchr(WhiteSpace, c)) { f.SetSize(Size - 1); } else break; } } #endif f.Close(); if (!uEncrypt) { // Just signing... move MIME tree into child node LDataI *NewRoot = LocalRoot->GetStore()->Create(MAGIC_ATTACHMENT); if (!NewRoot) { d->SetError(LLoadString(IDS_GNUPG_ERR_NEW_ATTACH_FAIL)); DecryptStatus(1); } // Copy over the root node headers NewRoot->SetStr(FIELD_INTERNET_HEADER, LocalRoot->GetStr(FIELD_INTERNET_HEADER)); // Reparent the old root to the new root, and then attach that to the message... if (!LocalRoot->Save(NewRoot) || !m->GetObject()->SetObj(FIELD_MIME_SEG, NewRoot)) { d->SetError(LLoadString(IDS_GNUPG_ERR_REPARENT)); DecryptStatus(1); } LocalRoot = NewRoot; } // 2) Encrypt/sign the file: LString InFile(p); p--; p += "encrypted.gpg"; LString OutFile(p); if (LFileExists(OutFile)) { FileDev->Delete(OutFile, false); } LString Args, s; Args.Printf("--batch --passphrase-fd 0 -u 0x%s", PrivKeyId.Get()); if (uEncrypt) { LDataIt To = m->GetTo(); for (LDataPropI *Recip = To->First(); Recip; Recip = To->Next()) { auto Email = Recip->GetStr(FIELD_EMAIL); LAssert(Email != NULL); if (Email) { s.Printf(" --recipient %s", Email); Args += s; } else { d->SetError(LLoadString(IDS_GNUPG_ERR_RECIP_NO_EMAIL)); DecryptStatus(1); } } } s.Printf(" --armor -o \"%s\" %s \"%s\"", OutFile.Get(), uSign && uEncrypt ? "-se" : (uSign ? "--detach-sign" : "-e"), InFile.Get()); Args += s; LSubProcess Proc(GpgBinPath, Args); char Buf[256]; if (!Proc.Start(true, true)) { d->SetError(LLoadString(IDS_GNUPG_ERR_CANT_START)); DecryptStatus(1); } LString PswStr; PswStr.Printf("%s\n", Psw.Get()); ssize_t w = Proc.Write(PswStr.Get(), PswStr.Length()); if (w < 0) { d->SetError(LLoadString(IDS_GNUPG_ERR_WRITE)); DecryptStatus(1); } ssize_t r = Proc.Read(Buf, sizeof(Buf)-1); Buf[MAX(r, 0)] = 0; int Result = Proc.Wait(); if (Result) { d->SetError(Buf[0] ? Buf : LLoadString(IDS_GNUPG_ERR_ENCRYPT_FAIL)); DecryptStatus(1); } // 3) Import the encrypted message and replace contents of MIME tree. LArray InData, OutData; if (!ReadFile(OutData, OutFile)) DecryptStatus(1); #ifndef _DEBUG // Clean up temporary files... FileDev->Delete(InFile, false); FileDev->Delete(OutFile, false); #endif if (uEncrypt) { // Clear out all existing attachments... DeleteChildSegments(LocalRoot); } // Setup the root MIME node to have the right type and fields... LAutoStreamI Data; { // By using a LMime object we preserve the existing headers in the MIME // segment while still being able to change the MIME type and charset. LMime Tmp; Tmp.SetHeaders(LocalRoot->GetStr(FIELD_INTERNET_HEADER)); Tmp.SetMimeType(uSign ? sMultipartSigned : sMultipartEncrypted); Tmp.SetCharset("utf-8"); Tmp.SetSub( "Content-Type", "protocol", uEncrypt ? "application/pgp-encrypted" : "application/pgp-signature"); LocalRoot->SetStr(FIELD_INTERNET_HEADER, Tmp.GetHeaders()); // Set a body message const char *BodyMsg = "This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156)\n"; Data.Reset(new LMemStream(BodyMsg, strlen(BodyMsg))); LocalRoot->SetStream(Data); LocalRoot->Save(); } if (uEncrypt) { // Attach some app info... LDataI *AppInfo = LocalRoot->GetStore()->Create(MAGIC_ATTACHMENT); if (!AppInfo) { d->SetError(LLoadString(IDS_GNUPG_ERR_NEW_ATTACH_FAIL)); DecryptStatus(1); } AppInfo->SetStr(FIELD_MIME_TYPE, "application/pgp-encrypted"); const char *AppInfoMsg = "Version: 1\n"; Data.Reset(new LMemStream(AppInfoMsg, strlen(AppInfoMsg))); AppInfo->SetStream(Data); AppInfo->Save(LocalRoot); } { // Attach the new data to the email... LDataI *File = LocalRoot->GetStore()->Create(MAGIC_ATTACHMENT); if (!File) { d->SetError(LLoadString(IDS_GNUPG_ERR_NEW_ATTACH_FAIL)); DecryptStatus(1); } if (uEncrypt) { // Attach the encrypted data here... LMime Tmp; Tmp.SetMimeType(sAppOctetStream); Tmp.SetFileName(BaseName); Tmp.Set("Content-Disposition", "inline"); Tmp.SetSub("Content-Disposition", "filename", BaseName); File->SetStr(FIELD_INTERNET_HEADER, Tmp.GetHeaders()); } else // uSign { // Set up the signature attachment LMime Tmp; Tmp.SetMimeType("application/pgp-signature"); Tmp.SetFileName(BaseName); Tmp.Set("Content-Description", "OpenPGP digital signature"); Tmp.Set("Content-Disposition", "attachment"); Tmp.SetSub("Content-Disposition", "filename", BaseName); File->SetStr(FIELD_INTERNET_HEADER, Tmp.GetHeaders()); } Data.Reset(new LMemStream(&OutData[0], OutData.Length())); File->SetStream(Data); File->Save(LocalRoot); } // Tell the UI that the object has changed... LArray ChangeArr; ChangeArr.Add(m->GetObject()); d->App->SetContext(_FL); d->App->OnChange(ChangeArr, 0); DecryptStatus(0); }); } -void MailUiGpg::DoCommand(int Cmd, std::function callback) +void MailUiGpg::DoCommand( + int Cmd, + /// This callback will do the normal command processing... + /// In the case where we encrypt / sign we replace the normal + /// processing and don't do it at all... thus NOT calling the + /// callback. + std::function callback) { switch (Cmd) { case IDM_SEND_MSG: { if (!d || !d->Enc || !d->Sign || !d->Attach || !d->Ui) { // Resending an old mail. // There is no Enc/Sign UI. DecryptStatus(0); } if (!d->Enc->Value() && !d->Sign->Value()) { - DecryptStatus(0); // No need to sign &| encrypt + DecryptStatus(0); // No need to sign &| encrypt, but do the normal processing } - Mail *m = d->Ui->GetItem(); + auto m = d->Ui->GetItem(); if (!m) { d->SetError(LLoadString(IDS_GNUPG_ERR_NOMSG)); - DecryptStatus(1); + DecryptStatus(1); // Don't do normal processing of the cmd } SignEncrypt(d->Sign->Value() != 0, d->Enc->Value() != 0, d->Attach->Value() != 0, - [this, m, callback](auto status) - { - if (!status) - { - // Send the email.. - m->Send(true); + [this, m](auto status) + { + if (!status) + { + // Send the email.. + m->Send(true); - // Close the window... - d->Ui->Quit(); - } - - // Bypass the normal code - DecryptStatus(1); - }); + // Close the window... but after we clean up. + d->Ui->PostEvent(M_CLOSE); + } + }); + + // Don't call the callback as we're not doing the normal processing of this command. + return; } } - DecryptStatus(0); + DecryptStatus(0); // Do the default processing } LMessage::Result MailUiGpg::OnEvent(LMessage *Msg) { switch (Msg->Msg()) { case M_GNUPG_KEY_INFO: { d->Inf.Reset( (KeyArr*) Msg->B() ); AddressList *AddrLst = d->GetAddrLst(); if (d->Inf && AddrLst) { int NoKey = 0; List a; if (AddrLst->GetAll(a)) { LHashTbl, GpgConnector::KeyInfo*> Map; for (unsigned i=0; iInf->Length(); i++) { GpgConnector::KeyInfo *ki = &(*d->Inf)[i]; Map.Add(ki->Email, ki); } for (auto i: a) { // Check if this recipient has a key... GpgConnector::KeyInfo *ki = (i->sAddr) ? Map.Find(i->sAddr) : NULL; i->SetInt(FIELD_COLOUR, ki ? cDefaultListItemColour : cError.c32()); i->Update(); if (!ki) NoKey++; } } if (NoKey > 0) d->SetError(LLoadString(IDS_GNUPG_ERR_ONE_OR_MORE)); else if (d->Enc && d->Sign) { if (d->Enc->Value() && d->Sign->Value()) d->SetSuccess(LLoadString(IDS_GNUPG_ENCRYPTED_AND_SIGNED)); else if (d->Enc->Value()) d->SetSuccess(LLoadString(IDS_GNUPG_ENCRYPTED)); else if (d->Sign->Value()) d->SetSuccess(LLoadString(IDS_GNUPG_SIGNED)); else LAssert(0); } else LAssert(0); } else d->SetError("Parameter error."); break; } case M_GNUPG_SIG_CHECK: { Mail *m = d->Ui ? d->Ui->GetItem() : NULL; LAutoPtr Resp((GpgSigCheckResponse*)Msg->A()); if (!Resp || m != (Mail*)Resp->UserValue) { d->SetError("M_GNUPG_SIG_CHECK: bad response"); break; } if (Resp->Error) { d->SetError(Resp->Error); break; } LString Dt = Resp->TimeStamp.Get(); const char *Type = Resp->SignatureMatch ? LLoadString(IDS_GNUPG_GOOD_SIG) : LLoadString(IDS_GNUPG_BAD_SIG); LString Msg; if (Resp->Identity) Msg.Printf(LLoadString(IDS_GNUPG_SIG_MSG), Type, Resp->Identity.Get(), Dt.Get()); else Msg.Printf(LLoadString(IDS_GNUPG_SIG_NO_ID), Type, Dt.Get()); if (Resp->SignatureMatch) d->SetSuccess(Msg); else d->SetError(Msg); break; } case M_GNUPG_DECRYPT: { LAutoPtr Resp((GpgDecryptResponse*)Msg->A()); if (!Resp) { d->SetError(LLoadString(IDS_GNUPG_ERR_INVALID_DECRYPTION)); break; } if (!Resp->Data) { d->SetError(LLoadString(IDS_GNUPG_ERR_NO_OUTPUT)); break; } if (Resp->Error) { d->SetError(Resp->Error); break; } Mail *m = d->Ui->GetItem(); if (!m || m != (Mail*)Resp->UserValue) { d->SetError("Incorrect mail object after decryption."); break; } d->SetSuccess(LLoadString(IDS_GNUPG_DECRYPT_OK)); LDataI *Obj = m->GetObject(); if (!Obj) { d->SetError(LLoadString(IDS_GNUPG_ERR_NOMSG)); break; } // This turns of notification processing, the message is changing // but we don't want it to get dirty. d->Ui->_Running = false; // Unload the attachments, because they will point to stale back-end // objects, that "SetStream" will delete. m->UnloadAttachments(); // Set the stream of the object (which will MIME parse the data, // replacing the MIME Seg tree) Obj->SetStream(Resp->Data); // Re-enable the notifcation processing. d->Ui->_Running = true; // Get the UI to reload and display the object... LArray Items; Items.Add(Obj); m->App->SetContext(_FL); m->App->OnChange(Items, 0); // Change the button to disabled... no need for it anymore. SetCtrlEnabled(IDC_DECRYPT, false); break; } } return LView::OnEvent(Msg); } bool MailUiGpg::Pour(LRegion &r) { LRect lrg = FindLargest(r); if (!lrg.Valid()) return false; int y = LSysFont->GetHeight() + 12; lrg.y2 = lrg.y1 + MIN(y, lrg.Y()) - 1; SetPos(lrg); if (d->Table) { LRect c = GetClient(); c.Inset(PANEL_BORDER_PX, PANEL_BORDER_PX); d->Table->SetPos(c); } return true; } void MailUiGpg::OnCreate() { AttachChildren(); LResources::StyleElement(this); // This is in OnCreate because the CheckSignature needs a valid // view handle to post the message back to us. if (d->Signed) { GpgConnector *Conn = d->App->GetGpgConnector(); if (Conn) { Mail *m = d->Ui->GetItem(); LDataI *obj = m ? m->GetObject() : NULL; LAutoStreamI Msg; if (obj) Msg = obj->GetStream(_FL); if (Msg) { Conn->CheckSignature(this, Msg, (LMessage::Param)m); d->SetWarning(LLoadString(IDS_GNUPG_CHECK_MSG)); } else { d->SetError(LLoadString(IDS_GNUPG_ERR_NOMSG)); } } else { d->NotInstalled(); } } } void MailUiGpg::OnPaint(LSurface *pDC) { LCssTools Tools(this); LRect c = GetClient(); Tools.PaintBorder(pDC, c); Tools.PaintPadding(pDC, c); Tools.PaintContent(pDC, c); } diff --git a/win/Scribe_vs2019.sln b/win/Scribe_vs2019.sln --- a/win/Scribe_vs2019.sln +++ b/win/Scribe_vs2019.sln @@ -1,83 +1,83 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.32413.511 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Scribe", "Scribe_vs2019.vcxproj", "{540DDE64-0927-4E67-B927-2E3BE7ECB029}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lgi", "..\..\..\lgi\trunk\win\Lgi_vs2019.vcxproj", "{95DF9CA4-6D37-4A85-A648-80C2712E0DA1}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mapi", "..\mapi\ScribeMapi_vs2019.vcxproj", "{148574CE-4DA6-4B8A-9EC6-FF68ADC2A046}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScribeMapi", "..\mapi\ScribeMapi_vs2019.vcxproj", "{148574CE-4DA6-4B8A-9EC6-FF68ADC2A046}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LgiStatic", "..\..\..\Lgi\trunk\win\LgiStatic_vs2019.vcxproj", "{DE6D97B9-A194-401B-A8A4-83110C56D572}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Updater", "..\..\..\Lgi\trunk\utils\Updater\Updater_vs2019.vcxproj", "{11E9238B-921E-44E5-A3D2-61C5BFA7CC6C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aspell-dist-0.60", "..\..\libs\aspell-0.60.6.1\win32\dist\aspell-dist-0.60-vs2019.vcxproj", "{1509FE6D-0B3A-422A-99D1-E26A26CE8DA5}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzip2-1.0.6", "..\..\libs\bzip2-1.0.6\windows\bzip2-1.0.6-vs2019.vcxproj", "{E5575141-C1A2-4997-BADB-7584CF546E1F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libntlm", "..\..\..\Lgi\trunk\src\common\Net\libntlm-0.4.2\build-win32\libntlm_vs2019.vcxproj", "{F97AAACA-BF41-46B8-B534-A1639589A1A3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Release|x64 = Release|x64 ReleaseNoOptimize|x64 = ReleaseNoOptimize|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {540DDE64-0927-4E67-B927-2E3BE7ECB029}.Debug|x64.ActiveCfg = Debug|x64 {540DDE64-0927-4E67-B927-2E3BE7ECB029}.Debug|x64.Build.0 = Debug|x64 {540DDE64-0927-4E67-B927-2E3BE7ECB029}.Release|x64.ActiveCfg = Release|x64 {540DDE64-0927-4E67-B927-2E3BE7ECB029}.Release|x64.Build.0 = Release|x64 {540DDE64-0927-4E67-B927-2E3BE7ECB029}.ReleaseNoOptimize|x64.ActiveCfg = ReleaseNoOptimize|x64 {540DDE64-0927-4E67-B927-2E3BE7ECB029}.ReleaseNoOptimize|x64.Build.0 = ReleaseNoOptimize|x64 {95DF9CA4-6D37-4A85-A648-80C2712E0DA1}.Debug|x64.ActiveCfg = Debug|x64 {95DF9CA4-6D37-4A85-A648-80C2712E0DA1}.Debug|x64.Build.0 = Debug|x64 {95DF9CA4-6D37-4A85-A648-80C2712E0DA1}.Release|x64.ActiveCfg = Release|x64 {95DF9CA4-6D37-4A85-A648-80C2712E0DA1}.Release|x64.Build.0 = Release|x64 {95DF9CA4-6D37-4A85-A648-80C2712E0DA1}.ReleaseNoOptimize|x64.ActiveCfg = ReleaseNoOptimize|x64 {95DF9CA4-6D37-4A85-A648-80C2712E0DA1}.ReleaseNoOptimize|x64.Build.0 = ReleaseNoOptimize|x64 {148574CE-4DA6-4B8A-9EC6-FF68ADC2A046}.Debug|x64.ActiveCfg = Debug|x64 {148574CE-4DA6-4B8A-9EC6-FF68ADC2A046}.Debug|x64.Build.0 = Debug|x64 {148574CE-4DA6-4B8A-9EC6-FF68ADC2A046}.Release|x64.ActiveCfg = Release|x64 {148574CE-4DA6-4B8A-9EC6-FF68ADC2A046}.Release|x64.Build.0 = Release|x64 {148574CE-4DA6-4B8A-9EC6-FF68ADC2A046}.ReleaseNoOptimize|x64.ActiveCfg = Release|x64 {148574CE-4DA6-4B8A-9EC6-FF68ADC2A046}.ReleaseNoOptimize|x64.Build.0 = Release|x64 {DE6D97B9-A194-401B-A8A4-83110C56D572}.Debug|x64.ActiveCfg = Debug|x64 {DE6D97B9-A194-401B-A8A4-83110C56D572}.Debug|x64.Build.0 = Debug|x64 {DE6D97B9-A194-401B-A8A4-83110C56D572}.Release|x64.ActiveCfg = Release|x64 {DE6D97B9-A194-401B-A8A4-83110C56D572}.Release|x64.Build.0 = Release|x64 {DE6D97B9-A194-401B-A8A4-83110C56D572}.ReleaseNoOptimize|x64.ActiveCfg = Release|x64 {DE6D97B9-A194-401B-A8A4-83110C56D572}.ReleaseNoOptimize|x64.Build.0 = Release|x64 {11E9238B-921E-44E5-A3D2-61C5BFA7CC6C}.Debug|x64.ActiveCfg = Debug|x64 {11E9238B-921E-44E5-A3D2-61C5BFA7CC6C}.Debug|x64.Build.0 = Debug|x64 {11E9238B-921E-44E5-A3D2-61C5BFA7CC6C}.Release|x64.ActiveCfg = Release|x64 {11E9238B-921E-44E5-A3D2-61C5BFA7CC6C}.Release|x64.Build.0 = Release|x64 {11E9238B-921E-44E5-A3D2-61C5BFA7CC6C}.ReleaseNoOptimize|x64.ActiveCfg = Release|x64 {11E9238B-921E-44E5-A3D2-61C5BFA7CC6C}.ReleaseNoOptimize|x64.Build.0 = Release|x64 {1509FE6D-0B3A-422A-99D1-E26A26CE8DA5}.Debug|x64.ActiveCfg = Debug|x64 {1509FE6D-0B3A-422A-99D1-E26A26CE8DA5}.Debug|x64.Build.0 = Debug|x64 {1509FE6D-0B3A-422A-99D1-E26A26CE8DA5}.Release|x64.ActiveCfg = Release|x64 {1509FE6D-0B3A-422A-99D1-E26A26CE8DA5}.Release|x64.Build.0 = Release|x64 {1509FE6D-0B3A-422A-99D1-E26A26CE8DA5}.ReleaseNoOptimize|x64.ActiveCfg = Release|x64 {1509FE6D-0B3A-422A-99D1-E26A26CE8DA5}.ReleaseNoOptimize|x64.Build.0 = Release|x64 {E5575141-C1A2-4997-BADB-7584CF546E1F}.Debug|x64.ActiveCfg = Debug|x64 {E5575141-C1A2-4997-BADB-7584CF546E1F}.Debug|x64.Build.0 = Debug|x64 {E5575141-C1A2-4997-BADB-7584CF546E1F}.Release|x64.ActiveCfg = Release|x64 {E5575141-C1A2-4997-BADB-7584CF546E1F}.Release|x64.Build.0 = Release|x64 {E5575141-C1A2-4997-BADB-7584CF546E1F}.ReleaseNoOptimize|x64.ActiveCfg = Release|x64 {E5575141-C1A2-4997-BADB-7584CF546E1F}.ReleaseNoOptimize|x64.Build.0 = Release|x64 {F97AAACA-BF41-46B8-B534-A1639589A1A3}.Debug|x64.ActiveCfg = Debug|x64 {F97AAACA-BF41-46B8-B534-A1639589A1A3}.Debug|x64.Build.0 = Debug|x64 {F97AAACA-BF41-46B8-B534-A1639589A1A3}.Release|x64.ActiveCfg = Release|x64 {F97AAACA-BF41-46B8-B534-A1639589A1A3}.Release|x64.Build.0 = Release|x64 {F97AAACA-BF41-46B8-B534-A1639589A1A3}.ReleaseNoOptimize|x64.ActiveCfg = ReleaseNoOptimize|x64 {F97AAACA-BF41-46B8-B534-A1639589A1A3}.ReleaseNoOptimize|x64.Build.0 = ReleaseNoOptimize|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {269D6B2E-2EA7-4141-8BC5-FA6B1F7DED92} EndGlobalSection EndGlobal