home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1998 February / PCOnline_02_1998.iso / filesbbs / win3x / pgpjn.exe / JNSOURCE.ZIP / PGPJNENC.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-11  |  24.1 KB  |  900 lines

  1. //    PGPJNENC.CPP
  2. //    Runtime Loadable Encryptor Extension for Pegasus Mail for Windows.
  3. //    Copyright (c) 1995, David Harris, All Rights Reserved.
  4. //
  5. //    Pretty Good Privacy modifications by John Navas
  6. //    Copyright (c) 1995, John Navas, All Rights Reserved.
  7. //
  8. //    Encryptor module: this module implements the actual Encryptor
  9. //    Interface Routines called by WinPMail at runtime. For more
  10. //    information on the actual form and function of each call, consult
  11. //    the file CRYPTIF.TXT in the FORMS subdirectory of your WINPMAIL
  12. //    installation directory.
  13. //
  14. //    The author grants explicit permission for this source code to be
  15. //    used or modified as required, subject only to the conditions that
  16. //    the copyright notices above are preserved; that this source code
  17. //    not be used in any product distributed in competition with this
  18. //  product; that by using this code you agree that the code is
  19. //    provided without warranty of any kind, either explicit or implied,
  20. //    and you use it at your own risk.
  21. //
  22. //    This module implements an interface to Pretty Good Privacy (tm)
  23. //    and (c) Copyright 1990-1994 Philip Zimmermann. All rights reserved.
  24. //
  25. //    The Massachusetts Institute of Technology is the distributor of PGP
  26. //    version 2.6, for distribution in the USA only.  It is available from
  27. //    "net-dist.mit.edu," a controlled FTP site that has restrictions and
  28. //    limitations, similar to those used by RSA Data Security, Inc., to comply
  29. //    with export control requirements.  The software resides in the directory
  30. //    /pub/PGP.
  31.  
  32. #include "pgpjn.h"
  33. #include "winexejn.h"
  34. #include "resource.h"
  35.  
  36. ///////////////////////////////////////////////////////////////////////////////
  37. // PGP window state
  38.  
  39. #ifdef _DEBUG
  40. const int PGPwindow = SW_SHOWNORMAL;
  41. #else
  42. const int PGPwindow = SW_SHOWMINNOACTIVE;
  43. #endif // _DEBUG
  44.  
  45. ///////////////////////////////////////////////////////////////////////////////
  46. // FRAME A TEXT STRING IF IT HAS EMBEDDED BLANKS
  47.  
  48. // frame temporary object (for function call argument)
  49. #define FRAMEIT(s) FrameIt(MyBuffer(((char*)(s))?lstrlen(s)+1+2:0,(s)))
  50.  
  51. char*
  52. FrameIt(char* string)
  53. {
  54.     if (string)
  55.         if (strchr(string, ' ')) {
  56.             int len = lstrlen(string);
  57.             
  58.             memmove(string + 1, string, len + 1);
  59.             string[0] = '"';
  60.             lstrcat(string, "\"");
  61.         }
  62.     return string;
  63. }
  64.  
  65. ///////////////////////////////////////////////////////////////////////////////
  66. // REMOVE CONTROL CHARACTERS
  67. // Embedded CR-LF are kept
  68.  
  69. static
  70. char*
  71. RemoveCtrl(char* string)
  72. {
  73.     int len = lstrlen(string);
  74.     
  75.     for (int n = len; --n >= 0;)        // examine each character decending
  76.         if (__isascii(string[n]) && iscntrl(string[n])) {    // just control characters
  77.             if (n > 0 && '\r' == string[n-1] && '\n' == string[n] && '\0' != string[n+1]) {
  78.                 --n;                    // skip over embedded CR-LF
  79.                 continue;
  80.             }
  81.             memmove(string + n, string + n + 1, (len--) - n);    // wipe out control character
  82.         }
  83.     return string;
  84. }
  85.  
  86. ///////////////////////////////////////////////////////////////////////////////
  87. // SCAN FOR TEXT LINE IN FILE
  88.  
  89. static
  90. BOOL                                    // FALSE if found; TRUE if not found
  91. ScanFile(
  92. MyFile2& fil,                            // input file to scan
  93. const char* string,                        // string to scan for
  94. BOOL after = TRUE                        // FALSE leaves pos before; TRUE leaves pos after
  95. )
  96. {
  97.     int len = lstrlen(string);            // length of string
  98.     
  99.     for (;;) {
  100.         char buf[80];                    // input buffer
  101.                 
  102.         fil.Gets(buf, sizeof(buf));    // read a line
  103.         if (fil.Eof() || fil.Error())
  104.             return TRUE;
  105.         if (! strncmp(buf, string, len)) {
  106.             if (! after)
  107.                 fil.Seek(- (long) strlen(buf), SEEK_CUR);    // back up over line
  108.             break;
  109.         }
  110.         Yield();
  111.     }
  112.     return FALSE;
  113. }
  114.  
  115. ///////////////////////////////////////////////////////////////////////////////
  116. // DECODE PGP SIGNATURE MESSAGE
  117.  
  118. typedef enum { NONE = -1, BAD = 0, GOOD = 1, NOKEY = 2 } SigType;
  119.  
  120. SigType
  121. SigStatus(
  122. const char* name,                        // name of file to process
  123. char* text = NULL                        // save PGP sig status here
  124. )
  125. {
  126.     SigType ret;
  127.     
  128.     int glen = lstrlen(SigGood);
  129.     int blen = lstrlen(SigBad);
  130.     int klen = lstrlen(SigNoKey);
  131.     
  132.     char buf[80 + 2 + 1];                // input line buffer
  133.     MyFile2 tmp(name, "r", 8 * BUFSIZ);    // auto close
  134.  
  135.     // find PGP message in stderr output
  136.     for (;;) {
  137.         tmp.Gets(buf, sizeof(buf));
  138.         if (tmp.Error() || tmp.Eof()) {
  139.             buf[0] = '\0';                        // null default
  140.             ret = NONE;                            // no signature
  141.             break;
  142.         }
  143.         // see if PGP found a good signature
  144.         if (! strncmp(buf, SigGood, glen)) {
  145.             MessageBeep(MB_OK);                    // catch users attention (WinPMail doesn't)
  146.             ret = GOOD;                            // good signature
  147.             break;
  148.         }
  149.         // see if PGP found a bad signature
  150.         if (! strncmp(buf, SigBad, blen)) {
  151.             MessageBeep(MB_ICONEXCLAMATION);    // catch users attention (WinPMail doesn't)
  152.             ret = BAD;                            // bad signature
  153.             break;
  154.         }
  155.         // see if PGP couldn't find the key for a signature
  156.         if (! strncmp(buf, SigNoKey, klen)) {
  157.             MessageBeep(MB_ICONEXCLAMATION);    // catch users attention (WinPMail doesn't)
  158.             ret = NOKEY;                        // no key found
  159.             break;
  160.         }
  161.     }                
  162.     // process PGP text for WinPMail
  163.     if (text) {
  164.         buf[80] = '\0';
  165.         RemoveCtrl(buf);
  166.         lstrcpy(text, buf);
  167.     }
  168.     return ret;
  169. }
  170.  
  171. ///////////////////////////////////////////////////////////////////////////////
  172. // CENTER A DIALOG BOX
  173.  
  174. void
  175. CenterDialog(HWND hwndDlg)
  176. {
  177.     RECT rc;
  178.  
  179.     // center dialog box on display            
  180.     GetWindowRect(hwndDlg, &rc);
  181.     SetWindowPos(hwndDlg, NULL,
  182.         ((GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2),
  183.         ((GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2),
  184.         0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
  185. }
  186.  
  187. ///////////////////////////////////////////////////////////////////////////////
  188. // LOAD STDERR OUTPUT INTO DIALOG CONTROL
  189.  
  190. static
  191. BOOL                                    // FALSE for success; TRUE for failure
  192. LoadStderrOut(
  193. HWND hwndItm,                            // dialog box control
  194. const char* stderrout                    // stderr output capture file
  195. )
  196. {
  197.     MyFile1 fil(stderrout, OF_READ);    // automatically closed
  198.     if (HFILE_ERROR == fil)
  199.         return TRUE;                    // return failure
  200.     LONG len = fil.GetLength();            // length of file
  201.     MyBuffer buf((size_t) (len + 1));    // alloc buffer for entire file (auto free)
  202.     if (! (char*) buf)
  203.         return TRUE;                    // return failure
  204.     len = _lread(fil, buf, (UINT) len);    // read entire file
  205.     buf[len] = '\0';                    // turn file into string
  206.     RemoveCtrl(buf);                    // remove control characters
  207.     // setup stderr output in dialog edit control
  208.     SetWindowText(hwndItm, buf);        // load text
  209.     PostMessage(hwndItm, EM_SETSEL, 0, MAKELONG(0, -1));    // scroll to end of text
  210.     return FALSE;                        // return success
  211. }
  212.  
  213. ///////////////////////////////////////////////////////////////////////////////
  214. // DISPLAY PGP STDERR OUTPUT
  215.  
  216. static const char* DialogTag;            // error summary tag
  217. static const char* DialogFileErr;        // file with stderr output
  218.  
  219. BOOL
  220. CALLBACK _export
  221. DialogProcErr(
  222. HWND hwndDlg,    /* handle of dialog box    */
  223. UINT msg,        /* message    */
  224. WPARAM wParam,    /* first message parameter    */
  225. LPARAM lParam    /* second message parameter    */
  226. )
  227. {
  228.     switch (msg) {
  229.     case WM_INITDIALOG:
  230.         // center dialog box
  231.         CenterDialog(hwndDlg);
  232.         // error summary tag (using system font)
  233.         SendDlgItemMessage(hwndDlg, IDC_STDERRTAG, WM_SETFONT, NULL, 0L);
  234.         SetDlgItemText(hwndDlg, IDC_STDERRTAG, DialogTag);
  235.         // process stderr output (file -> buffer -> dialog)
  236.         LoadStderrOut(GetDlgItem(hwndDlg, IDC_STDERROUT), DialogFileErr);
  237.         // catch users attention
  238.         MessageBeep(MB_ICONEXCLAMATION);
  239.         break;
  240.  
  241.     case WM_COMMAND :
  242.         switch (wParam) {
  243.         case IDOK:
  244.         case IDCANCEL:
  245.             EndDialog(hwndDlg, 0);
  246.             return TRUE;
  247.         }
  248.         break;
  249.     }
  250.     
  251.     return FALSE;                        // did not process
  252. }
  253.  
  254. static
  255. void
  256. StderrDialog(
  257. const char* tag,                        // description of error
  258. const char* stderrout,                    // stderr output capture file
  259. HWND hwndOwner = hwndParent                // handle of parent window
  260. )
  261. {
  262.     // save data for dialog box
  263.     DialogTag = tag;
  264.     DialogFileErr = stderrout;
  265.     
  266.     // modal dialog box
  267.     DialogBox(hLibInstance,
  268.         MAKEINTRESOURCE(IDD_STDERRDLG),
  269.         hwndOwner,
  270.         (DLGPROC) DialogProcErr);
  271. }
  272.  
  273. ///////////////////////////////////////////////////////////////////////////////
  274. // RUN DOS PGP EXECUTABLE
  275.  
  276. int                                        // return code
  277. static
  278. RunPGP(
  279. UINT fiCmdShow,                            // window state
  280. char* options,
  281. char* sourcefile,
  282. char* destfile,
  283. char* recipient,
  284. char* key,
  285. char* stderr                            // optional redirection for stderr
  286. )
  287. {
  288.     MyTempFile temppath;
  289.     char tempfile[_MAX_FNAME+_MAX_EXT];
  290.     int ret;
  291.  
  292.     // prepare temporary file
  293.     {
  294.         char fname[_MAX_FNAME];
  295.         char ext[_MAX_EXT];
  296.         MyFile2 tmp(temppath, "w");
  297.         if (! tmp.Error())
  298.             tmp.Printf("%s\n%s\n%s\n%s\n%s\n%s\n",
  299.                 PGPpath, options, sourcefile, destfile, recipient, stderr);
  300.         if (tmp.Error()) {
  301.             MessageBox(
  302.                 hwndParent,                        /* handle of parent window    */
  303.                 "Unable to create temporary file!",    /* address of text in message box    */
  304.                 "PGP Interface",                /* address of title of message box    */
  305.                 MB_ICONSTOP | MB_OK);            /* style of message box    */
  306.             return SOME_ERROR;
  307.         }
  308.         _splitpath(temppath, NULL, NULL, fname, ext);
  309.         _makepath(tempfile, NULL, NULL, fname, ext);
  310.     }
  311.  
  312.     // run PGP
  313.     {
  314.         char buf[256];
  315.  
  316.         // build arguments        
  317.         lstrcpy(buf, tempfile);
  318.         if (*key) {
  319.             if (strchr(key, '"'))
  320.                 MessageBox(
  321.                     hwndParent,                        /* handle of parent window    */
  322.                     "Pass phrase may not contain a doublequote (\") character!",    /* address of text in message box    */
  323.                     "PGP Interface",                /* address of title of message box    */
  324.                     MB_ICONEXCLAMATION | MB_OK);    /* style of message box    */
  325.             lstrcat(buf, " \"");
  326.             lstrcat(buf, key);
  327.             lstrcat(buf, "\"");
  328.         }
  329.         if (strlen(buf) >= 127)
  330.             MessageBox(
  331.                 hwndParent,                        /* handle of parent window    */
  332.                 "Your pass phrase is too long!",    /* address of text in message box    */
  333.                 "PGP Interface",                /* address of title of message box    */
  334.                 MB_ICONEXCLAMATION | MB_OK);    /* style of message box    */
  335.         ret = WinExeJN(PGPJNDOS, buf, MyDir, fiCmdShow);
  336.     }
  337.  
  338.     if (ret != RAN_OK) {
  339. #ifdef _DEBUG
  340.         MyDebugOutput("PGP did NOT run OK!\n");
  341. #endif // _DEBUG
  342.         return ret;
  343.     }
  344.     if (_access(temppath, 00)) {
  345. #ifdef _DEBUG
  346.         MyDebugOutput("PGP returned 0\n");
  347. #endif // _DEBUG
  348.         return RAN_OK;
  349.     }
  350.     {
  351.         MyFile1 tmp(temppath, OF_READ);
  352.  
  353.         if (tmp != HFILE_ERROR) {
  354.             char buf[8];
  355.             UINT len = _lread(tmp, buf, sizeof(buf) - 1);
  356.  
  357.             buf[len] = '\0';
  358.             ret = atoi(buf);
  359.         }
  360.     }
  361.  
  362. #ifdef _DEBUG
  363.     MyDebugOutput("PGP returned %d\n", ret);
  364. #endif // _DEBUG
  365.     return ret;
  366. }
  367.  
  368. ///////////////////////////////////////////////////////////////////////////////
  369. // ENCRYPT_FILE
  370.  
  371. //  Returns:  1 if the file was successfully encrypted.
  372. //            2 if the file was successfully encrypted but
  373. //              may contain 8-bit data and should be sent
  374. //              encoded using BASE64.
  375. //            0 on failure.
  376. extern "C"
  377. int
  378. FAR PASCAL _export
  379. ENCRYPT_FILE(
  380. char *sourcefile,
  381. char *destfile,
  382. char *recipient,                        // normal putlic key selection
  383. char *key,                                // may be used to override recipient
  384. int textfile
  385. )
  386. {
  387.     int ret;
  388.  
  389. #ifdef _DEBUG
  390.     MyDebugOutput("ENCRYPT_FILE called (r='%s' k='%s')\n", recipient, key);
  391. #endif // _DEBUG
  392.  
  393.     // make temp file for stderr output
  394.     MyTempFile stderrout;
  395.         
  396.     // run PGP
  397.     {
  398.         char rk[256];            // key buffer
  399.  
  400.         // choose which to use as key
  401.         lstrcpyn(rk, (key != NULL && *key != '\0') ? key : recipient, 128);
  402.         // ensure termination
  403.         rk[128] = '\0';
  404.         // frame it if necessary
  405.         FrameIt(rk);
  406.         // master key logic
  407.         if (*PGPJNKey) {
  408.             lstrcat(rk, " ");
  409.             lstrcat(rk, PGPJNKey);
  410.         }
  411.         
  412.         // run PGP
  413.         ret = RunPGP(PGPwindow, "+bat -fea", sourcefile, destfile,
  414.             rk, "", stderrout);
  415.     }
  416.  
  417.     // return OK result
  418.     if (RAN_OK == ret && ! _access(destfile, 00)) {
  419. #ifdef _DEBUG
  420.         MyDebugOutput("ENCRYPT_FILE returns 1\n");
  421. #endif // _DEBUG
  422.         return 1;
  423.     }
  424.  
  425.     // failure
  426.     StderrDialog("Encryption failed!  (Empty file will be sent.)", stderrout);
  427.     remove(destfile);
  428. #ifdef _DEBUG
  429.     MyDebugOutput("ENCRYPT_FILE returns 0\n");
  430. #endif // _DEBUG
  431.     return 0;
  432. }
  433.  
  434. ///////////////////////////////////////////////////////////////////////////////
  435. // SIGN_FILE
  436.  
  437. //  Returns:  1 if the message was successfully processed
  438. //            2 if the file was successfully processed but
  439. //              may contain 8-bit data and should be sent
  440. //              encoded using BASE64.
  441. //            0 if an error occurred during processing
  442. //           -1 if the operation is not supported
  443. extern "C"
  444. int
  445. FAR PASCAL _export
  446. SIGN_FILE(
  447. char *sourcefile,
  448. char *destfile,
  449. char *recipient,                        // used for optional encryption
  450. char *key,                                // reserved for pass phrase
  451. int encrypt_as_well
  452. )
  453. {
  454.     int ret;
  455.  
  456. #ifdef _DEBUG
  457.     MyDebugOutput("SIGN_FILE called (r='%s' k='%s')\n", recipient, key);
  458. #endif // _DEBUG
  459.  
  460.     // make temp file for stderr output
  461.     MyTempFile stderrout;
  462.         
  463.     {
  464.         char rk[256];                    // key buffer
  465.  
  466.         // frame recipient if necessary
  467.         lstrcpyn(rk, recipient, 128);
  468.         rk[128] = '\0';                    // ensure termination
  469.         FrameIt(rk);                    // frame it if necessary
  470.  
  471.         // add master key if necessary
  472.         if (*PGPJNKey) {
  473.             lstrcat(rk, " ");
  474.             lstrcat(rk, PGPJNKey);
  475.         }
  476.         
  477.         // run PGP
  478.         ret = RunPGP(PGPwindow,
  479.             (! encrypt_as_well) ? "+bat -fsta" : "+bat -feas",
  480.             sourcefile, destfile, rk, key, stderrout);
  481.     }
  482.  
  483.     // check result
  484.     if (RAN_OK == ret && ! _access(destfile, 00)) {
  485.         // success
  486.         ret = 1;
  487.     }
  488.     else {
  489.         // failure
  490.         StderrDialog("Sign File failed!", stderrout);
  491.         remove(destfile);
  492.         ret = 0;
  493.     }
  494.  
  495. #ifdef _DEBUG
  496.     MyDebugOutput("SIGN_FILE returns %d\n", ret);
  497. #endif // _DEBUG
  498.  
  499.     return ret;
  500. }
  501.  
  502. ///////////////////////////////////////////////////////////////////////////////
  503. // DECRYPT_FILE
  504.  
  505. //  Returns:  1 if the file was successfully decrypted
  506. //            2 if the file was decrypted but is non-textual
  507. //            0 on password or system failure
  508. extern "C"
  509. int
  510. FAR PASCAL _export
  511. DECRYPT_FILE(
  512. char *sourcefile,
  513. char *destfile,
  514. char *key
  515. )
  516. {
  517.     int ret = 0;
  518.  
  519. #ifdef _DEBUG
  520.     MyDebugOutput("DECRYPT_FILE called (k='%s')\n", key);
  521. #endif // _DEBUG
  522.  
  523.     do {    // makes it easy to break out
  524.         int rtc;
  525.         char buf[256];                    // i/o buffer
  526.         long pos, len, cop, pos1;        // file positions and length
  527.         int startlen = lstrlen(PGPBegin);
  528.         int stoplen = lstrlen(PGPEnd);
  529.         
  530.         {
  531.             // open files for initial copy (binary mode for repositioning)
  532.             MyFile2 fin(sourcefile, "rb", 8 * BUFSIZ);
  533.             MyFile2 fout(destfile, "wb", 8 * BUFSIZ);
  534.             // make sure input and output files got opened
  535.             if (fin.Error() || fout.Error())
  536.                 break;
  537.     
  538.             // get length of input file
  539.             len = fin.GetLength();
  540.     
  541.             // copy input to output up until PGP body
  542.             for (;;) {
  543.                 fin.Gets(buf, sizeof(buf));
  544.                 if (fin.Eof() || fin.Error())
  545.                     break;
  546.                 if (! strncmp(buf, PGPBegin, startlen))
  547.                     break;
  548.                 fout.Puts(buf);
  549.                 Yield();
  550.             }
  551.             if (fin.Error()) {            // error
  552.                 MessageBox(
  553.                     hwndParent,                        /* handle of parent window    */
  554.                     "I/O error on decryption input file!",    /* address of text in message box    */
  555.                     "PGP Interface",                /* address of title of message box    */
  556.                     MB_ICONEXCLAMATION | MB_OK);    /* style of message box    */
  557.                 break;
  558.             }
  559.     
  560.             // save next line in PGP body and output marker
  561.             pos = fin.Tell();
  562.             pos1 = fout.Tell();
  563.         }
  564.  
  565.         // make temp file for stderr output
  566.         MyTempFile stderrout;
  567.         
  568.         // run PGP, which should add decrypted message to output
  569.         rtc = RunPGP(PGPwindow, "+bat -f", sourcefile, destfile, "", key, stderrout);
  570.         // 1: decryption failed
  571.         // 2: cyphertext not found
  572.  
  573.         {        
  574.             // open files for final copy/append (binary mode for repositioning)
  575.             MyFile2 fin(sourcefile, "rb", 8 * BUFSIZ);
  576.             MyFile2 fout(destfile, "r+b", 8 * BUFSIZ);
  577.             // make sure input and output files got opened
  578.             if (fin.Error() || fout.Error())
  579.                 break;
  580.     
  581.             // start in PGP body
  582.             fin.Seek(pos, SEEK_SET);
  583.             // position output
  584.             fout.Seek(0, SEEK_END);
  585.     
  586.             cop = fout.Tell() - pos1;        // amount copied by PGP
  587.             if (rtc != RAN_OK && (0 == cop || len == cop)) {
  588.                 // PGP just dups the file if it can't find valid ciphertext
  589.                 if (len == cop) {
  590.                     MyFile2 ferr(stderrout, "w");
  591.                     if (! ferr.Error())
  592.                         ferr.Printf("PGP could not find valid ciphertext to decrypt.\n"
  593.                             "(The message may have been corrupted.)");
  594.                     fout.Seek(pos1, SEEK_SET);    // remove the PGP dup
  595.                     fout.Trunc(pos1);    // and truncate the file
  596.                 }
  597.                 StderrDialog("Decryption failed!", stderrout);
  598.                 fout.Puts(buf);            // copy start line to output
  599.             }
  600.             else {
  601.                 // tell user about signature
  602.                 switch (SigStatus(stderrout, buf)) {
  603.                 case BAD:
  604.                     StderrDialog("Invalid PGP signature!", stderrout);
  605.                 case GOOD:
  606.                 case NOKEY:
  607.                     fout.Printf("%s\r\n%s\r\n%s\r\n", PGPBeginAdvise, buf, PGPEndAdvise);
  608.                     break;
  609.                 }
  610.  
  611.                 // scan for end of PGP body
  612.                 if (ScanFile(fin, PGPEnd))
  613.                     break;
  614.             }
  615.                         
  616.             // copy/append remainder of input to output
  617.             for (;;) {
  618.                 fin.Gets(buf, sizeof(buf));
  619.                 if (fin.Error() || fin.Eof())
  620.                     break;
  621.                 fout.Puts(buf);
  622.                 Yield();
  623.             }
  624.         }
  625.                 
  626.         ret = 1;
  627.     } while (0);    // never loop
  628.  
  629.     // return to caller
  630. #ifdef _DEBUG
  631.     MyDebugOutput("DECRYPT_FILE returns %d\n", ret);
  632. #endif // _DEBUG
  633.     return ret;
  634. }
  635.  
  636. ///////////////////////////////////////////////////////////////////////////////
  637. // DESTROY_FILE
  638.  
  639. //  Returns:  1 if the file was destroyed
  640. //            0 if the file was not destroyed (in which
  641. //              case WinPMail will delete it as described).
  642. extern "C"
  643. int
  644. FAR PASCAL _export
  645. DESTROY_FILE(char *sourcefile)            // pathname of file to destroy
  646. {
  647.     MyFile2 fil(sourcefile, "r+b", 8 * BUFSIZ);    // open file for binary appending
  648.  
  649. #ifdef _DEBUG
  650.     MyDebugOutput("DESTROY_FILE called (f='%s')\n", sourcefile);
  651. #endif // _DEBUG
  652.  
  653.     if (fil.Error())
  654.         return 0;                        // open failure
  655.     if (fil.Erase())
  656.         return 0;                        // erase failure
  657.     fil.Close();                        // close the file
  658.     remove(sourcefile);                    // delete it from the disk
  659. #ifdef _DEBUG
  660.     MyDebugOutput("DESTROY_FILE normal return\n");
  661. #endif // _DEBUG
  662.     return 1;                            // return success
  663. }
  664.  
  665. ///////////////////////////////////////////////////////////////////////////////
  666. // VERIFY_SIGNATURE
  667.  
  668. //  Returns:  1 if the digital signature was valid
  669. //            0 if the digital signature was invalid
  670. //           -1 if no digital signature could be found
  671. //           -2 if the operation is not supported
  672. extern "C"
  673. int
  674. FAR PASCAL _export
  675. VERIFY_SIGNATURE(
  676. char *sourcefile,
  677. char *text                                // limited to 80 characters
  678. )
  679. {
  680.     int ret;
  681.  
  682. #ifdef _DEBUG
  683.     MyDebugOutput("VERIFY_SIGNATURE called (f='%s')\n", sourcefile);
  684. #endif // _DEBUG
  685.  
  686.     // make temp file for stderr output
  687.     MyTempFile stderrout;
  688.     
  689.     // run PGP (all i want is return code)
  690.     ret = RunPGP(PGPwindow, "+bat -f", sourcefile, "nul", "", "", stderrout);
  691.  
  692.     // check result
  693.     switch (ret) {
  694.     case RAN_OK:
  695.     case 1:                                // 1 is OK too
  696.         switch (SigStatus(stderrout, text)) {
  697.         case NONE:
  698.             ret = -1;
  699.             break;
  700.         case GOOD:
  701.             ret = 1;
  702.             break;
  703.         case BAD:
  704.         case NOKEY:
  705.             ret = 0;
  706.             break;
  707.         }
  708.         break;
  709.     default:
  710.         StderrDialog("Verify Signature failed!", stderrout);
  711.         ret = 0;                                    // signature verify failed
  712.         break;
  713.     }
  714.     
  715. #ifdef _DEBUG
  716.     MyDebugOutput("VERIFY_SIGNATURE returns %d\n", ret);
  717. #endif // _DEBUG
  718.  
  719.     return ret;
  720. }
  721.  
  722. ///////////////////////////////////////////////////////////////////////////////
  723. // KEY_MANAGEMENT
  724.  
  725. static const char* DialogFileKey;        // file with public key
  726.  
  727. BOOL
  728. CALLBACK _export
  729. DialogProcKey(
  730. HWND hwndDlg,    /* handle of dialog box    */
  731. UINT msg,        /* message    */
  732. WPARAM wParam,    /* first message parameter    */
  733. LPARAM lParam    /* second message parameter    */
  734. )
  735. {
  736.     static BOOL AddKey;
  737.     static BOOL ChkKey;
  738.     int ret;                            // return code
  739.     
  740.     switch (msg) {
  741.     case WM_INITDIALOG:
  742.         // center dialog box
  743.         CenterDialog(hwndDlg);
  744.         // init flags
  745.         EnableWindow(GetDlgItem(hwndDlg, IDC_ADDKEY), AddKey = FALSE);
  746.         EnableWindow(GetDlgItem(hwndDlg, IDC_CHKKEY), ChkKey = FALSE);
  747.         // load from file if present
  748.         do {
  749.             long pos1, pos2;
  750.             MyFile2 fil(DialogFileKey ? DialogFileKey : "", "rb", 8 * BUFSIZ);
  751.                                                                            
  752.             if (fil.Error())
  753.                 break;
  754.             // find start of public key block
  755.             ScanFile(fil, PGPBeginKey, FALSE);
  756.             pos1 = fil.Tell();
  757.             // find end of public key block
  758.             ScanFile(fil, PGPEndKey, TRUE);
  759.             pos2 = fil.Tell();
  760.             // if public key found
  761.             if (pos2 > pos1) {
  762.                 int len = (int) (pos2 - pos1);    // length of file segment
  763.                 MyBuffer buf((size_t) (len + 1));    // alloc buffer for entire seg
  764.                                             
  765.                 if ((char*) buf) {    // if buffer allocated
  766.                     fil.Seek(pos1, SEEK_SET);    // position file
  767.                     len = fil.Read(buf, sizeof(char), (unsigned int) len);    // read entire seg
  768.                     buf[len] = '\0';            // turn seg into string
  769.                     RemoveCtrl(buf);            // remove control characters
  770.                     // setup stderr output in dialog edit control
  771.                     SetDlgItemText(hwndDlg, IDC_KEYMGMT, buf);    // load text
  772.                     PostMessage(GetDlgItem(hwndDlg, IDC_KEYMGMT),    // scroll to start of text
  773.                         EM_SETSEL, 0, MAKELONG(0, 0));
  774.                     EnableWindow(GetDlgItem(hwndDlg, IDC_ADDKEY), AddKey = TRUE);
  775.                 }
  776.             }
  777.         } while (0);
  778.         break;
  779.         
  780.     case WM_COMMAND :
  781.         switch (wParam) {
  782.         
  783.         case IDC_KEYMGMT:
  784.             switch (HIWORD(lParam)) {
  785.             case EN_CHANGE:
  786.                 {
  787.                     int len = (int) SendMessage((HWND) LOWORD(lParam), WM_GETTEXTLENGTH, 0, 0L);
  788.                     BOOL chkok = (len != 0);
  789.                                     
  790.                     if (AddKey != chkok)
  791.                         EnableWindow(GetDlgItem(hwndDlg, IDC_ADDKEY), AddKey = chkok);
  792.                     if (len > MAXNAME
  793.                     || SendDlgItemMessage(hwndDlg, IDC_KEYMGMT, EM_GETLINECOUNT, 0, 0) > 1)
  794.                         chkok = FALSE;
  795.                     if (ChkKey != chkok) {
  796.                         EnableWindow(GetDlgItem(hwndDlg, IDC_CHKKEY), ChkKey = chkok);
  797.                     }
  798.                 }
  799.                 return TRUE;
  800.             }
  801.             break;
  802.  
  803.         case IDC_ADDKEY:
  804.             {
  805.                 // make temp file for std output
  806.                 MyTempFile stderrout;
  807.                 // make temp file for key source
  808.                 MyTempFile sourcefile;
  809.                                 
  810.                 // load sourcefile
  811.                 do {
  812.                     // allocate i/o buffer
  813.                     int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_KEYMGMT)) + 1;
  814.                     MyBuffer buf(len);    // auto delete when goes out of scope
  815.                     if (! (char*) buf)
  816.                         break;
  817.                     // get dialog data into buffer
  818.                     GetWindowText(GetDlgItem(hwndDlg, IDC_KEYMGMT), buf, len);
  819.                                     
  820.                     // open output file
  821.                     MyFile1 fil(sourcefile, WRITE);
  822.                     // write data to output file if it got opened
  823.                     if (fil != HFILE_ERROR)
  824.                         _lwrite(fil, buf, len);
  825.                 } while (0);    // never loop
  826.                                 
  827.                 // run PGP
  828.                 ret = RunPGP(PGPwindow, "+bat -ka", "nul", stderrout, sourcefile, "", "nul");
  829.                             
  830.                 // std output capture file
  831.                 StderrDialog("Add Public Key to Key Ring", stderrout, hwndDlg);
  832.                     
  833.                 // restore focus
  834.                 SetFocus(GetDlgItem(hwndDlg, IDC_KEYMGMT));
  835.                     
  836.                 return TRUE;
  837.             }
  838.  
  839.         case IDC_CHKKEY:
  840.             {
  841.                 // allocate recipient buffer
  842.                 int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_KEYMGMT)) + 1;
  843.                 MyBuffer buf(len);    // deleted auto when it goes out of scope
  844.                     
  845.                 // get dialog data into buffer
  846.                 if ((char*) buf)
  847.                     GetWindowText(GetDlgItem(hwndDlg, IDC_KEYMGMT), buf, len);
  848.                                     
  849.                 // make temp file for std output
  850.                 MyTempFile stderrout;
  851.                                     
  852.                 // run PGP
  853.                 ret = RunPGP(PGPwindow, "+bat -kc", "nul", stderrout, FRAMEIT(buf), "", "nul");
  854.                         
  855.                 // std output capture file
  856.                 StderrDialog("Check Key Ring for Public Key", stderrout, hwndDlg);
  857.                         
  858.                 // restore focus
  859.                 SetFocus(GetDlgItem(hwndDlg, IDC_KEYMGMT));
  860.                         
  861.                 return TRUE;
  862.             }
  863.             
  864.         case IDOK:
  865.         case IDCANCEL:
  866.             EndDialog(hwndDlg, 0);
  867.             return TRUE;
  868.         }
  869.         break;
  870.     }
  871.     
  872.     return FALSE;                        // did not process
  873. }
  874.  
  875. // return value is ignored
  876. extern "C"
  877. int
  878. FAR PASCAL _export
  879. KEY_MANAGEMENT(char *sourcefile)
  880. {
  881. #ifdef _DEBUG
  882.     MyDebugOutput("KEY_MANAGEMENT called (f='%s')\n", sourcefile);
  883. #endif // _DEBUG
  884.  
  885.     // save data for dialog box
  886.     DialogFileKey = sourcefile;
  887.  
  888.     // modal dialog box
  889.     DialogBox(hLibInstance,
  890.         MAKEINTRESOURCE(IDD_KEYMGMTDLG),
  891.         hwndParent,
  892.         (DLGPROC) DialogProcKey);
  893.  
  894.     return 0;
  895. }
  896.  
  897. ///////////////////////////////////////////////////////////////////////////////
  898.  
  899. //    PGPJNENC.CPP
  900.