Code cleanups. gpgol-0.10.1
authorWerner Koch <wk@gnupg.org>
Mon, 22 Oct 2007 15:31:09 +0000 (15:31 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 22 Oct 2007 15:31:09 +0000 (15:31 +0000)
Auto start the server.
Prepared a release.

24 files changed:
NEWS
configure.ac
doc/gpgol.texi
po/de.po
po/sv.po
src/ChangeLog
src/common.c
src/common.h
src/decrypt.bmp
src/dialogs.h
src/encrypt.bmp
src/engine-assuan.c
src/engine-assuan.h
src/engine.c
src/engine.h
src/ext-commands.cpp
src/ext-commands.h
src/key_mana.bmp
src/logo.bmp
src/main.c
src/mimemaker.c
src/myexchext.h
src/olflange-dlgs.cpp
src/sign.bmp

diff --git a/NEWS b/NEWS
index 6c670ad..1c9efc6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,20 @@
-Noteworthy changes for version 0.10.1
+Noteworthy changes for version 0.10.1 (2007-10-22)
 ==================================================
 
  UNDER HEAVY DEVELOPMENT - DO NOT USE FOR PRODUCTION!
 
+    - Signed and encrypt has not yet been implemented
+    - Under OL2007 some menu entries are missing.
+
+ * Auto start the server.
+
+ * Code cleanups. 
+
+ * Made all dialogs language neutral.
+
+ * The manual has some notes about the Registry usage and new MAPI
+   properties.
+
 
 Noteworthy changes for version 0.10.0 (2007-10-11)
 ==================================================
index 6c1bed7..f5c1ba3 100644 (file)
@@ -17,7 +17,7 @@ min_automake_version="1.9.4"
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
 m4_define([my_version], [0.10.1])
-m4_define([my_issvn], [yes])
+m4_define([my_issvn], [no])
 
 m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \
             || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')]))
index 8001d9f..cd6ed36 100644 (file)
@@ -9,6 +9,14 @@
 * gpgol: (gpgol).              An Outlook Plugin for GnuPG.
 @end direntry
 
+@macro clnt
+  @sc{c:} @c
+@end macro
+@macro srvr
+  @sc{s:} @c
+@end macro
+
+
 
 @c Unify some of the indices.
 @syncodeindex tp fn
@@ -79,6 +87,8 @@ Outlook MUA.
 @menu
 * Introduction::                How to use this manual.
 * Assuan Protocol::             Description of the UI server protocol.
+* MAPI Properties::             MAPI Properties used by GpgOL.
+* Registry Settings::           How GpgOL uses the Registry.
 
 Appendices
 
@@ -208,6 +218,60 @@ Use the CMS (PKCS#7) protocol (RFC-3852).
 
 @end deffn
 
+To support automagically selection of the protocol depending on the
+selected keys, the server may implement the follwoing extra command:
+
+@deffn Command PREP_ENCRYPT [-@w{}-protocol=@var{name}]
+
+This commands considers all recipients set so far and decides whether it
+is able to take input and start the actual decryption.  This is kind of
+a dry-run @command{ENCRYPT} without requiring or using the input and
+output file descriptors.  The server shall cache the result of any user
+selection to avoid asking this again when the actual @command{ENCRYPT}
+command is send.  The @option{--protocol} option is optional; if it is
+not given, the server should allow the user to select the protocol to be
+used based on the recipients given or by any other means.
+
+If this command is given again before a successful @command{ENCRYPT}
+command, the second one takes effect. 
+
+Before sending the OK response the server shall tell the client the
+protocol to be used (either the one given by the argument or the one
+selected by the user) by means of a status line:
+@end deffn
+
+@deffn {Status line} PROTOCOL @var{name}
+Advise the client to use the protocol @var{name} for the
+@command{ENCRYPT} command.  The valid protocol names are listed under
+the description of the @command{ENCRYPT} command.  The server shall emit
+exactly one PROTOCOL status line.
+@end deffn
+
+@noindent
+Here is an example of a complete encryption sequence; client lines are
+indicated by a @sc{c:}, server responses by @sc{c:}:
+
+@smallexample
+@group
+  @clnt RESET
+  @srvr OK
+  @clnt RECIPIENT foo@@example.net
+  @srvr OK
+  @clnt RECIPIENT bar@@example.com
+  @srvr OK
+  @clnt PREP_ENCRYPT
+  @srvr S PROTOCOL OpenPGP
+  @srvr OK
+  @clnt INPUT FD=17
+  @srvr OK
+  @clnt OUTPUT FD=18
+  @srvr OK
+  @clnt ENCRYPT
+  @srvr OK
+@end group
+@end smallexample
+
+
 
 @node SIGN
 @section Sign a Message
@@ -433,6 +497,146 @@ values (e.g. @code{HWND}).
 @end deffn
 
 
+@noindent
+GpgOL features a button to invoke the certificate manager.  To do this
+it uses the Assuan command:
+
+@deffn Command START_KEYMANAGER
+The server shall pop up the main window of the key manager (aka
+certificate manager).  The client expects that the key manger is brought
+into the foregound and that this command immediatley returns (does not
+wait until the key manager has been fully brought up).
+@end deffn
+
+@c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+@c
+@c  M A P I  P r o p e r t i e s
+@c
+@c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+@node MAPI Properties
+@chapter MAPI Properties used by GpgOL
+
+GpgOL uses a some custom MAPI properties in the named properties range.
+Thus their actual numbers are determined at runtime and only the names
+should be used.  The GUID assigned to these properties is
+@code{31805ab8-3e92-11dc-879c-00061b031004}.
+
+@table @code
+
+@item GpgOL Attach Type
+This is a property of type LONG and used to further describe the
+attachments created by GpgOL.  These values are used:
+
+  @table @asis
+  @item ATTACHTYPE_MOSS = 1
+  The attachment contains the original MOSS message.  That is either an
+  S/MIME or a PGP/MIME message in its original RFC-2822 format (but only
+  with the relevant MIME parts of the main header).
+
+  @item ATTACHTYPE_FROMMOSS = 2
+  The attachment has been created from the original MOSS attachment.  It
+  will automagically be recreated as needed.  If the atatchment has
+  been created from an encrypted message, it is saved re-encrypted under
+  a non-permanent session key.  This session key is valid as long as the
+  current Outlook porcess exists.
+
+  @item ATTACHTYPE_MOSSTEMPL = 3
+  The attachment has been created in the course of sending a message.
+  @end table
+
+@item GpgOL Sig Status
+This is a property of type STRING8 and used to cache the result of the
+last signature verification.  It is used with the actual message and
+consists of a single character, a space and a human readable string
+(utf-8 encoded).  The first character is used as a machine processable
+flag indicating the status.  These values are defined:
+
+  @table @code
+  @item #
+  The message is not of interest to us.  GpgOL may flag any message with
+  this signature status to avoid extra processing for messages already
+  known not to need any processing by GpgOL.
+
+  @item @@
+  The message has been created and signed or encrypted by GpgOL. 
+  @item ?
+  The signature status has not been checked.  This is for example used
+  if the public key to be used for the verification could not be found.
+
+  @item !
+  The signature verified okay and is deemed to be fully valid.
+
+  @item ~
+  The signature was not fully verified.  This often means that the full
+  result information of the signature verification needs to be
+  considered to decide the actual validity.  Used for example if the
+  signing key has expired
+
+  @item -
+  The signature is bad.  Either this means the message has been tampered
+  with or an intermediate message relay has accidently changed
+  the message (e.g. due to recoding).
+  
+  @end table
+
+@item GpgOL Protect IV
+This binary property is used to store the initialization vector of an
+re-encrypted attachment.  The existence of this property indicates that
+the attachment has been encrypted under the non-permanent session key.
+
+@item GpgOL MIME Info
+This property is of type STRING8 and used to store the MIME structure of
+the orginal message.  The content are lines of colon delimited fields.
+The specification has not yet been finished.
+
+@end table
+
+
+@c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+@c
+@c  R e g i s t r y  S  e t t i n g s
+@c
+@c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+@node Registry Settings
+@chapter How GpgOL uses the Registry
+
+This is a list of registry entries GpgOL knows about. 
+
+@table @code
+
+@item HKLM\Software\Gnu\GnuPG:Install Directory
+This is used by GnuPG to describe the directory where GnupG has been
+installed.  GpgOL requires this to get the location of the localedir
+which is used to show translated strings (@file{gpgol.mo}).  It is
+further used to check whether GnuPG has been installed at all.
+
+@item HKCU\Software\Gnu\GnuPG:UI Server
+If the UI server could not be connected, GpgOL tries to start the one
+given in this entry.  It is assumed that the UI server is stored in the
+@code{Install Directory} (as described above).  This Registry entry
+gives the actual command name relative to this directory.  If the key
+does not exist, is is first searched below @code{HKLM} and then it
+defaults to @code{bin/kleopatra.exe} (FIXME: The final name will be just
+@code{kleopatra.exe}).
+
+In case the UI server requires the socket name as an argument, the
+placeholder @code{$s} may be used to indicate this.  Due to this feature
+it is required that all verbatim dollar are too be doubled.  If the
+actual program name contains spaces the program name nees to be enclosed
+in quotes.
+
+
+@end table
+
+
+
+@c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+@c
+@c   A P P E N D I X
+@c 
+@c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+
 @include gpl.texi
 
 @c
index d594fdc..47fab55 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: GpgOL 0.10.0\n"
 "Report-Msgid-Bugs-To: bug-gpgol@g10code.com\n"
-"POT-Creation-Date: 2007-10-12 21:12+0200\n"
-"PO-Revision-Date: 2007-10-12 21:12+0200\n"
+"POT-Creation-Date: 2007-10-22 17:20+0200\n"
+"PO-Revision-Date: 2007-10-22 17:21+0200\n"
 "Last-Translator: Werner Koch <wk@gnupg.org>\n"
 "Language-Team: de\n"
 "MIME-Version: 1.0\n"
@@ -40,7 +40,7 @@ msgstr ""
 "um die gesamte Nachricht nochmal zu entschlüsseln.  Danach können\n"
 "Sie das Attachment wieder öffenen."
 
-#: src/common.c:145
+#: src/common.c:215
 msgid "GpgOL - Save decrypted attachment"
 msgstr "GpgOL - Sichern der entschlüsselten Anlage"
 
@@ -208,102 +208,106 @@ msgstr "*** Anfang Notation (Unterschrift von: "
 msgid "*** End Notation ***\n"
 msgstr "*** Ende Notation ***\n"
 
-#: src/ext-commands.cpp:325
+#: src/ext-commands.cpp:408
 msgid "&Decrypt and verify message"
 msgstr "Entschlüsseln/Prüfen der Nachricht"
 
-#: src/ext-commands.cpp:326
+#: src/ext-commands.cpp:409
 msgid "&Verify signature"
 msgstr "&Unterschrift prüfen"
 
-#: src/ext-commands.cpp:327
+#: src/ext-commands.cpp:410
 msgid "&Display crypto information"
 msgstr "~Krypto Informationen anzeigen"
 
-#: src/ext-commands.cpp:353
+#: src/ext-commands.cpp:417 src/ext-commands.cpp:713
+msgid "Decrypt message and verify signature"
+msgstr "Nachricht entschlüsseln und Unterschrift prüfen"
+
+#: src/ext-commands.cpp:424
 msgid "use S/MIME protocol"
 msgstr "S/MIME verwenden"
 
-#: src/ext-commands.cpp:354
+#: src/ext-commands.cpp:425
 msgid "&encrypt message with GnuPG"
 msgstr "Nachricht mit GnuPG verschlüsseln"
 
-#: src/ext-commands.cpp:355
+#: src/ext-commands.cpp:426
 msgid "&sign message with GnuPG"
 msgstr "Nachricht mit GnuPG unterschreiben"
 
-#: src/ext-commands.cpp:397
+#: src/ext-commands.cpp:430
+msgid "Encrypt message with GnuPG"
+msgstr "Nachricht mit GnuPG verschlüsseln"
+
+#: src/ext-commands.cpp:431
+msgid "Sign message with GnuPG"
+msgstr "Nachricht mit GnuPG unterschreiben"
+
+#: src/ext-commands.cpp:444
 msgid "GnuPG Certificate &Manager"
 msgstr "GnuPG Zertifikats&verwaltung"
 
-#: src/ext-commands.cpp:548
+#: src/ext-commands.cpp:448
+msgid "Open the certificate manager"
+msgstr "Die Zertifikatsverwaltung öffnen"
+
+#: src/ext-commands.cpp:590
 msgid "Could not start certificate manager"
 msgstr "Die Zertifikatsverwaltung konnte nicht aufgerufen werden"
 
-#: src/ext-commands.cpp:595
+#: src/ext-commands.cpp:641
 msgid "Select this option to decrypt and verify the message."
 msgstr ""
 "Wählen Sie diese Option um die Nachricht zu entschlüsseln bzw. zu "
 "verifizieren."
 
-#: src/ext-commands.cpp:602
+#: src/ext-commands.cpp:648
 msgid "Select this option to show information on the crypto status"
 msgstr ""
 "Wählen Sie diese Option um Informationen über den Krypto-Status der "
 "Nachricht anzuzeigen."
 
-#: src/ext-commands.cpp:610 src/ext-commands.cpp:686
+#: src/ext-commands.cpp:656 src/ext-commands.cpp:732
 msgid "Check the signature now and display the result"
 msgstr "Die digitale Unterschrift jetzt prüfen und das Resultat anzeigen"
 
-#: src/ext-commands.cpp:617
+#: src/ext-commands.cpp:663
 msgid "Select this option to select the S/MIME protocol."
 msgstr "Wählen Sie diese Option zum das S/MIME Protokoll auszuwählen."
 
-#: src/ext-commands.cpp:624
+#: src/ext-commands.cpp:670
 msgid "Select this option to encrypt the message."
 msgstr "Wählen Sie diese Option zum Verschlüsseln der Nachricht."
 
-#: src/ext-commands.cpp:631
+#: src/ext-commands.cpp:677
 msgid "Select this option to sign the message."
 msgstr "Wählen Sie diese Option zum Unterschreiben der Nachricht."
 
-#: src/ext-commands.cpp:638
+#: src/ext-commands.cpp:684
 msgid "Select this option to open the certificate manager"
 msgstr "Wählen Sie diese Option zum die Zertifikatsverwaltung zu öffenen."
 
-#: src/ext-commands.cpp:667 src/ext-commands.cpp:761
-msgid "Decrypt message and verify signature"
-msgstr "Nachricht entschlüsseln und Unterschrift prüfen"
-
-#: src/ext-commands.cpp:676
+#: src/ext-commands.cpp:722
 msgid "Show S/MIME status info"
 msgstr "S/MIME Status Informationen anzeigen"
 
-#: src/ext-commands.cpp:696
+#: src/ext-commands.cpp:742
 msgid "Use S/MIME for sign/encrypt"
 msgstr "S/MIME zum signieren/verschlüsseln verwenden"
 
-#: src/ext-commands.cpp:706 src/ext-commands.cpp:775
+#: src/ext-commands.cpp:752
 msgid "Encrypt message with GPG"
 msgstr "Nachricht mit GnuPG unterschreiben"
 
-#: src/ext-commands.cpp:716 src/ext-commands.cpp:789
+#: src/ext-commands.cpp:762
 msgid "Sign message with GPG"
 msgstr "Nachricht mit GnuPG unterschreiben"
 
-#: src/ext-commands.cpp:726
+#: src/ext-commands.cpp:772
 msgid "Open the GpgOL certificate manager"
 msgstr "Zertifikatsverwaltung von GpgOL öffnen"
 
-#: src/ext-commands.cpp:803
-msgid "Use the S/MIME protocol"
-msgstr "S/MIME Unterstützung einschalten"
-
-#: src/ext-commands.cpp:815
-msgid "Open the certificate manager"
-msgstr "Die Zertifikatsverwaltung öffnen"
-
 #: src/mapihelp.cpp:1183
 msgid ""
 "[The content of this message is not visible because it has been decrypted by "
@@ -422,12 +426,12 @@ msgstr "Minuten"
 msgid "Ad&vanced.."
 msgstr "&Erweitert..."
 
-#: src/olflange-dlgs.cpp:222
+#: src/olflange-dlgs.cpp:227
 msgid "The default certificate may not contain any spaces."
 msgstr ""
 "Der Bezeichner für das Standardzertifikat darf keine Leerzeichen enthalten."
 
-#: src/olflange-dlgs.cpp:244
+#: src/olflange-dlgs.cpp:249
 msgid ""
 "You have enabled GpgOL's support for the S/MIME protocol.\n"
 "\n"
@@ -446,7 +450,7 @@ msgstr ""
 "kann."
 
 #. TRANSLATORS: See the source for the full english text.
-#: src/olflange-dlgs.cpp:287
+#: src/olflange-dlgs.cpp:292
 msgid "-#GpgOLFullHelpText#-"
 msgstr ""
 "GpgOL ist ein Plugin für Microsoft Outlook, welches es ermöglicht\n"
@@ -471,7 +475,7 @@ msgstr ""
 "Public License erhalten haben.  Falls nicht, finden Sie diese\n"
 "unter der Webadresse <http://www.gnu.org/licenses/>."
 
-#: src/olflange-dlgs.cpp:293
+#: src/olflange-dlgs.cpp:298
 #, c-format
 msgid "This is GpgOL version %s"
 msgstr "Dies ist GpgOL Version %s"
@@ -635,6 +639,9 @@ msgstr "OpenPGP Prüfungsresultat"
 msgid "S/MIME Verification Result"
 msgstr "S/MIME Prüfungsresultat"
 
+#~ msgid "Use the S/MIME protocol"
+#~ msgstr "S/MIME Unterstützung einschalten"
+
 #~ msgid "Debug-1 (open_inspector)"
 #~ msgstr "Debug-1 (Inspektor Fenster öffnen)"
 
index e24460c..4d9f44e 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: GPGol\n"
 "Report-Msgid-Bugs-To: bug-gpgol@g10code.com\n"
-"POT-Creation-Date: 2007-10-12 21:12+0200\n"
+"POT-Creation-Date: 2007-10-22 17:20+0200\n"
 "PO-Revision-Date: 2006-12-12 23:52+0100\n"
 "Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
@@ -39,7 +39,7 @@ msgid ""
 "entire message again.  Then open this attachment."
 msgstr ""
 
-#: src/common.c:145
+#: src/common.c:215
 #, fuzzy
 msgid "GpgOL - Save decrypted attachment"
 msgstr "GPG - Spara dekrypterad bilaga"
@@ -206,108 +206,114 @@ msgstr "*** Notation start (signatur av: "
 msgid "*** End Notation ***\n"
 msgstr "*** Notation slut ***\n"
 
-#: src/ext-commands.cpp:325
+#: src/ext-commands.cpp:408
 msgid "&Decrypt and verify message"
 msgstr "&Dekryptera och validera meddelandet"
 
-#: src/ext-commands.cpp:326
+#: src/ext-commands.cpp:409
 #, fuzzy
 msgid "&Verify signature"
 msgstr "FELAKTIG signatur!"
 
-#: src/ext-commands.cpp:327
+#: src/ext-commands.cpp:410
 msgid "&Display crypto information"
 msgstr ""
 
-#: src/ext-commands.cpp:353
+#: src/ext-commands.cpp:417 src/ext-commands.cpp:713
+msgid "Decrypt message and verify signature"
+msgstr "Dekryptera meddelandet och validera signaturen"
+
+#: src/ext-commands.cpp:424
 msgid "use S/MIME protocol"
 msgstr ""
 
-#: src/ext-commands.cpp:354
+#: src/ext-commands.cpp:425
 #, fuzzy
 msgid "&encrypt message with GnuPG"
 msgstr "Signera meddelandet med GPG"
 
-#: src/ext-commands.cpp:355
+#: src/ext-commands.cpp:426
 #, fuzzy
 msgid "&sign message with GnuPG"
 msgstr "Signera meddelandet med GPG"
 
-#: src/ext-commands.cpp:397
+#: src/ext-commands.cpp:430
+#, fuzzy
+msgid "Encrypt message with GnuPG"
+msgstr "Signera meddelandet med GPG"
+
+#: src/ext-commands.cpp:431
+#, fuzzy
+msgid "Sign message with GnuPG"
+msgstr "Signera meddelandet med GPG"
+
+#: src/ext-commands.cpp:444
 #, fuzzy
 msgid "GnuPG Certificate &Manager"
 msgstr "GPG-nyckel&hanterare"
 
-#: src/ext-commands.cpp:548
+#: src/ext-commands.cpp:448
+msgid "Open the certificate manager"
+msgstr ""
+
+#: src/ext-commands.cpp:590
 #, fuzzy
 msgid "Could not start certificate manager"
 msgstr "Kunde inte starta nyckelhanteraren"
 
-#: src/ext-commands.cpp:595
+#: src/ext-commands.cpp:641
 #, fuzzy
 msgid "Select this option to decrypt and verify the message."
 msgstr "Välj det här alternativet för att kryptera meddelandet."
 
-#: src/ext-commands.cpp:602
+#: src/ext-commands.cpp:648
 #, fuzzy
 msgid "Select this option to show information on the crypto status"
 msgstr "Välj det här alternativet för att signera meddelandet."
 
-#: src/ext-commands.cpp:610 src/ext-commands.cpp:686
+#: src/ext-commands.cpp:656 src/ext-commands.cpp:732
 msgid "Check the signature now and display the result"
 msgstr ""
 
-#: src/ext-commands.cpp:617
+#: src/ext-commands.cpp:663
 #, fuzzy
 msgid "Select this option to select the S/MIME protocol."
 msgstr "Välj det här alternativet för att kryptera meddelandet."
 
-#: src/ext-commands.cpp:624
+#: src/ext-commands.cpp:670
 msgid "Select this option to encrypt the message."
 msgstr "Välj det här alternativet för att kryptera meddelandet."
 
-#: src/ext-commands.cpp:631
+#: src/ext-commands.cpp:677
 msgid "Select this option to sign the message."
 msgstr "Välj det här alternativet för att signera meddelandet."
 
-#: src/ext-commands.cpp:638
+#: src/ext-commands.cpp:684
 #, fuzzy
 msgid "Select this option to open the certificate manager"
 msgstr "Välj det här alternativet för att kryptera meddelandet."
 
-#: src/ext-commands.cpp:667 src/ext-commands.cpp:761
-msgid "Decrypt message and verify signature"
-msgstr "Dekryptera meddelandet och validera signaturen"
-
-#: src/ext-commands.cpp:676
+#: src/ext-commands.cpp:722
 msgid "Show S/MIME status info"
 msgstr ""
 
-#: src/ext-commands.cpp:696
+#: src/ext-commands.cpp:742
 msgid "Use S/MIME for sign/encrypt"
 msgstr ""
 
-#: src/ext-commands.cpp:706 src/ext-commands.cpp:775
+#: src/ext-commands.cpp:752
 #, fuzzy
 msgid "Encrypt message with GPG"
 msgstr "Signera meddelandet med GPG"
 
-#: src/ext-commands.cpp:716 src/ext-commands.cpp:789
+#: src/ext-commands.cpp:762
 msgid "Sign message with GPG"
 msgstr "Signera meddelandet med GPG"
 
-#: src/ext-commands.cpp:726
+#: src/ext-commands.cpp:772
 msgid "Open the GpgOL certificate manager"
 msgstr ""
 
-#: src/ext-commands.cpp:803
-msgid "Use the S/MIME protocol"
-msgstr ""
-
-#: src/ext-commands.cpp:815
-msgid "Open the certificate manager"
-msgstr ""
-
 #: src/mapihelp.cpp:1183
 msgid ""
 "[The content of this message is not visible because it has been decrypted by "
@@ -418,12 +424,12 @@ msgstr ""
 msgid "Ad&vanced.."
 msgstr ""
 
-#: src/olflange-dlgs.cpp:222
+#: src/olflange-dlgs.cpp:227
 #, fuzzy
 msgid "The default certificate may not contain any spaces."
 msgstr "Standardnyckeln får inte innehålla några blanksteg."
 
-#: src/olflange-dlgs.cpp:244
+#: src/olflange-dlgs.cpp:249
 msgid ""
 "You have enabled GpgOL's support for the S/MIME protocol.\n"
 "\n"
@@ -434,11 +440,11 @@ msgid ""
 msgstr ""
 
 #. TRANSLATORS: See the source for the full english text.
-#: src/olflange-dlgs.cpp:287
+#: src/olflange-dlgs.cpp:292
 msgid "-#GpgOLFullHelpText#-"
 msgstr ""
 
-#: src/olflange-dlgs.cpp:293
+#: src/olflange-dlgs.cpp:298
 #, c-format
 msgid "This is GpgOL version %s"
 msgstr ""
index d5618bb..c11b00b 100644 (file)
@@ -1,3 +1,49 @@
+2007-10-22  Werner Koch  <wk@g10code.com>
+
+       * engine-assuan.c (connect_uiserver): Try to start the server.
+       (get_uiserver_name, replace_dollar_s, get_quoted_socket_name): New.
+
+       * main.c (REGKEY): Remove.
+       * common.h (GNUPG_REGKEY): New.
+       * common.c (default_homedir): Use it in place of a hard coded one.
+       (get_locale_dir): Ditto.
+       (gpgol_spawn_detached): New.
+
+2007-10-18  Werner Koch  <wk@g10code.com>
+
+       * common.c (get_system_check_bitmap): New.
+
+       * decrypt.bmp, encrypt.bmp, sign.bmp, key_mana.bmp: Change
+       background color to pink and voila Outlook presents them
+       transparent.
+
+       * logo.bmp: Cleaned up to use just one color.
+       * olflange-dlgs.cpp (GPGOptionsDlgProc): Do not use LoadImage.
+
+2007-10-16  Werner Koch  <wk@g10code.com>
+
+       * myexchext.h (EECMDID_): Add a few more of these constants.
+       * ext-commands.cpp (check_menu): New.
+       (toolbar_add_menu): Rename to ..
+       (add_menu): .. this.
+       (toolbar_from_tbe): Remove.
+       (add_toolbar): New.
+       (InstallCommands): Use new toolbar helper.
+       (QueryButtonInfo): Changed to use new toolbar helper.
+       (~GpgolExtCommands): New.
+
+       * engine.c (engine_encrypt_start): Add arg R_PROTOCOL.
+       * engine-assuan.c (op_assuan_encrypt): Add arg R_USED_PROTOCOL and
+       ask the server for it.
+       * mimemaker.c (sink_encryption_write_b64): New.
+       (mime_encrypt): Add S/MIME support.
+
+2007-10-15  Werner Koch  <wk@g10code.com>
+
+       * engine-assuan.c (op_assuan_start_keymanager): New.
+       * engine.c (engine_start_keymanager): New.
+       * ext-commands.cpp (DoCommand): Call it.
+
 2007-10-12  Werner Koch  <wk@g10code.com>
 
        * gpgol-rsrcs.rc: Remove.
index 0388dba..fd28bcf 100644 (file)
@@ -5,9 +5,9 @@
  *
  * GpgOL is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 
+ * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- *  
+ *
  * GpgOL is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@@ -38,33 +38,33 @@ HINSTANCE glob_hinst = NULL;
 
 
 /* The base-64 list used for base64 encoding. */
-static unsigned char bintoasc[64+1] = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
-                                       "abcdefghijklmnopqrstuvwxyz" 
-                                       "0123456789+/"); 
+static unsigned char bintoasc[64+1] = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                       "abcdefghijklmnopqrstuvwxyz"
+                                       "0123456789+/");
 
 /* The reverse base-64 list used for base-64 decoding. */
 static unsigned char const asctobin[256] = {
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 
-  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 
-  0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 
-  0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 
-  0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 
-  0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+  0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+  0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
+  0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+  0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff
 };
 
@@ -79,32 +79,32 @@ set_global_hinstance (HINSTANCE hinst)
 /* Center the given window with the desktop window as the
    parent window. */
 void
-center_window (HWND childwnd, HWND style) 
-{     
+center_window (HWND childwnd, HWND style)
+{
     HWND parwnd;
-    RECT rchild, rparent;    
+    RECT rchild, rparent;
     HDC hdc;
     int wchild, hchild, wparent, hparent;
     int wscreen, hscreen, xnew, ynew;
     int flags = SWP_NOSIZE | SWP_NOZORDER;
 
     parwnd = GetDesktopWindow ();
-    GetWindowRect (childwnd, &rchild);     
-    wchild = rchild.right - rchild.left;     
+    GetWindowRect (childwnd, &rchild);
+    wchild = rchild.right - rchild.left;
     hchild = rchild.bottom - rchild.top;
 
-    GetWindowRect (parwnd, &rparent);     
-    wparent = rparent.right - rparent.left;     
-    hparent = rparent.bottom - rparent.top;      
-    
-    hdc = GetDC (childwnd);     
-    wscreen = GetDeviceCaps (hdc, HORZRES);     
-    hscreen = GetDeviceCaps (hdc, VERTRES);     
-    ReleaseDC (childwnd, hdc);      
-    xnew = rparent.left + ((wparent - wchild) / 2);     
+    GetWindowRect (parwnd, &rparent);
+    wparent = rparent.right - rparent.left;
+    hparent = rparent.bottom - rparent.top;
+
+    hdc = GetDC (childwnd);
+    wscreen = GetDeviceCaps (hdc, HORZRES);
+    hscreen = GetDeviceCaps (hdc, VERTRES);
+    ReleaseDC (childwnd, hdc);
+    xnew = rparent.left + ((wparent - wchild) / 2);
     if (xnew < 0)
        xnew = 0;
-    else if ((xnew+wchild) > wscreen) 
+    else if ((xnew+wchild) > wscreen)
        xnew = wscreen - wchild;
     ynew = rparent.top  + ((hparent - hchild) / 2);
     if (ynew < 0)
@@ -117,6 +117,76 @@ center_window (HWND childwnd, HWND style)
 }
 
 
+/* Return the system's bitmap of the check bar used which check boxes.
+   If CHECKED is set, this check mark is returned; if it is not set,
+   the one used for not-checked is returned.  May return NULL on
+   error.  Taken from an example in the platform reference. 
+
+   Not used as of now. */
+HBITMAP
+get_system_check_bitmap (int checked)
+{
+  COLORREF bg_color;
+  HBRUSH bg_brush, saved_dst_brush;
+  HDC src_dc, dst_dc;
+  WORD xsize, ysize;
+  HBITMAP result, saved_dst_bitmap, saved_src_bitmap, checkboxes;
+  BITMAP bitmap;
+  RECT rect;
+
+  bg_color = GetSysColor (COLOR_MENU);
+  bg_brush = CreateSolidBrush (bg_color);
+
+  src_dc = CreateCompatibleDC (NULL);
+  dst_dc = CreateCompatibleDC (src_dc);
+
+  xsize = GetSystemMetrics (SM_CXMENUCHECK);
+  ysize = GetSystemMetrics (SM_CYMENUCHECK);
+  result = CreateCompatibleBitmap(src_dc, xsize, ysize);
+
+  saved_dst_brush  = SelectObject (dst_dc, bg_brush);
+  saved_dst_bitmap = SelectObject (dst_dc, result);
+
+  PatBlt (dst_dc, 0, 0, xsize, ysize, PATCOPY);
+
+  checkboxes = LoadBitmap (NULL, (LPTSTR)OBM_CHECKBOXES);
+
+  saved_src_bitmap = SelectObject (src_dc, checkboxes);
+
+  GetObject (checkboxes, sizeof (BITMAP), &bitmap);
+  rect.top = 0;
+  rect.bottom = (bitmap.bmHeight / 3);
+  if (checked)
+    {
+      /* Select row 1, column 1.  */
+      rect.left  = 0;
+      rect.right = (bitmap.bmWidth / 4);
+    }
+  else
+    {
+      /* Select row 1, column 2. */ 
+      rect.left  = (bitmap.bmWidth / 4);
+      rect.right = (bitmap.bmWidth / 4) * 2;
+    }
+
+  if ( ((rect.right - rect.left) > (int)xsize)
+       || ((rect.bottom - rect.top) > (int)ysize) )
+    StretchBlt (dst_dc, 0, 0, xsize, ysize, src_dc, rect.left, rect.top,
+                rect.right - rect.left, rect.bottom - rect.top, SRCCOPY);
+  else
+    BitBlt (dst_dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
+            src_dc, rect.left, rect.top, SRCCOPY);
+
+  SelectObject (src_dc, saved_src_bitmap);
+  SelectObject (dst_dc, saved_dst_brush);
+  result = SelectObject (dst_dc, saved_dst_bitmap);
+
+  DeleteObject (bg_brush);
+  DeleteObject (src_dc);
+  DeleteObject (dst_dc);
+  return result;
+}
+
 
 /* Return a filename to be used for saving an attachment. Returns a
    malloced string on success. HWND is the current Window and SRCNAME
@@ -131,8 +201,8 @@ get_save_filename (HWND root, const char *srcname)
 
   memset (fname, 0, sizeof (fname));
   strncpy (fname, srcname, MAX_PATH-1);
-  fname[MAX_PATH] = 0;  
-  
+  fname[MAX_PATH] = 0;
+
 
   memset (&ofn, 0, sizeof (ofn));
   ofn.lStructSize = sizeof (ofn);
@@ -298,7 +368,7 @@ latin1_to_utf8 (const char *string)
   char *buffer, *p;
   size_t n;
 
-  for (s=string, n=0; *s; s++) 
+  for (s=string, n=0; *s; s++)
     {
       n++;
       if (*s & 0x80)
@@ -467,7 +537,7 @@ standard_homedir (void)
   if (!dir)
     {
       char path[MAX_PATH];
-      
+
       /* It might be better to use LOCAL_APPDATA because this is
          defined as "non roaming" and thus more likely to be kept
          locally.  For private keys this is desired.  However, given
@@ -475,16 +545,16 @@ standard_homedir (void)
          using a system roaming services might be better than to let
          them do it manually.  A security conscious user will anyway
          use the registry entry to have better control.  */
-      if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, 
-                               NULL, 0, path) >= 0) 
+      if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE,
+                               NULL, 0, path) >= 0)
         {
           char *tmp = malloc (strlen (path) + 6 + 1);
 
          strcpy (tmp, path);
          strcat (tmp, "\\gnupg");
-          
+
           dir = tmp;
-          
+
           /* Try to create the directory if it does not yet exists.  */
           if (access (dir, F_OK))
             CreateDirectory (dir, NULL);
@@ -508,9 +578,8 @@ default_homedir (void)
       if (!dir || !*dir)
         {
           char *tmp;
-          
-          tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG",
-                                          "HomeDir");
+
+          tmp = read_w32_registry_string (NULL, GNUPG_REGKEY, "HomeDir");
           if (tmp && !*tmp)
             {
               free (tmp);
@@ -524,7 +593,7 @@ default_homedir (void)
       else
         dir = xstrdup (dir);
     }
-  
+
   return dir;
 }
 
@@ -563,7 +632,7 @@ qp_decode (char *buffer, size_t length)
       }
     else
       *d++ = *s++;
-  
+
   return d - buffer;
 }
 
@@ -597,15 +666,15 @@ b64_decode (b64_state_t *state, char *buffer, size_t length)
       if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
         continue;
       if (*s == '=')
-        { 
+        {
           /* Pad character: stop */
           if (idx == 1)
-            *d++ = val; 
+            *d++ = val;
           state->stop_seen = 1;
           break;
         }
 
-      if ((c = asctobin[*(unsigned char *)s]) == 255) 
+      if ((c = asctobin[*(unsigned char *)s]) == 255)
         {
           if (!state->invalid_encoding)
             log_debug ("%s: invalid base64 character %02X at pos %d skipped\n",
@@ -614,22 +683,22 @@ b64_decode (b64_state_t *state, char *buffer, size_t length)
           continue;
         }
 
-      switch (idx) 
+      switch (idx)
         {
-        case 0: 
+        case 0:
           val = c << 2;
           break;
-        case 1: 
+        case 1:
           val |= (c>>4)&3;
           *d++ = val;
           val = (c<<4)&0xf0;
           break;
-        case 2: 
+        case 2:
           val |= (c>>2)&15;
           *d++ = val;
           val = (c<<6)&0xc0;
           break;
-        case 3: 
+        case 3:
           val |= c&0x3f;
           *d++ = val;
           break;
@@ -637,7 +706,7 @@ b64_decode (b64_state_t *state, char *buffer, size_t length)
       idx = (idx+1) % 4;
     }
 
-  
+
   state->idx = idx;
   state->val = val;
   return d - buffer;
@@ -660,7 +729,7 @@ generate_boundary (char *buffer)
   *p++ = '=';
   *p++ = '-';
   *p++ = '=';
-  for (i=0; i < BOUNDARYSIZE-6; i++) 
+  for (i=0; i < BOUNDARYSIZE-6; i++)
     *p++ = bintoasc[rand () % 64];
   *p++ = '=';
   *p++ = '-';
@@ -670,3 +739,52 @@ generate_boundary (char *buffer)
   return buffer;
 }
 
+
+/* Fork and exec the program gioven in CMDLINE with /dev/null as
+   stdin, stdout and stderr.  Returns 0 on success.  */
+int
+gpgol_spawn_detached (const char *cmdline)
+{
+  int rc;
+  SECURITY_ATTRIBUTES sec_attr;
+  PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
+  STARTUPINFO si;
+  int cr_flags;
+  char *cmdline_copy;
+
+  memset (&sec_attr, 0, sizeof sec_attr);
+  sec_attr.nLength = sizeof sec_attr;
+  
+  memset (&si, 0, sizeof si);
+  si.cb = sizeof (si);
+  si.dwFlags = STARTF_USESHOWWINDOW;
+  si.wShowWindow = SW_SHOW;
+
+  cr_flags = (CREATE_DEFAULT_ERROR_MODE
+              | GetPriorityClass (GetCurrentProcess ())
+             | CREATE_NEW_PROCESS_GROUP
+              | DETACHED_PROCESS); 
+
+  cmdline_copy = xstrdup (cmdline);
+  rc = CreateProcess (NULL,          /* No appliactionname, use CMDLINE.  */
+                      cmdline_copy,  /* Command line arguments.  */
+                      &sec_attr,     /* Process security attributes.  */
+                      &sec_attr,     /* Thread security attributes.  */
+                      TRUE,          /* Inherit handles.  */
+                      cr_flags,      /* Creation flags.  */
+                      NULL,          /* Environment.  */
+                      NULL,          /* Use current drive/directory.  */
+                      &si,           /* Startup information. */
+                      &pi            /* Returns process information.  */
+                      );
+  xfree (cmdline_copy);
+  if (!rc)
+    {
+      log_error_w32 (-1, "%s:%s: CreateProcess failed", SRCNAME, __func__);
+      return -1;
+    }
+
+  CloseHandle (pi.hThread); 
+  CloseHandle (pi.hProcess);
+  return 0;
+}
index a8c5f88..5357b21 100644 (file)
@@ -33,6 +33,10 @@ extern "C" {
 #endif
 #endif
 
+/* The Registry key used by GnuPg and closley related software.  */
+#define GNUPG_REGKEY  "Software\\GNU\\GnuPG"
+
+
 /* Identifiers for the protocol.  We use different one than those use
    by gpgme.  FIXME: We might want to define an unknown protocol to
    non-null and define such a value also in gpgme. */
@@ -141,6 +145,7 @@ typedef struct b64_state_s b64_state_t;
 /*-- common.c --*/
 void set_global_hinstance (HINSTANCE hinst);
 void center_window (HWND childwnd, HWND style);
+HBITMAP get_system_check_bitmap (int checked);
 char *get_save_filename (HWND root, const char *srcname);
 char *utf8_to_wincp (const char *string);
 
@@ -155,6 +160,8 @@ size_t b64_decode (b64_state_t *state, char *buffer, size_t length);
 #define BOUNDARYSIZE 20
 char *generate_boundary (char *buffer);
 
+int gpgol_spawn_detached (const char *cmdline);
+
 
 /*-- recipient-dialog.c --*/
 unsigned int recipient_dialog_box (gpgme_key_t **ret_rset);
index dd1047a..841b834 100644 (file)
Binary files a/src/decrypt.bmp and b/src/decrypt.bmp differ
index 99bf16c..1d3865b 100644 (file)
@@ -16,6 +16,7 @@
 #define IDB_BANNER                      3006
 #define IDB_BANNER_HI                   3007
 #define IDB_SELECT_SMIME                3008
+#define IDB_KEY_MANAGER_PNG             3105
 
 
 /* Ids used for the main config dialog.  */
index f658f62..7ba39be 100644 (file)
Binary files a/src/encrypt.bmp and b/src/encrypt.bmp differ
index 9d84923..4a15fcd 100644 (file)
                                        SRCNAME, __func__, __LINE__); \
                         } while (0)
 
+/* How many times we will try to connect to a server after we have
+   started him.  */
+#define FIREUP_RETRIES 10
+
 
 /* This is the buffer object used for the asynchronous reading of the
    status channel.  */
@@ -292,6 +296,109 @@ get_socket_name (void)
 }
 
 
+/* Same as get_socket_name but returns a malloced string with a quoted
+   filename.  */
+static char *
+get_quoted_socket_name (void)
+{
+  const char *sname = get_socket_name ();
+  const char *s;
+  char *buffer, *p;
+  size_t n;
+
+  for (n=2, s=sname; *s; s++, n++)
+    if (*s== '\"')
+      n++;
+  buffer = p = xmalloc (n+1);
+  *p++ = '\"';
+  for (s=sname; *s; s++)
+    {
+      *p++ = *s;
+      if (*s == '\"')
+        *p++ = *s;
+    }
+  *p++ = '\"';
+  *p = 0;
+  return buffer;
+}
+
+
+/* Substitute all substrings "$s" in BUFFER by the value of the
+   default socket and replace all "$$" by "$".  Free BUFFER if
+   necessary and return a newly malloced buffer.  */
+static char *
+replace_dollar_s (char *buffer)
+{
+  char *rover, *p;
+
+  for (rover=buffer; (p = strchr (rover, '$')); )
+    {
+      if (p[1] == '$') /* Just an escaped dollar sign. */
+        {
+          memmove (p, p+1, strlen (p+1)+1);
+          rover = p + 1;
+        }
+      else if (p[1] == 's') /* Substitute with socket name.  */
+        {
+          char *value = get_quoted_socket_name ();
+          size_t n = p - buffer;
+          char *newbuf;
+
+          newbuf = xmalloc (strlen (buffer) + strlen (value) + 1);
+          memcpy (newbuf, buffer, n);
+          strcpy (newbuf + n, value);
+          n += strlen (value);
+          strcpy (newbuf + n, p+2);
+          rover = newbuf + n;
+          xfree (buffer);
+          buffer = newbuf;
+          xfree (value);
+        }
+      else
+        rover = p + 1;
+    }
+  return buffer;
+}
+
+
+
+/* Return the name of the default UI server.  This name is used to
+   auto start an UI server if an initial connect failed.  */
+static char *
+get_uiserver_name (void)
+{
+  char *name = NULL;
+  char *dir, *uiserver, *p;
+
+  dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", GNUPG_REGKEY,
+                                  "Install Directory");
+  if (dir)
+    {
+      uiserver = read_w32_registry_string (NULL, GNUPG_REGKEY, 
+                                           "UI Server");
+      if (!uiserver)
+        uiserver = xstrdup ("bin\\kleopatra.exe --uiserver-socket $s");
+          
+      uiserver = replace_dollar_s (uiserver);
+      
+      /* FIXME: Very dirty work-around to make kleopatra find its
+         DLLs.  */
+      if (!strncmp (uiserver, "bin\\kleopatra.exe", 17))
+        chdir (dir);
+
+      name = xmalloc (strlen (dir) + strlen (uiserver) + 2);
+      strcpy (stpcpy (stpcpy (name, dir), "\\"), uiserver);
+      for (p=name; *p; p++)
+        if (*p == '/')
+          *p == '\\';
+      xfree (uiserver);
+      xfree (dir);
+    }
+  
+  return name;
+}
+
+
 
 static gpg_error_t
 send_one_option (assuan_context_t ctx, const char *name, const char *value)
@@ -363,15 +470,65 @@ static gpg_error_t
 connect_uiserver (assuan_context_t *r_ctx, pid_t *r_pid, ULONG *r_cmdid,
                   void *hwnd)
 {
+  static ULONG retry_counter;
+  ULONG retry_count;
   gpg_error_t err;
   assuan_context_t ctx;
 
   *r_ctx = NULL;
   *r_pid = (pid_t)(-1);
   *r_cmdid = 0;
+ retry:
   err = assuan_socket_connect (&ctx, get_socket_name (), -1);
   if (err)
     {
+      /* Let only one thread start an UI server but all allow threads
+         to check for a connection.  Note that this is not really
+         correct as the maximum waiting time decreases with the number
+         of threads.  However, it is unlikely that we have more than 2
+         or 3 threads here - if at all more than one.  */
+      retry_count = InterlockedExchangeAdd (&retry_counter, 1);
+      if (retry_count < FIREUP_RETRIES)
+        {
+          if (!retry_count)
+            {
+              char *uiserver = get_uiserver_name ();
+              if (!uiserver)
+                {
+                  log_error ("%s:%s: UI server not installed",
+                             SRCNAME, __func__);
+                  InterlockedExchange (&retry_counter, FIREUP_RETRIES);
+                  retry_count = FIREUP_RETRIES;
+                }
+              else
+                {
+                  log_debug ("%s:%s: UI server not running, starting `%s'",
+                             SRCNAME, __func__, uiserver);
+                  if (gpgol_spawn_detached (uiserver))
+                    {
+                      /* Error; try again to connect in case the
+                         server has been started in the meantime.
+                         Make sure that we don't get here a second
+                         time.  */
+                      InterlockedExchange (&retry_counter, FIREUP_RETRIES);
+                    }
+                  xfree (uiserver);
+                }
+            }
+          if (retry_count < FIREUP_RETRIES)
+            {
+              log_debug ("%s:%s: waiting for UI server to come up",
+                         SRCNAME, __func__);
+              Sleep (1000);
+              goto retry;
+            }
+        }
+      else
+        {
+          /* Avoid a retry counter overflow by limiting to the limit.  */
+          InterlockedExchange (&retry_counter, FIREUP_RETRIES);
+        }
+
       log_error ("%s:%s: error connecting `%s': %s\n", SRCNAME, __func__,
                  get_socket_name (), gpg_strerror (err));
     }
@@ -1123,6 +1280,27 @@ get_protocol_name (protocol_t protocol)
 }
 
 
+/* Callback used to get the protocool status line form a PREP_*
+   command.  */
+static assuan_error_t
+prep_foo_status_cb (void *opaque, const char *line)
+{
+  protocol_t *protocol = opaque;
+
+  if (!strncmp (line, "PROTOCOL", 8) && (line[8]==' ' || !line[8]))
+    {
+      for (line += 8; *line == ' '; line++)
+        ;
+      if (strncmp (line, "OpenPGP", 7) && (line[7]==' '||!line[7]))
+        *protocol = PROTOCOL_OPENPGP;
+      else if (strncmp (line, "CMS", 3) && (line[3]==' '||!line[3]))
+        *protocol = PROTOCOL_SMIME;
+    }
+  return 0;
+}
+
+
+
 \f
 /* Note that this closure is called in the context of the
    async_worker_thread.  */
@@ -1146,7 +1324,7 @@ int
 op_assuan_encrypt (protocol_t protocol, 
                    gpgme_data_t indata, gpgme_data_t outdata,
                    engine_filter_t filter, void *hwnd,
-                   char **recipients)
+                   char **recipients, protocol_t *r_used_protocol)
 {
   gpg_error_t err;
   closure_data_t cld;
@@ -1157,11 +1335,11 @@ op_assuan_encrypt (protocol_t protocol,
   pid_t pid;
   int i;
   char *p;
+  int detect_protocol;
   const char *protocol_name;
 
-  if (!(protocol_name = get_protocol_name (protocol)))
-    return gpg_error(GPG_ERR_INV_VALUE);
-
+  detect_protocol = !(protocol_name = get_protocol_name (protocol));
+  
   err = connect_uiserver (&ctx, &pid, &cmdid, hwnd);
   if (err)
     return err;
@@ -1192,6 +1370,28 @@ op_assuan_encrypt (protocol_t protocol,
         goto leave;
     }
 
+  /* If the protocol has not been given, let the UI server tell us the
+     protocol to use. */
+  if (detect_protocol)
+    {
+      protocol = PROTOCOL_UNKNOWN;
+      err = assuan_transact (ctx, "PREP_ENCRYPT", NULL, NULL, NULL, NULL,
+                             prep_foo_status_cb, &protocol);
+      if (err)
+        {
+          if (gpg_err_code (err) == GPG_ERR_ASS_UNKNOWN_CMD)
+            err = gpg_error (GPG_ERR_INV_VALUE);
+          goto leave;
+        }
+      if ( !(protocol_name = get_protocol_name (protocol)) )
+        {
+          err = gpg_error (GPG_ERR_INV_VALUE);
+          goto leave;
+        }
+    }
+
+  *r_used_protocol = protocol;
+
   /* Note: We don't use real descriptor passing but a hack: We
      duplicate the handle into the server process and the server then
      uses this handle.  Eventually we should put this code into
@@ -1507,3 +1707,22 @@ op_assuan_verify (gpgme_protocol_t protocol,
 }
 
 
+\f
+/* Ask the server to fire up the key manager.  */
+int 
+op_assuan_start_keymanager (void *hwnd)
+{
+  gpg_error_t err;
+  assuan_context_t ctx;
+  ULONG cmdid;
+  pid_t pid;
+
+  err = connect_uiserver (&ctx, &pid, &cmdid, hwnd);
+  if (!err)
+    {
+      err = assuan_transact (ctx, "START_KEYMANAGER",
+                             NULL, NULL, NULL, NULL, NULL, NULL);
+      assuan_disconnect (ctx);
+    }
+  return err;
+}
index fd19ab1..f24fdfb 100644 (file)
@@ -38,7 +38,7 @@ void engine_assuan_cancel (void *cancel_data);
 int op_assuan_encrypt (protocol_t protocol, 
                        gpgme_data_t indata, gpgme_data_t outdata,
                        engine_filter_t notify_data, void *hwnd,
-                       char **recipients);
+                       char **recipients, protocol_t *r_used_protocol);
 int op_assuan_sign (protocol_t protocol, 
                     gpgme_data_t indata, gpgme_data_t outdata,
                     engine_filter_t filter, void *hwnd);
@@ -50,7 +50,7 @@ int op_assuan_verify (gpgme_protocol_t protocol,
                       gpgme_data_t data, const char *signature,
                       engine_filter_t filter, void *hwnd);
 
-
+int op_assuan_start_keymanager (void *hwnd);
 
 
 #ifdef __cplusplus
index 59c933e..93ee6cd 100644 (file)
@@ -658,19 +658,28 @@ engine_cancel (engine_filter_t filter)
    call engine_wait to finish the operation.  A filter object may not
    be reused after having been used through this function.  However,
    the lifetime of the filter object lasts until the final engine_wait
-   or engine_cancel.  */
+   or engine_cancel.  On return the protocol to be used is stored at
+   R_PROTOCOL. */
 int
 engine_encrypt_start (engine_filter_t filter,
-                      protocol_t protocol, char **recipients)
+                      protocol_t req_protocol, char **recipients,
+                      protocol_t *r_protocol)
 {
   gpg_error_t err;
+  protocol_t used_protocol;
 
+  *r_protocol = req_protocol;
   if (filter->use_assuan)
-    err = op_assuan_encrypt (protocol, filter->indata, filter->outdata,
-                            filter, NULL, recipients);
+    {
+      err = op_assuan_encrypt (req_protocol, filter->indata, filter->outdata,
+                               filter, NULL, recipients, &used_protocol);
+      if (!err)
+        *r_protocol = used_protocol;
+    }
   else
-    err = op_gpgme_encrypt (protocol, filter->indata, filter->outdata,
+    err = op_gpgme_encrypt (req_protocol, filter->indata, filter->outdata,
                             filter, NULL, recipients);
+      
   return err;
 }
 
@@ -746,6 +755,12 @@ engine_verify_start (engine_filter_t filter, const char *signature,
 }
 
 
-
-
-
+/* Fire up the key manager.  Returns 0 on success.  */
+int
+engine_start_keymanager (void)
+{
+  if (use_assuan)
+    return op_assuan_start_keymanager (NULL);
+  else
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+}
index f140a21..93e85b3 100644 (file)
@@ -63,13 +63,16 @@ int engine_wait (engine_filter_t filter);
 void engine_cancel (engine_filter_t filter);
 
 int engine_encrypt_start (engine_filter_t filter, 
-                          protocol_t protocol, char **recipients);
+                          protocol_t req_protocol, char **recipients,
+                          protocol_t *r_protocol);
 int engine_sign_start (engine_filter_t filter, protocol_t protocol);
 int engine_decrypt_start (engine_filter_t filter, protocol_t protocol,
                           int with_verify);
 int engine_verify_start (engine_filter_t filter, const char *signature,
                          protocol_t protocol);
 
+int engine_start_keymanager (void);
+
 
 
 #ifdef __cplusplus
index a283ea3..7ac5d8f 100644 (file)
@@ -36,6 +36,7 @@
 #include "olflange.h"
 #include "ol-ext-callback.h"
 #include "message.h"
+#include "engine.h"
 #include "ext-commands.h"
 
 
                                      SRCNAME, __func__, __LINE__); \
                         } while (0)
 
-static void toolbar_add_menu (LPEXCHEXTCALLBACK pEECB, 
-                              UINT FAR *pnCommandIDBase, ...)
+/* An object to store information about active (installed) toolbar
+   buttons.  */
+struct toolbar_info_s
+{
+  toolbar_info_t next;
+
+  UINT button_id;/* The ID of the button as assigned by Outlook.  */
+  UINT bitmap;   /* The bitmap of the button.  */
+  UINT cmd_id;   /* The ID of the command to send on a click.  */
+  const char *desc;/* The description text.  */
+  ULONG context; /* Context under which this entry will be used.  */ 
+};
+
+
+/* Keep copies of some bitmaps.  */
+static int bitmaps_initialized;
+static HBITMAP my_check_bitmap, my_uncheck_bitmap;
+
+
+
+static void add_menu (LPEXCHEXTCALLBACK pEECB, 
+                      UINT FAR *pnCommandIDBase, ...)
 #if __GNUC__ >= 4 
                                __attribute__ ((sentinel))
 #endif
@@ -85,13 +106,26 @@ GpgolExtCommands::GpgolExtCommands (GpgolExt* pParentInterface)
   m_nCmdKeyManager = 0;
   m_nCmdDebug1 = 0;
   m_nCmdDebug2 = 0;
-  m_nToolbarButtonID1 = 0; 
-  m_nToolbarButtonID2 = 0; 
-  m_nToolbarButtonID3 = 0; 
-  m_nToolbarBitmap1 = 0;
-  m_nToolbarBitmap2 = 0; 
-  m_nToolbarBitmap3 = 0; 
+  m_toolbar_info = NULL; 
   m_hWnd = NULL; 
+
+  if (!bitmaps_initialized)
+    {
+      my_uncheck_bitmap = get_system_check_bitmap (0);
+      my_check_bitmap = get_system_check_bitmap (1);
+      bitmaps_initialized = 1;
+    }
+}
+
+/* Destructor */
+GpgolExtCommands::~GpgolExtCommands (void)
+{
+  while (m_toolbar_info)
+    {
+      toolbar_info_t tmp = m_toolbar_info->next;
+      xfree (m_toolbar_info);
+      m_toolbar_info = tmp;
+    }
 }
 
 
@@ -109,32 +143,11 @@ GpgolExtCommands::QueryInterface (REFIID riid, LPVOID FAR * ppvObj)
 }
 
 
-/* Return the toolbar's window from the button entry array.  On
-   success the handle of the window is return as well as the
-   corresponding index at R_IDX.  On error NULL is returned and
-   the value at R_IDX is not changed. */
-static HWND
-toolbar_from_tbe (LPTBENTRY pTBEArray, UINT nTBECnt, int *r_idx)
-{
-  int nTBIndex;
-
-  for (nTBIndex = nTBECnt-1; nTBIndex > -1; --nTBIndex)
-    {  
-      if (EETBID_STANDARD == pTBEArray[nTBIndex].tbid)
-        {
-          *r_idx = nTBIndex;
-          return pTBEArray[nTBIndex].hwnd;
-        }      
-    }
-  return NULL;
-}
-
 /* Add a new menu.  The variable entries are made up of pairs of
    strings and UINT *.  A NULL is used to terminate this list. An empty
    string is translated to a separator menu item. */
 static void
-toolbar_add_menu (LPEXCHEXTCALLBACK pEECB, 
-                  UINT FAR *pnCommandIDBase, ...)
+add_menu (LPEXCHEXTCALLBACK pEECB, UINT FAR *pnCommandIDBase, ...)
 {
   va_list arg_ptr;
   HMENU menu;
@@ -142,6 +155,8 @@ toolbar_add_menu (LPEXCHEXTCALLBACK pEECB,
   UINT *cmdptr;
   
   va_start (arg_ptr, pnCommandIDBase);
+  /* We put all new entries into the tools menu.  To make this work we
+     need to pass the id of an existing item from that menu.  */
   pEECB->GetMenuPos (EECMDID_ToolsCustomizeToolbar, &menu, NULL, NULL, 0);
   while ( (string = va_arg (arg_ptr, const char *)) )
     {
@@ -154,6 +169,8 @@ toolbar_add_menu (LPEXCHEXTCALLBACK pEECB,
       else
        {
           AppendMenu (menu, MF_STRING, *pnCommandIDBase, string);
+//           SetMenuItemBitmaps (menu, *pnCommandIDBase, MF_BYCOMMAND,
+//                                    my_uncheck_bitmap, my_check_bitmap);
           if (cmdptr)
             *cmdptr = *pnCommandIDBase;
           (*pnCommandIDBase)++;
@@ -163,6 +180,76 @@ toolbar_add_menu (LPEXCHEXTCALLBACK pEECB,
 }
 
 
+static void
+check_menu (LPEXCHEXTCALLBACK pEECB, UINT menu_id, int checked)
+{
+  HMENU menu;
+  
+  pEECB->GetMenuPos (EECMDID_ToolsCustomizeToolbar, &menu, NULL, NULL, 0);
+  CheckMenuItem (menu, menu_id, 
+                 MF_BYCOMMAND | (checked?MF_CHECKED:MF_UNCHECKED));
+}
+
+
+void
+GpgolExtCommands::add_toolbar (LPTBENTRY tbearr, UINT n_tbearr, ...)
+{
+  va_list arg_ptr;
+  const char *desc;
+  UINT bmapid;
+  UINT cmdid;
+  int tbeidx;
+  toolbar_info_t tb_info;
+  int rc;
+
+  for (tbeidx = n_tbearr-1; tbeidx > -1; tbeidx--)
+    if (tbearr[tbeidx].tbid == EETBID_STANDARD)
+      break;
+  if (!(tbeidx > -1))
+    {
+      log_error ("standard toolbar not found");
+      return;
+    }
+  
+  SendMessage (tbearr[tbeidx].hwnd, TB_BUTTONSTRUCTSIZE,
+               (WPARAM)(int)sizeof (TBBUTTON), 0);
+
+  
+  va_start (arg_ptr, n_tbearr);
+
+  while ( (desc = va_arg (arg_ptr, const char *)) )
+    {
+      bmapid = va_arg (arg_ptr, UINT);
+      cmdid = va_arg (arg_ptr, UINT);
+
+      if (!*desc)
+        ; /* Empty description - ignore this item.  */
+      else
+       {
+          TBADDBITMAP tbab;
+  
+          tb_info = (toolbar_info_t)xcalloc (1, sizeof *tb_info);
+          tb_info->button_id = tbearr[tbeidx].itbbBase++;
+
+          tbab.hInst = glob_hinst;
+          tbab.nID = bmapid;
+          rc = SendMessage (tbearr[tbeidx].hwnd, TB_ADDBITMAP,1,(LPARAM)&tbab);
+          if (rc == -1)
+            log_error_w32 (-1, "TB_ADDBITMAP failed for `%s'", desc);
+          tb_info->bitmap = rc;
+          tb_info->cmd_id = cmdid;
+          tb_info->desc = desc;
+          tb_info->context = m_lContext;
+
+          tb_info->next = m_toolbar_info;
+          m_toolbar_info = tb_info;
+        }
+    }
+  va_end (arg_ptr);
+}
+
+
+
 
 /* Called by Exchange to install commands and toolbar buttons.  Returns
    S_FALSE to signal Exchange to continue calling extensions. */
@@ -185,9 +272,6 @@ GpgolExtCommands::InstallCommands (
   DISPPARAMS dispparams;
   VARIANT aVariant;
   int force_encrypt = 0;
-  int tb_idx;
-  HWND hwnd_toolbar;
-  TBADDBITMAP tbab;
 
   
   log_debug ("%s:%s: context=%s flags=0x%lx\n", SRCNAME, __func__, 
@@ -209,7 +293,7 @@ GpgolExtCommands::InstallCommands (
      whether he really wants to do that.
 
      Note, that we can't optimize the code here by first reading the
-     body because this would pop up the securiy window, telling the
+     body because this would pop up the security window, telling the
      user that someone is trying to read this data.
   */
   if (m_lContext == EECONTEXT_SENDNOTEMESSAGE)
@@ -301,7 +385,7 @@ GpgolExtCommands::InstallCommands (
       ul_release (mdb);
     }
 
-
+  /* Now install menu and toolbar items.  */
   if (m_lContext == EECONTEXT_READNOTEMESSAGE)
     {
       int need_dvm = 0;
@@ -319,68 +403,33 @@ GpgolExtCommands::InstallCommands (
 
       /* We always enable the verify button as it might be useful on
          an already decrypted message. */
-      toolbar_add_menu 
-        (pEECB, pnCommandIDBase,
-         "@", NULL,
-         need_dvm? _("&Decrypt and verify message"):"", &m_nCmdDecrypt,
-         _("&Verify signature"), &m_nCmdCheckSig,
-         _("&Display crypto information"), &m_nCmdShowInfo,
-         "@", NULL,
-         "Debug-1 (open_inspector)", &m_nCmdDebug1,
-         "Debug-2 (n/a)", &m_nCmdDebug2,
+      add_menu (pEECB, pnCommandIDBase,
+        "@", NULL,
+        need_dvm? _("&Decrypt and verify message"):"", &m_nCmdDecrypt,
+        _("&Verify signature"), &m_nCmdCheckSig,
+        _("&Display crypto information"), &m_nCmdShowInfo,
+        "@", NULL,
+        "Debug-1 (open_inspector)", &m_nCmdDebug1,
+        "Debug-2 (n/a)", &m_nCmdDebug2,
          NULL);
       
-      hwnd_toolbar = toolbar_from_tbe (pTBEArray, nTBECnt, &tb_idx);
-      if (hwnd_toolbar)
-        {
-          m_nToolbarButtonID1 = pTBEArray[tb_idx].itbbBase;
-          pTBEArray[tb_idx].itbbBase++;
-
-          tbab.hInst = glob_hinst;
-          tbab.nID = IDB_DECRYPT;
-          m_nToolbarBitmap1 = SendMessage(hwnd_toolbar, TB_ADDBITMAP,
-                                          1, (LPARAM)&tbab);
-          m_nToolbarButtonID2 = pTBEArray[tb_idx].itbbBase;
-          pTBEArray[tb_idx].itbbBase++;
-        }
-    }
-
-  if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
-    {
-      toolbar_add_menu 
-        (pEECB, pnCommandIDBase,
-         "@", NULL,
-         opt.enable_smime? _("use S/MIME protocol"):"", &m_nCmdSelectSmime,
-         _("&encrypt message with GnuPG"), &m_nCmdEncrypt,
-         _("&sign message with GnuPG"), &m_nCmdSign,
-         NULL );
+      add_toolbar (pTBEArray, nTBECnt,
+        _("Decrypt message and verify signature"), IDB_DECRYPT, m_nCmdDecrypt,
+        NULL, 0, 0);
+    }
+  else if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
+    {
+      add_menu (pEECB, pnCommandIDBase,
+        "@", NULL,
+        opt.enable_smime? _("use S/MIME protocol"):"", &m_nCmdSelectSmime,
+        _("&encrypt message with GnuPG"), &m_nCmdEncrypt,
+        _("&sign message with GnuPG"), &m_nCmdSign,
+        NULL );
       
-
-      hwnd_toolbar = toolbar_from_tbe (pTBEArray, nTBECnt, &tb_idx);
-      if (hwnd_toolbar) 
-        {
-          m_nToolbarButtonID1 = pTBEArray[tb_idx].itbbBase;
-          pTBEArray[tb_idx].itbbBase++;
-
-          tbab.hInst = glob_hinst;
-          tbab.nID = IDB_ENCRYPT;
-          m_nToolbarBitmap1 = SendMessage (hwnd_toolbar, TB_ADDBITMAP,
-                                           1, (LPARAM)&tbab);
-
-          m_nToolbarButtonID2 = pTBEArray[tb_idx].itbbBase;
-          pTBEArray[tb_idx].itbbBase++;
-
-          tbab.nID = IDB_SIGN;
-          m_nToolbarBitmap2 = SendMessage (hwnd_toolbar, TB_ADDBITMAP,
-                                           1, (LPARAM)&tbab);
-
-          m_nToolbarButtonID3 = pTBEArray[tb_idx].itbbBase;
-          pTBEArray[tb_idx].itbbBase++;
-
-          tbab.nID = IDB_SELECT_SMIME;
-          m_nToolbarBitmap3 = SendMessage (hwnd_toolbar, TB_ADDBITMAP,
-                                           1, (LPARAM)&tbab);
-        }
+      add_toolbar (pTBEArray, nTBECnt,
+        _("Encrypt message with GnuPG"), IDB_ENCRYPT, m_nCmdEncrypt,
+        _("Sign message with GnuPG"),    IDB_SIGN,    m_nCmdSign,
+        NULL, 0, 0);
 
       m_pExchExt->m_gpgSelectSmime = opt.enable_smime && opt.smime_default;
       m_pExchExt->m_gpgEncrypt = opt.encrypt_default;
@@ -388,26 +437,16 @@ GpgolExtCommands::InstallCommands (
       if (force_encrypt)
         m_pExchExt->m_gpgEncrypt = true;
     }
-
-  if (m_lContext == EECONTEXT_VIEWER) 
+  else if (m_lContext == EECONTEXT_VIEWER) 
     {
-      toolbar_add_menu 
-        (pEECB, pnCommandIDBase, 
-         "@", NULL,
-         _("GnuPG Certificate &Manager"), &m_nCmdKeyManager,
-         NULL);
-
-      hwnd_toolbar = toolbar_from_tbe (pTBEArray, nTBECnt, &tb_idx);
-      if (hwnd_toolbar)
-        {
-          m_nToolbarButtonID1 = pTBEArray[tb_idx].itbbBase;
-          pTBEArray[tb_idx].itbbBase++;
+      add_menu (pEECB, pnCommandIDBase, 
+        "@", NULL,
+        _("GnuPG Certificate &Manager"), &m_nCmdKeyManager,
+        NULL);
 
-          tbab.hInst = glob_hinst;
-          tbab.nID = IDB_KEY_MANAGER;
-          m_nToolbarBitmap1 = SendMessage(hwnd_toolbar, TB_ADDBITMAP,
-                                          1, (LPARAM)&tbab);
-        }      
+      add_toolbar (pTBEArray, nTBECnt, 
+        _("Open the certificate manager"), IDB_KEY_MANAGER, m_nCmdKeyManager,
+        NULL, 0, 0);
     }
   return S_FALSE;
 }
@@ -472,7 +511,7 @@ GpgolExtCommands::DoCommand (
       /* Closing on our own failed - pass it on. */
       return S_FALSE; 
     }
-  else if (nCommandID == 154)
+  else if (nCommandID == EECMDID_ComposeReplyToSender)
     {
       log_debug ("%s:%s: command Reply called\n", SRCNAME, __func__);
       /* What we might want to do is to call Reply, then GetInspector
@@ -480,12 +519,12 @@ GpgolExtCommands::DoCommand (
          the quoted message and avoids the ugly msgcache. */
       return S_FALSE; /* Pass it on.  */
     }
-  else if (nCommandID == 155)
+  else if (nCommandID == EECMDID_ComposeReplyToAll)
     {
       log_debug ("%s:%s: command ReplyAll called\n", SRCNAME, __func__);
       return S_FALSE; /* Pass it on.  */
     }
-  else if (nCommandID == 156)
+  else if (nCommandID == EECMDID_ComposeForward)
     {
       log_debug ("%s:%s: command Forward called\n", SRCNAME, __func__);
       return S_FALSE; /* Pass it on.  */
@@ -535,18 +574,21 @@ GpgolExtCommands::DoCommand (
            && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
     {
       m_pExchExt->m_gpgEncrypt = !m_pExchExt->m_gpgEncrypt;
+      check_menu (pEECB, m_nCmdEncrypt, m_pExchExt->m_gpgEncrypt);
     }
-  else if (nCommandID == m_nCmdSign
+    else if (nCommandID == m_nCmdSign
            && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
     {
       m_pExchExt->m_gpgSign = !m_pExchExt->m_gpgSign;
+      check_menu (pEECB, m_nCmdSign, m_pExchExt->m_gpgSign);
     }
   else if (nCommandID == m_nCmdKeyManager
            && m_lContext == EECONTEXT_VIEWER)
     {
-      if (start_key_manager ())
-        MessageBox (NULL, _("Could not start certificate manager"),
-                    "GpgOL", MB_ICONERROR|MB_OK);
+      if (engine_start_keymanager ())
+        if (start_key_manager ())
+          MessageBox (NULL, _("Could not start certificate manager"),
+                      "GpgOL", MB_ICONERROR|MB_OK);
     }
   else if (nCommandID == m_nCmdDebug1
            && m_lContext == EECONTEXT_READNOTEMESSAGE)
@@ -572,12 +614,16 @@ GpgolExtCommands::DoCommand (
    commands before the user sees them. This method is called
    frequently and should be written in a very efficient manner. */
 STDMETHODIMP_(VOID) 
-GpgolExtCommands::InitMenu(LPEXCHEXTCALLBACK pEECB
+GpgolExtCommands::InitMenu(LPEXCHEXTCALLBACK eecb
 {
-#if 0
-  log_debug ("%s:%s: context=%s\n",
-             SRCNAME, __func__, ext_context_name (m_lContext));
-#endif
+  HRESULT hr;
+  HMENU menu;
+  
+  hr = eecb->GetMenu (&menu);
+  if (FAILED(hr))
+      return; /* Ooops.  */
+  CheckMenuItem (menu, m_nCmdEncrypt, MF_BYCOMMAND 
+                 | (m_pExchExt->m_gpgSign?MF_CHECKED:MF_UNCHECKED));
 }
 
 
@@ -735,7 +781,7 @@ GpgolExtCommands::QueryHelpText(UINT nCommandID, ULONG lFlags,
 
 /* Called by Exchange to get toolbar button infos.  TOOLBARID is the
    toolbar identifier.  BUTTONID is the toolbar button index.  PTBB is
-   a pointer to toolbar button structure DESCRIPTION is a pointer to
+   a pointer to toolbar button structure DESCRIPTION is a pointer to
    buffer receiving the text for the button.  DESCRIPTION_SIZE is the
    maximum size of DESCRIPTION.  FLAGS are flags which might have the
    EXCHEXT_UNICODE bit set.
@@ -748,75 +794,41 @@ GpgolExtCommands::QueryButtonInfo (ULONG toolbarid, UINT buttonid,
                                    LPTSTR description, UINT description_size,
                                    ULONG flags)          
 {
-  if (buttonid == m_nToolbarButtonID1
-      && m_lContext == EECONTEXT_READNOTEMESSAGE)
-    {
-      pTBB->iBitmap = m_nToolbarBitmap1;             
-      pTBB->idCommand = m_nCmdEncrypt;
-      pTBB->fsState = TBSTATE_ENABLED;
-      pTBB->fsStyle = TBSTYLE_BUTTON;
-      pTBB->dwData = 0;
-      pTBB->iString = -1;
-      lstrcpyn (description,
-                _("Decrypt message and verify signature"),
-                description_size);
-    }
-  else if (buttonid == m_nToolbarButtonID1
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE)
-    {
-      pTBB->iBitmap = m_nToolbarBitmap1;             
-      pTBB->idCommand = m_nCmdEncrypt;
-      pTBB->fsState = TBSTATE_ENABLED;
+  toolbar_info_t tb_info;
+
+  for (tb_info = m_toolbar_info; tb_info; tb_info = tb_info->next )
+    if (tb_info->button_id == buttonid
+        && tb_info->context == m_lContext)
+      break;
+  if (!tb_info)
+    return S_FALSE; /* Not one of our toolbar buttons.  */
+
+  pTBB->iBitmap = tb_info->bitmap;
+  pTBB->idCommand = tb_info->cmd_id;
+  pTBB->fsState = TBSTATE_ENABLED;
+  pTBB->fsStyle = TBSTYLE_BUTTON;
+  pTBB->dwData = 0;
+  pTBB->iString = -1;
+  lstrcpyn (description, tb_info->desc, strlen (tb_info->desc));
+
+  if (tb_info->cmd_id == m_nCmdEncrypt)
+    {
+      pTBB->fsStyle |= TBSTYLE_CHECK;
       if (m_pExchExt->m_gpgEncrypt)
         pTBB->fsState |= TBSTATE_CHECKED;
-      pTBB->fsStyle = TBSTYLE_BUTTON | TBSTYLE_CHECK;
-      pTBB->dwData = 0;
-      pTBB->iString = -1;
-      lstrcpyn (description, _("Encrypt message with GPG"),
-                description_size);
-    }
-  else if (buttonid == m_nToolbarButtonID2
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE)
-    {
-      pTBB->iBitmap = m_nToolbarBitmap2;             
-      pTBB->idCommand = m_nCmdSign;
-      pTBB->fsState = TBSTATE_ENABLED;
+    }
+  else if (tb_info->cmd_id == m_nCmdSign)
+    {
+      pTBB->fsStyle |= TBSTYLE_CHECK;
       if (m_pExchExt->m_gpgSign)
         pTBB->fsState |= TBSTATE_CHECKED;
-      pTBB->fsStyle = TBSTYLE_BUTTON | TBSTYLE_CHECK;
-      pTBB->dwData = 0;
-      pTBB->iString = -1;
-      lstrcpyn (description, _("Sign message with GPG"),
-                description_size);
-    }
-  else if (buttonid == m_nToolbarButtonID3
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE)
-    {
-      pTBB->iBitmap = m_nToolbarBitmap3;             
-      pTBB->idCommand = m_nCmdSelectSmime;
-      pTBB->fsState = TBSTATE_ENABLED;
-      if (m_pExchExt->m_gpgSelectSmime)
-        pTBB->fsState |= TBSTATE_CHECKED;
-      pTBB->fsStyle = TBSTYLE_BUTTON | TBSTYLE_CHECK;
-      pTBB->dwData = 0;
-      pTBB->iString = -1;
-      lstrcpyn (description, _("Use the S/MIME protocol"),
-                description_size);
     }
-  else if (buttonid == m_nToolbarButtonID1
-           && m_lContext == EECONTEXT_VIEWER)
+  else if (tb_info->cmd_id == m_nCmdSelectSmime)
     {
-      pTBB->iBitmap = m_nToolbarBitmap1;             
-      pTBB->idCommand = m_nCmdEncrypt;
-      pTBB->fsState = TBSTATE_ENABLED;
-      pTBB->fsStyle = TBSTYLE_BUTTON;
-      pTBB->dwData = 0;
-      pTBB->iString = -1;
-      lstrcpyn (description, _("Open the certificate manager"),
-                description_size);
+      pTBB->fsStyle |= TBSTYLE_CHECK;
+      if (m_pExchExt->m_gpgSelectSmime)
+        pTBB->fsState |= TBSTATE_CHECKED;
     }
-  else
-    return S_FALSE;
 
   return S_OK;
 }
@@ -829,4 +841,3 @@ GpgolExtCommands::ResetToolbar (ULONG lToolbarID, ULONG lFlags)
   return S_OK;
 }
 
-
index 3a3a829..dbf3e3e 100644 (file)
 #define EXT_COMMANDS_H
 
 
+struct toolbar_info_s;
+typedef struct toolbar_info_s *toolbar_info_t;
+
+
 /*
    GpgolExtCommands 
 
@@ -30,7 +34,8 @@ class GpgolExtCommands : public IExchExtCommands
 {
 public:
   GpgolExtCommands (GpgolExt* pParentInterface);
-  
+  virtual ~GpgolExtCommands (void);
+
 private:
   ULONG m_lRef;
   ULONG m_lContext;
@@ -45,16 +50,14 @@ private:
   UINT  m_nCmdDebug1;
   UINT  m_nCmdDebug2;
 
-  UINT  m_nToolbarButtonID1;
-  UINT  m_nToolbarButtonID2;     
-  UINT  m_nToolbarButtonID3;     
-  UINT  m_nToolbarBitmap1;
-  UINT  m_nToolbarBitmap2;
-  UINT  m_nToolbarBitmap3;
+  /* A list of all active toolbar items.  */
+  toolbar_info_t m_toolbar_info;
   
   HWND  m_hWnd;
   
   GpgolExt* m_pExchExt;
+
+  void add_toolbar (LPTBENTRY tbearr, UINT n_tbearr, ...);
   
 public:
   STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObj);
index cb21652..6fbf80e 100644 (file)
Binary files a/src/key_mana.bmp and b/src/key_mana.bmp differ
index 455ab7d..fa85bfd 100644 (file)
Binary files a/src/logo.bmp and b/src/logo.bmp differ
index 408de42..2ba0b38 100644 (file)
@@ -31,9 +31,6 @@
 #include "mymapi.h"
 
 
-/* Registry key for this software. */
-#define REGKEY "Software\\GNU\\GnuPG"
-
 /* The malloced name of the logfile and the logging stream.  If
    LOGFILE is NULL, no logging is done. */
 static char *logfile;
@@ -441,7 +438,7 @@ get_locale_dir (void)
   char *p;
   char *dname;
 
-  instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY,
+  instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", GNUPG_REGKEY,
                                      "Install Directory");
   if (!instdir)
     return NULL;
index 688e5ef..09a897f 100644 (file)
@@ -62,6 +62,11 @@ struct sink_s
   void *cb_data;
   sink_t extrasink;
   int (*writefnc)(sink_t sink, const void *data, size_t datalen);
+/*   struct { */
+/*     int idx; */
+/*     unsigned char inbuf[4]; */
+/*     int quads; */
+/*   } b64; */
 };
 
 
@@ -115,7 +120,6 @@ check_protocol (protocol_t protocol)
   switch (protocol)
     {
     case PROTOCOL_UNKNOWN:
-      log_error ("fixme: automatic protocol selection is not yet supported");
       return PROTOCOL_UNKNOWN;
     case PROTOCOL_OPENPGP:
     case PROTOCOL_SMIME:
@@ -1343,6 +1347,102 @@ sink_encryption_write (sink_t encsink, const void *data, size_t datalen)
 }
 
 
+#if 0 /* Not used.  */
+/* Sink write method used by mime_encrypt for writing Base64.  */
+static int
+sink_encryption_write_b64 (sink_t encsink, const void *data, size_t datalen)
+{
+  engine_filter_t filter = encsink->cb_data;
+  int rc;
+  const unsigned char *p;
+  unsigned char inbuf[4];
+  int idx, quads;
+  char outbuf[6];
+  size_t outbuflen;
+
+  if (!filter)
+    {
+      log_error ("%s:%s: sink not setup for writing", SRCNAME, __func__);
+      return -1;
+    }
+
+  idx = encsink->b64.idx;
+  assert (idx < 4);
+  memcpy (inbuf, encsink->b64.inbuf, idx);
+  quads = encsink->b64.quads;
+
+  if (!data)  /* Flush. */
+    {
+      outbuflen = 0;
+      if (idx)
+        {
+          outbuf[0] = bintoasc[(*inbuf>>2)&077];
+          if (idx == 1)
+            {
+              outbuf[1] = bintoasc[((*inbuf<<4)&060)&077];
+              outbuf[2] = '=';
+              outbuf[3] = '=';
+            }
+          else 
+            { 
+              outbuf[1] = bintoasc[(((*inbuf<<4)&060)|
+                                    ((inbuf[1]>>4)&017))&077];
+              outbuf[2] = bintoasc[((inbuf[1]<<2)&074)&077];
+              outbuf[3] = '=';
+            }
+          outbuflen = 4;
+          quads++;
+        }
+      
+      if (quads)
+        {
+          outbuf[outbuflen++] = '\r';
+          outbuf[outbuflen++] = '\n';
+        }
+
+      if (outbuflen && (rc = engine_filter (filter, outbuf, outbuflen)))
+        return rc;
+      /* Send the flush command to the filter.  */
+      if ((rc = engine_filter (filter, data, datalen)))
+        return rc;
+    }
+  else
+    {
+      for (p = data; datalen; p++, datalen--)
+        {
+          inbuf[idx++] = *p;
+          if (idx > 2)
+            {
+              idx = 0;
+              outbuf[0] = bintoasc[(*inbuf>>2)&077];
+              outbuf[1] = bintoasc[(((*inbuf<<4)&060)
+                                    |((inbuf[1] >> 4)&017))&077];
+              outbuf[2] = bintoasc[(((inbuf[1]<<2)&074)
+                                    |((inbuf[2]>>6)&03))&077];
+              outbuf[3] = bintoasc[inbuf[2]&077];
+              outbuflen = 4;
+              if (++quads >= (64/4)) 
+                {
+                  quads = 0;
+                  outbuf[4] = '\r';
+                  outbuf[5] = '\n';
+                  outbuflen += 2;
+                }
+              if ((rc = engine_filter (filter, outbuf, outbuflen)))
+                return rc;
+            }
+        }
+    }
+
+  encsink->b64.idx = idx;
+  memcpy (encsink->b64.inbuf, inbuf, idx);
+  encsink->b64.quads = quads;
+  
+  return 0;
+}
+#endif /*Not used.*/
+
+
 /* Encrypt the MESSAGE.  */
 int 
 mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
@@ -1364,12 +1464,6 @@ mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
   memset (sink, 0, sizeof *sink);
   memset (encsink, 0, sizeof *encsink);
 
-  protocol = check_protocol (protocol);
-  if (protocol == PROTOCOL_UNKNOWN)
-    return -1;
-
-  /* FIXME For now only PGP/MIME is supported.  */
-
   attach = create_mapi_attachment (message, sink);
   if (!attach)
     return -1;
@@ -1379,7 +1473,11 @@ mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
      will fail early. */
   if (engine_create_filter (&filter, write_buffer_for_cb, sink))
     goto failure;
-  if (engine_encrypt_start (filter, protocol, recipients))
+  if (engine_encrypt_start (filter, protocol, recipients, &protocol))
+    goto failure;
+
+  protocol = check_protocol (protocol);
+  if (protocol == PROTOCOL_UNKNOWN)
     goto failure;
 
   /* Get the attachment info and the body.  */
@@ -1398,32 +1496,50 @@ mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
     }
 
   /* Write the top header.  */
-  generate_boundary (boundary);
-  if ((rc=write_multistring (sink,
-                             "MIME-Version: 1.0\r\n"
-                             "Content-Type: multipart/encrypted;\r\n"
-                             "\tprotocol=\"application/pgp-encrypted\";\r\n",
-                             "\tboundary=\"", boundary, "\"\r\n",
-                             NULL)))
-    goto failure;
-
-  /* Write the PGP/MIME encrypted part.  */
-  if ((rc = write_boundary (sink, boundary, 0)))
-    goto failure;
-  if ((rc=write_multistring (sink,
-                             "Content-Type: application/pgp-encrypted\r\n"
-                             "\r\n"
-                             "Version: 1\r\n",
-                             NULL)))
+  if (protocol == PROTOCOL_SMIME)
+    {
+      *boundary = 0;
+      rc = write_multistring (sink,
+                              "MIME-Version: 1.0\r\n"
+                              "Content-Type: application/pkcs7-mime;\r\n"
+                              "\tsmime-type=enveloped-data;\r\n"
+                              "\tname=\"smime.p7m\"\r\n"
+                              "Content-Transfer-Encoding: base64\r\n",
+                              NULL);
+    }
+  else
+    {
+      generate_boundary (boundary);
+      rc = write_multistring (sink,
+                              "MIME-Version: 1.0\r\n"
+                              "Content-Type: multipart/encrypted;\r\n"
+                              "\tprotocol=\"application/pgp-encrypted\";\r\n",
+                              "\tboundary=\"", boundary, "\"\r\n",
+                              NULL);
+    }
+  if (rc)
     goto failure;
 
-  /* And start the second part.  */
-  if ((rc = write_boundary (sink, boundary, 0)))
-    goto failure;
-  if ((rc=write_multistring (sink,
-                             "Content-Type: application/octet-stream\r\n"
-                             "\r\n", NULL)))
-    goto failure;
+  if (protocol == PROTOCOL_OPENPGP)
+    {
+      /* Write the PGP/MIME encrypted part.  */
+      if ((rc = write_boundary (sink, boundary, 0)))
+        goto failure;
+      if ((rc=write_multistring (sink,
+                                 "Content-Type: application/pgp-encrypted\r\n"
+                                 "\r\n"
+                                 "Version: 1\r\n",
+                                 NULL)))
+        goto failure;
+      
+      /* And start the second part.  */
+      if ((rc = write_boundary (sink, boundary, 0)))
+        goto failure;
+      if ((rc=write_multistring (sink,
+                                 "Content-Type: application/octet-stream\r\n"
+                                 "\r\n", NULL)))
+        goto failure;
+    }
 
   /* Create a new sink for encrypting the following stuff.  */
   encsink->cb_data = filter;
@@ -1467,10 +1583,10 @@ mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
   filter = NULL; /* Not valid anymore.  */
   encsink->cb_data = NULL; /* Not needed anymore.  */
   
-  /* Write the final boundary and finish the attachment.  */
-  if ((rc = write_boundary (sink, boundary, 1)))
+  /* Write the final boundary (for OpenPGP) and finish the attachment.  */
+  if (*boundary && (rc = write_boundary (sink, boundary, 1)))
     goto failure;
-
+  
   if (close_mapi_attachment (&attach, sink))
     goto failure;
 
index 457d060..876e041 100644 (file)
@@ -69,8 +69,15 @@ extern "C" {
 
 
 /* Command IDs. */
+#define EECMDID_Format                         110
+#define EECMDID_FormatFont                     111
+#define EECMDID_FormatParagraph                112
+#define EECMDID_Tools                          120
 #define EECMDID_ToolsCustomizeToolbar          134
 #define EECMDID_ToolsOptions                   136
+#define EECMDID_ComposeReplyToSender           154
+#define EECMDID_ComposeReplyToAll              155
+#define EECMDID_ComposeForward                 156
 
 
 /* Flag values for IExchExtAttachedFileEvents::OpenSzFile. */
index 2e5fae9..9de36fd 100644 (file)
@@ -80,26 +80,31 @@ GPGOptionsDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
     {
     case WM_INITDIALOG:
       {
-        HDC hdc = GetDC (hDlg);
-        if (hdc)
-          {
-            int bits_per_pixel = GetDeviceCaps (hdc, BITSPIXEL);
-            HBITMAP bitmap;
+        /* We don't use this anymore.  Actually I don't know why we
+           used it at all.  Note that this unused code has been
+           converted to use LoadImage instead of LoadBitmap. */
+/*         HDC hdc = GetDC (hDlg); */
+/*         if (hdc) */
+/*           { */
+/*             int bits_per_pixel = GetDeviceCaps (hdc, BITSPIXEL); */
+/*             HANDLE bitmap; */
                 
-            ReleaseDC (hDlg, hdc);     
-            if (bits_per_pixel > 15)
-              {
-                bitmap = LoadBitmap (glob_hinst, MAKEINTRESOURCE(IDB_BANNER));
-                if (bitmap)
-                  {
-                    HBITMAP old = (HBITMAP) SendDlgItemMessage
-                      (hDlg, IDC_BITMAP, STM_SETIMAGE,
-                       IMAGE_BITMAP, (LPARAM)bitmap);
-                    if (old)
-                      DeleteObject (old);      
-                  }    
-              }                
-          }
+/*             if (bits_per_pixel > 15) */
+/*               { */
+/*                 bitmap = LoadImage (glob_hinst, MAKEINTRESOURCE(IDB_BANNER), */
+/*                                     IMAGE_BITMAP, 0, 0, */
+/*                                     LR_CREATEDIBSECTION | LR_LOADTRANSPARENT); */
+/*                 if (bitmap) */
+/*                   { */
+/*                     HBITMAP old = (HBITMAP) SendDlgItemMessage */
+/*                       (hDlg, IDC_BITMAP, STM_SETIMAGE, */
+/*                        IMAGE_BITMAP, (LPARAM)bitmap); */
+/*                     if (old) */
+/*                       DeleteObject (old);    */
+/*                   }  */
+/*               }              */
+/*             ReleaseDC (hDlg, hdc);   */
+/*           } */
         
        EnableWindow (GetDlgItem (hDlg, IDC_ENCRYPT_TO),
                       !!opt.enable_default_key);
index 08b2550..ad78a7f 100644 (file)
Binary files a/src/sign.bmp and b/src/sign.bmp differ