Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F26766110
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
230 KB
Subscribers
None
View Options
diff --git a/po/de.po b/po/de.po
index b630a48..1be885b 100644
--- a/po/de.po
+++ b/po/de.po
@@ -1,1015 +1,1019 @@
# de.po - German translation for GpgOL
# Copyright (C) 2005, 2007 g10 Code GmbH
# This file is distributed under the same license as the GpgOL package.
# Werner Koch <wk@gnupg.org>, 2005, 2007.
#
msgid ""
msgstr ""
"Project-Id-Version: GpgOL 0.10.0\n"
"Report-Msgid-Bugs-To: bug-gpgol@g10code.com\n"
-"POT-Creation-Date: 2008-10-27 15:56+0100\n"
-"PO-Revision-Date: 2008-10-27 17:17+0100\n"
+"POT-Creation-Date: 2008-10-27 18:31+0100\n"
+"PO-Revision-Date: 2008-10-27 18:32+0100\n"
"Last-Translator: Werner Koch <wk@gnupg.org>\n"
"Language-Team: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/attached-file-events.cpp:58
msgid "Error creating file for attachment."
msgstr "Fehler bei der Erstellung der Datei für das Attachment."
#: src/attached-file-events.cpp:71
msgid "Error reading attachment."
msgstr "Fehler beim Lesen des Attachments."
#: src/attached-file-events.cpp:82 src/attached-file-events.cpp:95
msgid "Error writing attachment."
msgstr "Fehler beim Schreiben des Attachments."
#: src/attached-file-events.cpp:216
msgid ""
"Sorry, we are not able to decrypt this attachment.\n"
"\n"
"Please use the decrypt/verify button to decrypt the\n"
"entire message again. Then open this attachment."
msgstr ""
"Es ist leider nicht mehr möglich, diese Attachment zu öffnen.\n"
"\n"
"Bitten benutzen Sie den \"Entschlüsseln/Verifizieren\" Menüpunkt\n"
"um die gesamte Nachricht nochmal zu entschlüsseln. Danach können\n"
"Sie das Attachment wieder öffenen."
#: src/common.c:216
msgid "GpgOL - Save decrypted attachment"
msgstr "GpgOL - Sichern der entschlüsselten Anlage"
#: src/config-dialog.c:137
msgid "Debug output (for analysing problems)"
msgstr "Debugausgabe (zur Problemanalyse)"
#: src/engine.c:429
msgid ""
"The user interface server is not available or does not work. Using an "
"internal user interface.\n"
"\n"
"This is limited to the PGP/MIME protocol and thus S/MIME protected message "
"are not readable."
msgstr ""
"Achtung: Die GnuPG Benutzeroberfläche \"Kleopatra\" konnte nicht gefunden "
"werden.\n"
"\n"
"Um GpgOL zu nutzen probieren Sie bitte eine der folgenden Möglichkeiten "
"aus:\n"
"\n"
"1. Entweder: Outlook beenden und erneut starten.\n"
"\n"
"2. Oder: Outlook beenden. Dann \"Kleopatra\" aus dem Startmenü\n"
" (unter \"GnuPG für Windows\") oder auf einem anderen Weg starten.\n"
" Sobald \"Kleopatra\" läuft, erneut Outlook starten."
#: src/engine.c:433 src/ext-commands.cpp:774 src/ext-commands.cpp:795
#: src/ext-commands.cpp:800 src/main.c:682 src/main.c:688 src/message.cpp:320
msgid "GpgOL"
msgstr "GpgOL"
#: src/engine-gpgme.c:368
msgid ""
"The configured default encryption certificate is not available or does not "
"unambigiously specify one. Please fix this in the option dialog.\n"
"\n"
"This message won't be be encrypted to this certificate!"
msgstr ""
"Das voreingestellte zusätzliche Zertifikat zum Verschlüsseln ist nicht\n"
"vorhanden oder nicht eindeutig. Bitte beheben Sie dies in den\n"
"Optionseinstellungen.\n"
"\n"
"Die Nachricht wird deswegen nicht für dieses Zertifikat verschlüsselt!"
#: src/engine-gpgme.c:372
msgid "Encryption"
msgstr "Verschlüsselung"
#: src/engine-gpgme.c:788
msgid "Fingerprint: "
msgstr "Fingerabdruck: "
#: src/engine-gpgme.c:845
msgid "This signature is valid\n"
msgstr "Diese Unterschrift ist korrekt\n"
#: src/engine-gpgme.c:847
msgid "signature state is \"green\"\n"
msgstr "Status der Unterschrift ist \"grün\"\n"
#: src/engine-gpgme.c:849
msgid "signature state is \"red\"\n"
msgstr "Status der Unterschrift ist \"rot\"\n"
#: src/engine-gpgme.c:853
msgid "Warning: One of the certificates has been revoked\n"
msgstr "Warnung: Eines der Zertifikate wurde widerrufen\n"
#: src/engine-gpgme.c:863
msgid "Warning: The certificate used to create the signature expired at: "
msgstr ""
"Warnung: Das Zertifikat mit der diese Unterschrift erzeugt wurde verfiel am: "
#: src/engine-gpgme.c:869
msgid "Warning: At least one certification certificate has expired\n"
msgstr ""
"Warnung: Mindestens eines der Zertifizierungs-Zertifikate ist abgelaufen\n"
#: src/engine-gpgme.c:875
msgid "Warning: The signature expired at: "
msgstr "Die Unterschrift verfiel am: "
#: src/engine-gpgme.c:881
msgid "Can't verify due to a missing certificate\n"
msgstr ""
"Aufrund eines fehlenden Zertifikats ist eine Überprüfung nicht möglich\n"
#: src/engine-gpgme.c:885
msgid "The CRL is not available\n"
msgstr "Die CRL ist nicht verfügbar\n"
#: src/engine-gpgme.c:891
msgid "Available CRL is too old\n"
msgstr "Die vorhandene CRL ist zu alt\n"
#: src/engine-gpgme.c:896
msgid "A policy requirement was not met\n"
msgstr "Eine Richtlinie wurde nicht erfüllt\n"
#: src/engine-gpgme.c:902
msgid "A system error occured"
msgstr "Ein Systemfehler ist aufgetreten"
#: src/engine-gpgme.c:939
msgid ""
"WARNING: We have NO indication whether this certificate belongs to the "
"person named as shown above\n"
msgstr ""
"WARNUNG: Es gibt keinen Hinweis darauf, ob dieses Zertifikat wirklich der "
"Person gehört, die oben angezeigt ist\n"
#: src/engine-gpgme.c:946
msgid ""
"WARNING: The certificate does NOT BELONG to the person named as shown above\n"
msgstr ""
"WARNUNG: Das Zertifikat gehört NICHT der Person die oben angezeigt ist\n"
#: src/engine-gpgme.c:950
msgid ""
"WARNING: It is NOT certain that the certificate belongs to the person named "
"as shown above\n"
msgstr ""
"WARNING: Es ist nicht sicher, daß das Zertifikat der Person gehört, die oben "
"angezeigt ist\n"
#: src/engine-gpgme.c:983
msgid "Verification started at: "
msgstr "Überprüfung begann am: "
#: src/engine-gpgme.c:988
msgid "Verification result for: "
msgstr "Prüfungsresultat für: "
#: src/engine-gpgme.c:989
msgid "[unnamed part]"
msgstr "[Unbenannter Teil]"
#: src/engine-gpgme.c:1007 src/engine-gpgme.c:1037
msgid "Good signature from: "
msgstr "Korrekte Unterschrift von: "
#: src/engine-gpgme.c:1014
msgid " aka: "
msgstr " alias: "
#: src/engine-gpgme.c:1018 src/engine-gpgme.c:1040
msgid " created: "
msgstr " erzeugt: "
#: src/engine-gpgme.c:1027
msgid "*BAD* signature claimed to be from: "
msgstr "*FALSCHE* Unterschrift, vorgeblich von: "
#: src/engine-gpgme.c:1050
msgid "Error checking signature"
msgstr "Fehler beim Prüfen der Unterschrift"
#: src/engine-gpgme.c:1066
msgid "*** Begin Notation (signature by: "
msgstr "*** Anfang Notation (Unterschrift von: "
#: src/engine-gpgme.c:1086
msgid "*** End Notation ***\n"
msgstr "*** Ende Notation ***\n"
#: src/ext-commands.cpp:533
msgid "GpgOL Decrypt/Verify"
msgstr "GpgOL Enschlüsseln/Prüfen"
#: src/ext-commands.cpp:547
msgid ""
"This is a signed and encrypted message.\n"
"Click for more information. "
msgstr ""
"Dies ist eine unterschriebene und verschlüsselte Nachricht.\n"
"Klicken Sie hier um weitere Informationen zu erhalten. "
#: src/ext-commands.cpp:550
msgid ""
"This is an encrypted message.\n"
"Click for more information. "
msgstr ""
"Dies ist eine verschlüsselte Nachricht.\n"
"Klicken Sie hier um weitere Informationen zu erhalten. "
#: src/ext-commands.cpp:552
msgid ""
"This is a signed message.\n"
"Click for more information. "
msgstr ""
"Dies ist eine unterschriebene Nachricht.\n"
"Klicken Sie hier um weitere Informationen zu erhalten. "
#: src/ext-commands.cpp:562
msgid ">GnuPG protocol"
msgstr ">GnuPG Protokoll"
#: src/ext-commands.cpp:563
msgid "auto"
msgstr "automatisch"
#: src/ext-commands.cpp:564
msgid "PGP/MIME"
msgstr "PGP/MIME"
#: src/ext-commands.cpp:565
msgid "S/MIME"
msgstr "S/MIME"
#: src/ext-commands.cpp:567
msgid "&encrypt message with GnuPG"
msgstr "Nachricht verschlüsseln"
#: src/ext-commands.cpp:568
msgid "&sign message with GnuPG"
msgstr "Nachricht unterschreiben"
#: src/ext-commands.cpp:603
msgid "GnuPG Certificate &Manager"
msgstr "GnuPG Zertifikats&verwaltung"
#: src/ext-commands.cpp:604
msgid "Remove GpgOL flags from this folder"
msgstr "GpgOL Eigenschaften aus diesem Ordner entfernen"
#: src/ext-commands.cpp:608
msgid "Open the certificate manager"
msgstr "Die Zertifikatsverwaltung öffnen"
#: src/ext-commands.cpp:744
msgid ""
"Support for S/MIME has not been enabled.\n"
"\n"
"To enable S/MIME support, open the option dialog and check \"Enable the S/"
"MIME support\". The option dialog can be found in the main menu at: Extras-"
">Options->GpgOL.\n"
msgstr ""
"Unterstützung für S/MIME ist nicht eingeschaltet.\n"
"\n"
"Um die S/MIME Unterstützung einzuschalten, öffnen Sie bitte das Fenster mit "
"den Einstellungen um dort die Option \"S/MIME Unterstützung einschalten\" zu "
"aktivieren. Sie finden die Einstellungen im Hauptmenu unter: Extras-"
">Optionen->GpgOL.\n"
#: src/ext-commands.cpp:773
msgid "Could not start certificate manager"
msgstr "Die Zertifikatsverwaltung konnte nicht aufgerufen werden"
#: src/ext-commands.cpp:785
msgid ""
"You are about to start the process of reversing messages created by GpgOL to "
"prepare deinstalling of GpgOL. Running this command will put GpgOL into a "
"disabled state so that messages are not anymore processed by GpgOL.\n"
"\n"
"You should convert all folders one after the other with this command, close "
"Outlook and then deinstall GpgOL.\n"
"\n"
"Note that if you start Outlook again with GpgOL still being installed, GpgOL "
"will again process messages."
msgstr ""
"Sie sind dabei, eine Deinstallation von GpgOL vorzubereiten. Hierzu wird "
"GpgOL ausgechaltet, so das Nachrichten nicht mehr durch GpgOL angezeigt "
"werden.\n"
"\n"
"Sie sollten nacheinander dieses Kommandos für alle Ordner aufrufen, danach "
"Outlook schliessen und GpgOL deinstallieren.\n"
"\n"
"Bitte beachten Sie, daß nach einem erneuten Start von Outlook - mit "
"weiterhin installiertem GpgOL - Nachrichten wieder wie gewohnt von GpgOL "
"angezeigt werden."
#: src/ext-commands.cpp:799
msgid "Do you want to revert this folder?"
msgstr "Möchten Sie diesen Ordner von GpgOL befreien?"
#: src/ext-commands.cpp:901
msgid "Select this option to automatically select the protocol."
msgstr "Wählen Sie diese Option zum das Protokoll automatisch auszuwählen."
#: src/ext-commands.cpp:908
msgid "Select this option to select the PGP/MIME protocol."
msgstr "Wählen Sie diese Option zum das PGP/MIME Protokoll auszuwählen."
#: src/ext-commands.cpp:915
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:922
msgid "Select this option to encrypt the message."
msgstr "Wählen Sie diese Option zum Verschlüsseln der Nachricht."
#: src/ext-commands.cpp:929
msgid "Select this option to sign the message."
msgstr "Wählen Sie diese Option zum Unterschreiben der Nachricht."
#: src/ext-commands.cpp:936
msgid "Select this option to open the certificate manager"
msgstr "Wählen Sie diese Option zum die Zertifikatsverwaltung zu öffenen."
#: src/ext-commands.cpp:966
msgid "Automatically select the protocol for sign/encrypt"
msgstr "Wählen Sie diese Option um das Protokoll automatisch auszuwählen."
#: src/ext-commands.cpp:976
msgid "Use PGP/MIME for sign/encrypt"
msgstr "PGP/MIME zum signieren/verschlüsseln verwenden."
#: src/ext-commands.cpp:986
msgid "Use S/MIME for sign/encrypt"
msgstr "S/MIME zum signieren/verschlüsseln verwenden."
#: src/ext-commands.cpp:996
msgid "Encrypt message with GnuPG"
msgstr "Nachricht verschlüsseln"
#: src/ext-commands.cpp:1006
msgid "Sign message with GnuPG"
msgstr "Nachricht unterschreiben"
#: src/ext-commands.cpp:1016
msgid "Open the GpgOL certificate manager"
msgstr "Zertifikatsverwaltung von GpgOL öffnen"
#: src/main.c:681
#, c-format
msgid "Note: Using compatibility flags: %s"
msgstr "Notiz: Diese Kompatibilitätsflags werden verwendet: %s"
#: src/main.c:687
#, c-format
msgid ""
"Note: Writing debug logs to\n"
"\n"
"\"%s\""
msgstr ""
"Notiz: Debug-Logausgaben werden nach\n"
"\n"
"\"%s\"\n"
"\n"
"geschrieben."
#: src/mapihelp.cpp:1468 src/mapihelp.cpp:1476 src/mapihelp.cpp:1484
msgid "[no subject]"
msgstr "[Kein Betreff]"
#: src/mapihelp.cpp:2093
msgid ""
"[The content of this message is not visible because it has been decrypted by "
"another Outlook session. Use the \"decrypt/verify\" command to make it "
"visible]"
msgstr ""
"[Der Inhalt dieser Nachricht ist nicht sichtbar, da sie in einer anderen "
"Outlook Sitzung entschlüsselt wurde. Verwenden Sie den Menüpunkt "
"\"entschlüsseln/verifizieren\" um den Inhalt wieder sichtbar zu machen.]"
#: src/mapihelp.cpp:2870
msgid ""
"[The content of this message is not visible due to an processing error in "
"GpgOL.]"
msgstr ""
"[Aufgrund eines Verarbeitungsfehlers in GpgOL ist der Inhalt dieser "
"Nachricht nicht sichtbar.]"
#: src/message-events.cpp:320
msgid ""
"Sorry, we can only encrypt plain text messages and\n"
"no RTF messages. Please make sure that only the text\n"
"format has been selected."
msgstr ""
"Leider ist es nur möglich reine Textnachrichten aber keine\n"
"Nachrichten im RTF Format zu verschlüsseln. Bitte stellen \n"
"Sie sicher, daß lediglich das Text Format ausgewählt wurde.\n"
"(In der Menüleiste: \"Format\" => \"Nur Text\")"
#: src/message.cpp:192
msgid "[Crypto operation failed - can't show the body of the message]"
msgstr ""
"[Krypto-Operation ist fehlgeschlagen - Der Text der Nachricht kann nicht "
"angezeigt werden.]"
#: src/message.cpp:300
#, c-format
msgid ""
"Signature status: %s\n"
"Message class ..: %s\n"
"MIME structure .:\n"
"%s"
msgstr ""
"Status der Unterschrift: %s\n"
"Nachrichtenklasse .....: %s\n"
"Struktur der Nachricht :\n"
"%s"
#: src/message.cpp:308
msgid "GpgOL - Message Information"
msgstr "GpgOL - Informationen zu der Nachricht"
#: src/message.cpp:538
msgid "Signature verification of an encrypted message is not possible."
msgstr ""
"Die Prüfung der Unterschrift ist bei einer verschlüsselten Nachrichten nicht "
"möglich."
#: src/message.cpp:549
msgid "Signature verification of this message class is not possible."
msgstr ""
"Die Prüfung der Unterschrift ist bei dieser Nachrichtenklasse nicht möglich."
#: src/message.cpp:552
msgid ""
"Signature verification of this S/MIME message is not possible. Please check "
"that S/MIME processing has been enabled."
msgstr ""
"Die Prüfung der Unterschrift ist bei dieser S/MIME Nachricht nicht möglich. "
"Bitte überprüfen Sie in den Einstellungen, daß die Verarbeitung von S/MIME "
"eingeschaltet ist."
#: src/message.cpp:556
msgid "This message has no signature."
msgstr "Diese Nachricht hat keine Unterschrift."
#: src/message.cpp:854
msgid "This message is not encrypted."
msgstr "Diese Nachricht ist nicht verschlüsselt."
#: src/message.cpp:1081
#, c-format
msgid ""
"Decryption failed\n"
"(%s)"
msgstr ""
"Entschlüsselungsfehler\n"
"(%s)"
#: src/message.cpp:1228
msgid "No recipients to encrypt to are given"
msgstr "Empfänger zum Verschlüsseln wurde nicht angegeben"
-#: src/message.cpp:1244
+#: src/message.cpp:1241 src/message.cpp:1268
+msgid "Encrypting or signing an empty message is not possible."
+msgstr "Eine leere Nachricht kann nicht signiert oder verschlüsselt werden."
+
+#: src/message.cpp:1250
#, c-format
msgid "Encryption failed (%s)"
msgstr "Verschlüsselungsfehler (%s)"
-#: src/message.cpp:1265
+#: src/message.cpp:1277
#, c-format
msgid "Signing failed (%s)"
msgstr "Unterschrifterstellungsfehler (%s)"
#: src/mimeparser.c:1166
msgid "Error writing to stream"
msgstr "Dateischreibfehler"
#: src/mimeparser.c:1167
msgid "I/O-Error"
msgstr "Ein-/Ausgabefehler"
#: src/olflange-dlgs.cpp:44
msgid "General"
msgstr "Allgemein"
#: src/olflange-dlgs.cpp:45
msgid "Enable the S/MIME support"
msgstr "S/MIME Unterstützung einschalten"
#: src/olflange-dlgs.cpp:47
msgid "Message sending"
msgstr "Senden von Nachrichten"
#: src/olflange-dlgs.cpp:48
msgid "&Encrypt new messages by default"
msgstr "Neue Nachrichten per Voreinstellung verschlüsseln"
#: src/olflange-dlgs.cpp:49
msgid "&Sign new messages by default"
msgstr "Neue Nachrichten per Voreinstellung signieren"
#: src/olflange-dlgs.cpp:50
msgid "Use PGP/MIME by default"
msgstr "PGP/MIME per Voreinstellung verwenden"
#: src/olflange-dlgs.cpp:51
msgid "Use S/MIME by default"
msgstr "S/MIME per Voreinstellung verwenden"
#: src/olflange-dlgs.cpp:53
msgid "Message receiving"
msgstr "Lesen von Nachrichten"
#: src/olflange-dlgs.cpp:54
msgid "Also decrypt in preview window"
msgstr "Auch im Vorschaufenster entschlüsseln"
#: src/olflange-dlgs.cpp:55
msgid "Show HTML view if possible"
msgstr "HTML Darstellung anzeigen wenn möglich"
#: src/olflange-dlgs.cpp:56
msgid "Present encrypted message as attachment"
msgstr "Verschlüsselte Nachricht als Anlage anzeigen"
#: src/olflange-dlgs.cpp:59
msgid "Crypto Engine"
msgstr "Kryptoserver"
#: src/olflange-dlgs.cpp:216
msgid ""
"You have enabled GpgOL's support for the S/MIME protocol.\n"
"\n"
"New S/MIME messages are thus only viewable with GpgOL and not anymore with "
"Outlook's internal S/MIME support. Those message will even be unreadable by "
"Outlook after GpgOL has been deinstalled. A tool to mitigate this problem "
"will be provided when GpgOL arrives at production quality status."
msgstr ""
"Sie haben die S/MIME Unterstützung von GpgOL eingeschaltet.\n"
"\n"
"Neue S/MIME Nachrichten werden jetzt nur noch mittels GpgOL sichtbar sein "
"und nicht mehr über Outlooks interne S/MIME Unterstützung. Diese "
"Nachrichten werden auch dann nicht mehr mit Outlook lesbar sein, wenn GpgOL "
"deinstalliert wurde. Mit dem Erscheinen der endgültigen Version von GpgOL "
"wird aber ein Werkzeug bereitgestellt werden, welches dieses Problem lösen "
"kann."
#. TRANSLATORS: See the source for the full english text.
#: src/olflange-dlgs.cpp:272
msgid "-#GpgOLFullHelpText#-"
msgstr ""
"GpgOL ist ein Plugin für Microsoft Outlook, welches es ermöglicht\n"
"Nachrichten mittels der Internet-Standards PGP/MIME oder S/MIME\n"
"zu verschlüsseln und digital zu signieren. Im Hintergrund wird\n"
"dazu die GnuPG Software (<http://www.gnupg.org/>) benutzt.\n"
"Aktuelle Informationen zu GpgOL erhalten Sie durch eine Mausklick\n"
"auf das Firmenlogo.\n"
"\n"
"GpgOL ist Freie Software. Sie können es unter den Bedingungen\n"
"der GNU Lesser General Public License, wie von der Free Software\n"
"Foundation veröffentlicht, weitergeben und/oder modifizieren;\n"
"entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Wahl)\n"
"jeder späteren Version.\n"
"\n"
"GpgOL wird in der Hoffnung veröffentlicht, daß es Ihnen von Nutzen\n"
"sein wird, aber ohne irgendeine Garantie, sogar ohne die implizite\n"
"Garantie der Marktreife oder der Verwendbarkeit für einen bestimmten\n"
"Zweck. Details finden Sie in der GNU Lesser General Public License.\n"
"\n"
"Zusammen mit GpgOL sollten Sie eine Kopie der GNU Lesser General\n"
"Public License erhalten haben. Falls nicht, finden Sie diese\n"
"unter der Webadresse <http://www.gnu.org/licenses/>."
#: src/olflange-dlgs.cpp:278
#, c-format
msgid "This is GpgOL version %s"
msgstr "Dies ist GpgOL Version %s"
#: src/olflange.cpp:435
msgid ""
"You have installed a new version of GpgOL.\n"
"\n"
"Please open the option dialog and confirm that the settings are correct for "
"your needs. The option dialog can be found in the main menu at: Extras-"
">Options->GpgOL.\n"
msgstr ""
"Eine neue Version von GpgOL ist installiert worden.\n"
"\n"
"Bitte öffnen Sie das Fenster mit den Einstellungen und bestätigen Sie, daß "
"die die Einstellungen für Sie noch stimmen. Sie finden die Einstellungen im "
"Hauptmenu unter: Extras->Optionen->GpgOL.\n"
#: src/olflange.cpp:619
msgid ""
"This version of Outlook is too old!\n"
"\n"
"At least versions of Outlook 2003 older than SP2 exhibit crashes when "
"sending messages and messages might get stuck in the outgoing queue.\n"
"\n"
"Please update at least to SP2 before trying to send a message"
msgstr ""
"Diese Version von Outlook ist zu alt!\n"
"\n"
"Einige Versionen von Outlook 2003, älter als SP2, verursachen\n"
"Programmabrüche beim Senden von Nachrichten und diese Nachrichten\n"
"können dabei in der Ausgabewarteschlange stecken bleiben.\n"
"\n"
"Bitte updaten Sie auf SP2 bevor Sie versuchen eine Nachricht zu versenden."
#: src/passphrase-dialog.c:85
msgid "No certificate hint given."
msgstr "Kein Hinweis auf das Zertifikat"
#: src/passphrase-dialog.c:313 src/passphrase-dialog.c:464
msgid "Enter passphrase to unlock the secret key"
msgstr "Passphrase um geheimen Schlüssel zu entsperren"
#: src/passphrase-dialog.c:314 src/passphrase-dialog.c:465
msgid "Hide typing"
msgstr "&Eingabe ausblenden"
#: src/passphrase-dialog.c:315 src/passphrase-dialog.c:466
#: src/recipient-dialog.c:385
msgid "&Cancel"
msgstr "&Abbrechen"
#: src/passphrase-dialog.c:350 src/passphrase-dialog.c:499
msgid "Invalid passphrase; please try again..."
msgstr "Ungültige Passphrase; bitte nochmal versuchen..."
#: src/passphrase-dialog.c:379
msgid "Select Signing Key"
msgstr "Signaturschlüssel auswählen"
#: src/passphrase-dialog.c:463
msgid "Encrypted to the following certificates:"
msgstr "Verschlüsselt für diese Zertifikate:"
#: src/recipient-dialog.c:88
msgid "Name"
msgstr "Name"
#: src/recipient-dialog.c:93
msgid "E-Mail"
msgstr "E-Mail"
#: src/recipient-dialog.c:98
msgid "Key-Info"
msgstr "Key-Info"
#: src/recipient-dialog.c:103
msgid "Key ID"
msgstr "Key-ID"
#: src/recipient-dialog.c:108
msgid "Validity"
msgstr "Gültigkeit"
#: src/recipient-dialog.c:383
msgid "Selected recipients:"
msgstr "Ausgewählte Empfänger:"
#: src/recipient-dialog.c:384
msgid "Recipient which were NOT found"
msgstr "Empfänger die NICHT gefunden wurden:"
#: src/recipient-dialog.c:444
msgid "Please select at least one recipient certificate."
msgstr "Bitte wählen Sie mindestens ein Empfängerzertifikat."
#: src/recipient-dialog.c:445
msgid "Recipient Dialog"
msgstr "Auswahl des Empfängerschlüssels"
#: src/verify-dialog.c:124
msgid "BAD signature!"
msgstr "FALSCHE Unterschrift!"
#: src/verify-dialog.c:126
msgid "Good signature"
msgstr "Korrekte Unterschrift"
#: src/verify-dialog.c:128
msgid "Good signature from revoked certificate"
msgstr "Korrekte Unterschrift; aber Zertifikat wurde widerrufen"
#: src/verify-dialog.c:130
msgid "Good signature from expired certificate"
msgstr "Korrekte Unterschrift; allerdings ist das Zertifikat abgelaufen"
#: src/verify-dialog.c:132
msgid "Good expired signature"
msgstr "Korrekte aber abgelaufene Unterschrift"
#: src/verify-dialog.c:135
msgid "Could not check signature: missing certificate"
msgstr "Unterschrift konnte nicht geprüft werden: Zertifikat fehlt"
#: src/verify-dialog.c:139
msgid "Verification error"
msgstr "Überprüfungsfehler"
#: src/verify-dialog.c:156
msgid "User-ID not found"
msgstr "User-ID nicht gefunden"
#: src/verify-dialog.c:168
msgid "This may be due to a wrong option setting"
msgstr "Möglicherweise durch falsche Einstellungen verursacht"
#: src/verify-dialog.c:174
#, c-format
msgid "Signature expired on %s"
msgstr "Unterschrift abgelaufen am %s"
#: src/verify-dialog.c:186
msgid "Signature issued by a certificate we do NOT trust."
msgstr "Die Unterschrift stammt von einem Zertifikat dem wir NICHT vertrauen."
#: src/verify-dialog.c:193
msgid "Signature issued by a non-valid certificate."
msgstr "Die Unterschrift stammt von einem ungültigen Zertifikat."
#: src/verify-dialog.c:209
msgid "Signature made"
msgstr "Signatur erstellt"
#: src/verify-dialog.c:210
msgid "using"
msgstr "mit"
#: src/verify-dialog.c:211
msgid "cert-ID"
msgstr "Key-Id"
#: src/verify-dialog.c:212
msgid "from"
msgstr "von"
#: src/verify-dialog.c:213
msgid "also known as"
msgstr "auch bekannt als"
#: src/verify-dialog.c:244
msgid "PGP/MIME Verification Result"
msgstr "PGP/MIME Prüfungsresultat"
#: src/verify-dialog.c:247
msgid "S/MIME Verification Result"
msgstr "S/MIME Prüfungsresultat"
#~ msgid "&Decrypt and verify message"
#~ msgstr "Entschlüsseln/Prüfen der Nachricht"
#~ msgid "&Verify signature"
#~ msgstr "&Unterschrift prüfen"
#~ 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."
#~ msgid "Check the signature now and display the result"
#~ msgstr "Die digitale Unterschrift jetzt prüfen und das Resultat anzeigen"
#~ msgid "Path to certificate manager binary"
#~ msgstr "Dateiname der Zertifikatsverwaltung"
#~ msgid "Select Certificate Manager"
#~ msgstr "GnuPG Zertifikats&verwaltung"
#~ msgid "Passphrase"
#~ msgstr "Passphrase"
#~ msgid "Cache &passphrase for"
#~ msgstr "Passphrase speichern für"
#~ msgid "minutes"
#~ msgstr "Minuten"
#~ msgid "Ad&vanced.."
#~ msgstr "&Erweitert..."
#~ msgid "&Display crypto information"
#~ msgstr "~Krypto Informationen anzeigen"
#~ 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."
#~ msgid "Show S/MIME status info"
#~ msgstr "S/MIME Status Informationen anzeigen"
#~ msgid ""
#~ "Message class: %s\n"
#~ "Sig Status : %s\n"
#~ "Structure of the message:\n"
#~ "%s"
#~ msgstr ""
#~ "Nachrichtenklasse: %s\n"
#~ "Signatur-Status: %s\n"
#~ "Struktur der Nachricht:\n"
#~ "%s"
#~ msgid "Also encrypt message with the default certificate"
#~ msgstr "Nachricht ebenfalls an das voreingestellte Zertifikat verschlüsseln"
#~ msgid "The default certificate may not contain any spaces."
#~ msgstr ""
#~ "Der Bezeichner für das Standardzertifikat darf keine Leerzeichen "
#~ "enthalten."
#~ msgid "Select GPG Key Manager"
#~ msgstr "Das Schlüsselverwaltungsprogramm festlegen"
#~ msgid "Encrypt message with GPG"
#~ msgstr "Nachricht mit GnuPG verschlüsseln"
#~ msgid "Sign message with GPG"
#~ msgstr "Nachricht mit GnuPG unterschreiben"
#~ msgid "use S/MIME protocol"
#~ msgstr "S/MIME verwenden"
#~ msgid "Use the S/MIME protocol"
#~ msgstr "S/MIME Unterstützung einschalten"
#~ msgid "Debug-1 (open_inspector)"
#~ msgstr "Debug-1 (Inspektor Fenster öffnen)"
#~ msgid "No valid OpenPGP data found."
#~ msgstr "Keine gültigen OpenPGP Daten gefunden"
#~ msgid "Decryption"
#~ msgstr "Entschlüsselung"
#~ msgid ""
#~ "[This is a PGP/MIME message]\r\n"
#~ "\r\n"
#~ "[Use the \"Decrypt\" button in the message window to show its content.]"
#~ msgstr ""
#~ "[Dies ist eine PGP/MIME Nachricht]\n"
#~ "\n"
#~ "[Benutzen Sie den \"Entschlüsselungs\"-Button im großen\n"
#~ "Nachrichtenfenster um den Inhalt anzuzeigen.]"
#~ msgid ""
#~ "Note: This is a PGP/MIME signed message. The GpgOL plugin is not always "
#~ "able to verify such a message due to missing support in Outlook.\n"
#~ "\n"
#~ "(This message will be shown only once per session)"
#~ msgstr ""
#~ "Hinweis: Dies is eine PGP/MIME signierte Nachricht. Das GpgOL Plugin\n"
#~ "ist nicht immer in der Lage, eine solche Nachricht zu verifizieren.\n"
#~ "Der Grund hierzu liegt in der fehlenden Unterstützung von Outlook.\n"
#~ "\n"
#~ "(Dieser Hinweis wird nur einmalig pro Sitzung angezeigt)"
#~ msgid "Verification"
#~ msgstr "Überprüfung"
#~ msgid "[This is a PGP/MIME message]"
#~ msgstr "[PGP/MIME Nachricht]"
#~ msgid "Problem decrypting PGP/MIME message"
#~ msgstr "Problem bei Entschlüsseln einer PGP/MIME Nachricht"
#~ msgid "Verification Failure"
#~ msgstr "Überprüfungsfehler"
#~ msgid "Decryption Failure"
#~ msgstr "Entschlüsselungsfehler"
#~ msgid ""
#~ "The message text cannot be displayed.\n"
#~ "You have to save the decrypted message to view it.\n"
#~ "Then you need to re-open the message.\n"
#~ "\n"
#~ "Do you want to save the decrypted message?"
#~ msgstr ""
#~ "Der Text der Nachricht kann nicht angezeigt werden.\n"
#~ "Sie sollten die entschlüsselte Nachricht abspeichern und\n"
#~ "sie dann wieder zum Betrachten öffnen.\n"
#~ "\n"
#~ "Möchten Sie die entschlüsselte Nachricht abspeichern?"
#~ msgid ""
#~ "Signed attachments found.\n"
#~ "\n"
#~ "@LIST@\n"
#~ "Do you want to verify the signatures?"
#~ msgstr ""
#~ "Es wurden unterschriebene Anhänge gefunden.\n"
#~ "\n"
#~ "@LIST@\n"
#~ "Möchten Sie diese Unterschriften überprüfen?"
#~ msgid "Attachment Verification"
#~ msgstr "Überprüfung der Anhänge"
#~ msgid ""
#~ "Encrypted attachments found.\n"
#~ "\n"
#~ "@LIST@\n"
#~ "Do you want to decrypt and save them?"
#~ msgstr ""
#~ "Es wurde verschlüsselte Anhange gefunden.\n"
#~ "\n"
#~ "@LIST@\n"
#~ "Möchten Sie diese entschlüsseln und abspeichern?"
#~ msgid "Attachment Decryption"
#~ msgstr "Entschlüsselung eines Anhangs"
#~ msgid "Attachment Encryption Failure"
#~ msgstr "Verschlüsselungsfehler eines Anhangs"
#~ msgid "Attachment Verification Failure"
#~ msgstr "Überprüfungsfehler eines Anhangs"
#~ msgid "Attachment Decryption Failure"
#~ msgstr "Entschlüsselungsfehler eines Anhangs"
#~ msgid "Attachment Signing Failure"
#~ msgstr "Unterschrifterstellungsfehler eines Anhangs"
#~ msgid "[PGP/MIME message]"
#~ msgstr "[PGP/MIME Nachricht]"
#~ msgid "[PGP/MIME message without plain text body]"
#~ msgstr "[PGP/MIME Nachricht ohne reinen Textkörper]"
#~ msgid "[PGP/MIME signed message without a plain text body]"
#~ msgstr "[PGP/MIME signierte Nachricht ohne reinen Textkörper]"
#~ msgid "[PGP/MIME signature]"
#~ msgstr "[PGP/MIME Signatur]"
#~ msgid "GPG &encrypt message"
#~ msgstr "Mit GPG &verschlüsseln"
#~ msgid "GPG &sign message"
#~ msgstr "Mit GPG unter&schreiben"
#~ msgid "Decrypt and verify the message."
#~ msgstr "Entschlüsseln und Prüfen der Nachricht."
#~ msgid "Open GPG Key Manager"
#~ msgstr "Die GPG Schlüsselverwaltung öffnen"
#~ msgid ""
#~ "If you cancel this dialog, the message will be sent in cleartext!\n"
#~ "\n"
#~ "Do you really want to cancel?"
#~ msgstr ""
#~ "Wenn Sie diesen Dialog abbrechen, wird die Nachricht im Klartext "
#~ "ausgesendet!\n"
#~ "\n"
#~ "Möchten Sie wirklich abbrechen?"
#~ msgid ""
#~ "If you cancel this dialog, the message will be sent without signing.\n"
#~ "\n"
#~ "Do you really want to cancel?"
#~ msgstr ""
#~ "Wenn Sie diesen Dialog abbrechen, so wird die Nachricht ohne Unterschrift "
#~ "versendet.\n"
#~ "\n"
#~ "Möchten Sie wirklich abbrechen?"
#~ msgid "Secret Key Dialog"
#~ msgstr "Auswahl des geheimen Schlüssels"
#~ msgid ""
#~ "If you cancel this dialog, the message will be sent without signing.\n"
#~ "Do you really want to cancel?"
#~ msgstr ""
#~ "Wenn Sie diesen Dialog abbrechen, so wird die Nachricht ohne Unterschrift "
#~ "versendet.\n"
#~ "\n"
#~ "Möchten Sie wirklich abbrechen?"
#~ msgid ""
#~ "If you cancel this dialog, the message will be sent in cleartext.\n"
#~ "\n"
#~ "Do you really want to cancel?"
#~ msgstr ""
#~ "Wenn Sie diesen Dialog abbrechen, so wird die NAchricht im Klartext "
#~ "versendet!\n"
#~ "\n"
#~ "Möchten Sie wirklich abbrechen?"
#~ msgid "[No attestation computed (e.g. messages was not signed)"
#~ msgstr ""
#~ "[Kein Testat berechnet (z.B. da die Nachricht nicht unterschrieben war)"
diff --git a/po/sv.po b/po/sv.po
index 94e452a..88cbb82 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -1,867 +1,871 @@
# Swedish translation for GPGol.
# Copyright (C) 2006 Free Software Foundation
# This file is distributed under the same license as the gpgol package.
# Daniel Nylander <po@danielnylander.se>, 2006.
#
msgid ""
msgstr ""
"Project-Id-Version: GPGol\n"
"Report-Msgid-Bugs-To: bug-gpgol@g10code.com\n"
-"POT-Creation-Date: 2008-10-27 15:56+0100\n"
+"POT-Creation-Date: 2008-10-27 18:31+0100\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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/attached-file-events.cpp:58
#, fuzzy
msgid "Error creating file for attachment."
msgstr ""
"Fel vid skapande av fil\n"
"Välj en annan"
#: src/attached-file-events.cpp:71
msgid "Error reading attachment."
msgstr ""
#: src/attached-file-events.cpp:82 src/attached-file-events.cpp:95
#, fuzzy
msgid "Error writing attachment."
msgstr "Fel vid skrivning av fil"
#: src/attached-file-events.cpp:216
msgid ""
"Sorry, we are not able to decrypt this attachment.\n"
"\n"
"Please use the decrypt/verify button to decrypt the\n"
"entire message again. Then open this attachment."
msgstr ""
#: src/common.c:216
#, fuzzy
msgid "GpgOL - Save decrypted attachment"
msgstr "GPG - Spara dekrypterad bilaga"
#: src/config-dialog.c:137
msgid "Debug output (for analysing problems)"
msgstr ""
#: src/engine.c:429
msgid ""
"The user interface server is not available or does not work. Using an "
"internal user interface.\n"
"\n"
"This is limited to the PGP/MIME protocol and thus S/MIME protected message "
"are not readable."
msgstr ""
#: src/engine.c:433 src/ext-commands.cpp:774 src/ext-commands.cpp:795
#: src/ext-commands.cpp:800 src/main.c:682 src/main.c:688 src/message.cpp:320
msgid "GpgOL"
msgstr ""
#: src/engine-gpgme.c:368
#, fuzzy
msgid ""
"The configured default encryption certificate is not available or does not "
"unambigiously specify one. Please fix this in the option dialog.\n"
"\n"
"This message won't be be encrypted to this certificate!"
msgstr ""
"Den konfigurerade standardkrypteringsnyckeln är inte tillgänglig eller anger "
"inte uttryckligen en nyckel. Rätta till det här i inställningarna.\n"
"\n"
"Det här meddelandet kommer inte att krypteras med den här nyckeln!"
#: src/engine-gpgme.c:372
msgid "Encryption"
msgstr "Kryptering"
#: src/engine-gpgme.c:788
msgid "Fingerprint: "
msgstr "Fingeravtryck: "
#: src/engine-gpgme.c:845
msgid "This signature is valid\n"
msgstr "Den här signaturen är giltig\n"
#: src/engine-gpgme.c:847
msgid "signature state is \"green\"\n"
msgstr "signaturens tillstånd är \"grön\"\n"
#: src/engine-gpgme.c:849
msgid "signature state is \"red\"\n"
msgstr "signaturens tillstånd är \"röd\"\n"
#: src/engine-gpgme.c:853
#, fuzzy
msgid "Warning: One of the certificates has been revoked\n"
msgstr "Varning: En av nycklarna har spärrats\n"
#: src/engine-gpgme.c:863
#, fuzzy
msgid "Warning: The certificate used to create the signature expired at: "
msgstr "Varning: Nyckeln som användes för att skapa signaturen gick ut den: "
#: src/engine-gpgme.c:869
#, fuzzy
msgid "Warning: At least one certification certificate has expired\n"
msgstr "Varning: Åtminstone en certifieringsnyckel har gått ut\n"
#: src/engine-gpgme.c:875
msgid "Warning: The signature expired at: "
msgstr "Varning: Signaturen gick ut den: "
#: src/engine-gpgme.c:881
#, fuzzy
msgid "Can't verify due to a missing certificate\n"
msgstr "Kan inte validera på grund av en saknad nyckel eller certifikat\n"
#: src/engine-gpgme.c:885
msgid "The CRL is not available\n"
msgstr "Spärrlistan är inte tillgänglig\n"
#: src/engine-gpgme.c:891
msgid "Available CRL is too old\n"
msgstr "Tillgänglig spärrlista är för gammal\n"
#: src/engine-gpgme.c:896
msgid "A policy requirement was not met\n"
msgstr "Ett policykrav matchades inte\n"
#: src/engine-gpgme.c:902
msgid "A system error occured"
msgstr "Ett systemfel inträffade"
#: src/engine-gpgme.c:939
#, fuzzy
msgid ""
"WARNING: We have NO indication whether this certificate belongs to the "
"person named as shown above\n"
msgstr ""
"VARNING: Vi har INGA indikationer på huruvida nyckeln tillhör personen vars "
"namn visas ovanför\n"
#: src/engine-gpgme.c:946
#, fuzzy
msgid ""
"WARNING: The certificate does NOT BELONG to the person named as shown above\n"
msgstr "VARNING: Nyckeln TILLHÖR INTE personen vars namn visas ovanför\n"
#: src/engine-gpgme.c:950
#, fuzzy
msgid ""
"WARNING: It is NOT certain that the certificate belongs to the person named "
"as shown above\n"
msgstr ""
"VARNING: Det är INTE säkert att nyckeln tillhör den person vars namn visas "
"ovanför\n"
#: src/engine-gpgme.c:983
msgid "Verification started at: "
msgstr "Validering startad: "
#: src/engine-gpgme.c:988
msgid "Verification result for: "
msgstr "Valideringsresultat för: "
#: src/engine-gpgme.c:989
msgid "[unnamed part]"
msgstr "[ej namngiven del]"
#: src/engine-gpgme.c:1007 src/engine-gpgme.c:1037
msgid "Good signature from: "
msgstr "Korrekt signatur från: "
#: src/engine-gpgme.c:1014
msgid " aka: "
msgstr "även känd som:"
#: src/engine-gpgme.c:1018 src/engine-gpgme.c:1040
msgid " created: "
msgstr " skapad: "
#: src/engine-gpgme.c:1027
msgid "*BAD* signature claimed to be from: "
msgstr "*FELAKTIG* signatur hävdades komma från: "
#: src/engine-gpgme.c:1050
msgid "Error checking signature"
msgstr "Fel vid kontroll av signatur"
#: src/engine-gpgme.c:1066
msgid "*** Begin Notation (signature by: "
msgstr "*** Notation start (signatur av: "
#: src/engine-gpgme.c:1086
msgid "*** End Notation ***\n"
msgstr "*** Notation slut ***\n"
#: src/ext-commands.cpp:533
msgid "GpgOL Decrypt/Verify"
msgstr ""
#: src/ext-commands.cpp:547
msgid ""
"This is a signed and encrypted message.\n"
"Click for more information. "
msgstr ""
#: src/ext-commands.cpp:550
msgid ""
"This is an encrypted message.\n"
"Click for more information. "
msgstr ""
#: src/ext-commands.cpp:552
msgid ""
"This is a signed message.\n"
"Click for more information. "
msgstr ""
#: src/ext-commands.cpp:562
msgid ">GnuPG protocol"
msgstr ""
#: src/ext-commands.cpp:563
msgid "auto"
msgstr ""
#: src/ext-commands.cpp:564
#, fuzzy
msgid "PGP/MIME"
msgstr "[PGP/MIME-meddelande]"
#: src/ext-commands.cpp:565
msgid "S/MIME"
msgstr ""
#: src/ext-commands.cpp:567
#, fuzzy
msgid "&encrypt message with GnuPG"
msgstr "Signera meddelandet med GPG"
#: src/ext-commands.cpp:568
#, fuzzy
msgid "&sign message with GnuPG"
msgstr "Signera meddelandet med GPG"
#: src/ext-commands.cpp:603
#, fuzzy
msgid "GnuPG Certificate &Manager"
msgstr "GPG-nyckel&hanterare"
#: src/ext-commands.cpp:604
msgid "Remove GpgOL flags from this folder"
msgstr ""
#: src/ext-commands.cpp:608
msgid "Open the certificate manager"
msgstr ""
#: src/ext-commands.cpp:744
msgid ""
"Support for S/MIME has not been enabled.\n"
"\n"
"To enable S/MIME support, open the option dialog and check \"Enable the S/"
"MIME support\". The option dialog can be found in the main menu at: Extras-"
">Options->GpgOL.\n"
msgstr ""
#: src/ext-commands.cpp:773
#, fuzzy
msgid "Could not start certificate manager"
msgstr "Kunde inte starta nyckelhanteraren"
#: src/ext-commands.cpp:785
msgid ""
"You are about to start the process of reversing messages created by GpgOL to "
"prepare deinstalling of GpgOL. Running this command will put GpgOL into a "
"disabled state so that messages are not anymore processed by GpgOL.\n"
"\n"
"You should convert all folders one after the other with this command, close "
"Outlook and then deinstall GpgOL.\n"
"\n"
"Note that if you start Outlook again with GpgOL still being installed, GpgOL "
"will again process messages."
msgstr ""
#: src/ext-commands.cpp:799
msgid "Do you want to revert this folder?"
msgstr ""
#: src/ext-commands.cpp:901
#, fuzzy
msgid "Select this option to automatically select the protocol."
msgstr "Välj det här alternativet för att kryptera meddelandet."
#: src/ext-commands.cpp:908
#, fuzzy
msgid "Select this option to select the PGP/MIME protocol."
msgstr "Välj det här alternativet för att kryptera meddelandet."
#: src/ext-commands.cpp:915
#, 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:922
msgid "Select this option to encrypt the message."
msgstr "Välj det här alternativet för att kryptera meddelandet."
#: src/ext-commands.cpp:929
msgid "Select this option to sign the message."
msgstr "Välj det här alternativet för att signera meddelandet."
#: src/ext-commands.cpp:936
#, 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:966
#, fuzzy
msgid "Automatically select the protocol for sign/encrypt"
msgstr "Välj det här alternativet för att kryptera meddelandet."
#: src/ext-commands.cpp:976
msgid "Use PGP/MIME for sign/encrypt"
msgstr ""
#: src/ext-commands.cpp:986
msgid "Use S/MIME for sign/encrypt"
msgstr ""
#: src/ext-commands.cpp:996
#, fuzzy
msgid "Encrypt message with GnuPG"
msgstr "Signera meddelandet med GPG"
#: src/ext-commands.cpp:1006
#, fuzzy
msgid "Sign message with GnuPG"
msgstr "Signera meddelandet med GPG"
#: src/ext-commands.cpp:1016
msgid "Open the GpgOL certificate manager"
msgstr ""
#: src/main.c:681
#, c-format
msgid "Note: Using compatibility flags: %s"
msgstr ""
#: src/main.c:687
#, c-format
msgid ""
"Note: Writing debug logs to\n"
"\n"
"\"%s\""
msgstr ""
#: src/mapihelp.cpp:1468 src/mapihelp.cpp:1476 src/mapihelp.cpp:1484
msgid "[no subject]"
msgstr ""
#: src/mapihelp.cpp:2093
msgid ""
"[The content of this message is not visible because it has been decrypted by "
"another Outlook session. Use the \"decrypt/verify\" command to make it "
"visible]"
msgstr ""
#: src/mapihelp.cpp:2870
msgid ""
"[The content of this message is not visible due to an processing error in "
"GpgOL.]"
msgstr ""
# A bit unclear in the original text
#: src/message-events.cpp:320
msgid ""
"Sorry, we can only encrypt plain text messages and\n"
"no RTF messages. Please make sure that only the text\n"
"format has been selected."
msgstr ""
"Tyvärr, vi kan endast kryptera vanliga textmeddelanden\n"
"och inte RTF-meddelanden. Se till att endast textformatet\n"
"har valts i inställningarna."
#: src/message.cpp:192
msgid "[Crypto operation failed - can't show the body of the message]"
msgstr ""
#: src/message.cpp:300
#, c-format
msgid ""
"Signature status: %s\n"
"Message class ..: %s\n"
"MIME structure .:\n"
"%s"
msgstr ""
#: src/message.cpp:308
msgid "GpgOL - Message Information"
msgstr ""
#: src/message.cpp:538
msgid "Signature verification of an encrypted message is not possible."
msgstr ""
#: src/message.cpp:549
msgid "Signature verification of this message class is not possible."
msgstr ""
#: src/message.cpp:552
msgid ""
"Signature verification of this S/MIME message is not possible. Please check "
"that S/MIME processing has been enabled."
msgstr ""
#: src/message.cpp:556
#, fuzzy
msgid "This message has no signature."
msgstr "Dekryptera meddelandet och validera signaturen"
#: src/message.cpp:854
msgid "This message is not encrypted."
msgstr ""
#: src/message.cpp:1081
#, fuzzy, c-format
msgid ""
"Decryption failed\n"
"(%s)"
msgstr "Kryptering misslyckades"
#: src/message.cpp:1228
msgid "No recipients to encrypt to are given"
msgstr ""
-#: src/message.cpp:1244
+#: src/message.cpp:1241 src/message.cpp:1268
+msgid "Encrypting or signing an empty message is not possible."
+msgstr ""
+
+#: src/message.cpp:1250
#, fuzzy, c-format
msgid "Encryption failed (%s)"
msgstr "Kryptering misslyckades"
-#: src/message.cpp:1265
+#: src/message.cpp:1277
#, fuzzy, c-format
msgid "Signing failed (%s)"
msgstr "Signering misslyckades"
#: src/mimeparser.c:1166
#, fuzzy
msgid "Error writing to stream"
msgstr "Fel vid skrivning av fil"
#: src/mimeparser.c:1167
msgid "I/O-Error"
msgstr "In-/Ut-fel"
#: src/olflange-dlgs.cpp:44
msgid "General"
msgstr ""
#: src/olflange-dlgs.cpp:45
msgid "Enable the S/MIME support"
msgstr ""
#: src/olflange-dlgs.cpp:47
msgid "Message sending"
msgstr ""
#: src/olflange-dlgs.cpp:48
#, fuzzy
msgid "&Encrypt new messages by default"
msgstr "Kryptera meddelandet med GPG"
#: src/olflange-dlgs.cpp:49
msgid "&Sign new messages by default"
msgstr ""
#: src/olflange-dlgs.cpp:50
msgid "Use PGP/MIME by default"
msgstr ""
#: src/olflange-dlgs.cpp:51
msgid "Use S/MIME by default"
msgstr ""
#: src/olflange-dlgs.cpp:53
msgid "Message receiving"
msgstr ""
#: src/olflange-dlgs.cpp:54
msgid "Also decrypt in preview window"
msgstr ""
#: src/olflange-dlgs.cpp:55
msgid "Show HTML view if possible"
msgstr ""
#: src/olflange-dlgs.cpp:56
msgid "Present encrypted message as attachment"
msgstr ""
#: src/olflange-dlgs.cpp:59
msgid "Crypto Engine"
msgstr ""
#: src/olflange-dlgs.cpp:216
msgid ""
"You have enabled GpgOL's support for the S/MIME protocol.\n"
"\n"
"New S/MIME messages are thus only viewable with GpgOL and not anymore with "
"Outlook's internal S/MIME support. Those message will even be unreadable by "
"Outlook after GpgOL has been deinstalled. A tool to mitigate this problem "
"will be provided when GpgOL arrives at production quality status."
msgstr ""
#. TRANSLATORS: See the source for the full english text.
#: src/olflange-dlgs.cpp:272
msgid "-#GpgOLFullHelpText#-"
msgstr ""
#: src/olflange-dlgs.cpp:278
#, c-format
msgid "This is GpgOL version %s"
msgstr ""
#: src/olflange.cpp:435
msgid ""
"You have installed a new version of GpgOL.\n"
"\n"
"Please open the option dialog and confirm that the settings are correct for "
"your needs. The option dialog can be found in the main menu at: Extras-"
">Options->GpgOL.\n"
msgstr ""
#: src/olflange.cpp:619
msgid ""
"This version of Outlook is too old!\n"
"\n"
"At least versions of Outlook 2003 older than SP2 exhibit crashes when "
"sending messages and messages might get stuck in the outgoing queue.\n"
"\n"
"Please update at least to SP2 before trying to send a message"
msgstr ""
"Den här versionen av Outlook är för gammal!\n"
"\n"
"Åtminstone versioner av Outlook 2003 äldre än SP2 kraschar när meddelanden "
"skickas och meddelanden kan fastna i utgående postkö.\n"
"\n"
"Uppdatera åtminstone till SP2 innan du försöker skicka ett meddelande"
#: src/passphrase-dialog.c:85
#, fuzzy
msgid "No certificate hint given."
msgstr "Inget nyckeltips angivet."
#: src/passphrase-dialog.c:313 src/passphrase-dialog.c:464
msgid "Enter passphrase to unlock the secret key"
msgstr ""
#: src/passphrase-dialog.c:314 src/passphrase-dialog.c:465
msgid "Hide typing"
msgstr ""
#: src/passphrase-dialog.c:315 src/passphrase-dialog.c:466
#: src/recipient-dialog.c:385
msgid "&Cancel"
msgstr ""
#: src/passphrase-dialog.c:350 src/passphrase-dialog.c:499
msgid "Invalid passphrase; please try again..."
msgstr "Ogiltig lösenfras; försök igen..."
#: src/passphrase-dialog.c:379
msgid "Select Signing Key"
msgstr "Välj signeringsnyckel"
#: src/passphrase-dialog.c:463
msgid "Encrypted to the following certificates:"
msgstr ""
#: src/recipient-dialog.c:88
msgid "Name"
msgstr "Namn"
#: src/recipient-dialog.c:93
msgid "E-Mail"
msgstr "E-post"
#: src/recipient-dialog.c:98
msgid "Key-Info"
msgstr "Nyckelinfo"
#: src/recipient-dialog.c:103
msgid "Key ID"
msgstr "Nyckel-id"
#: src/recipient-dialog.c:108
msgid "Validity"
msgstr "Giltighet"
#: src/recipient-dialog.c:383
msgid "Selected recipients:"
msgstr ""
#: src/recipient-dialog.c:384
msgid "Recipient which were NOT found"
msgstr ""
#: src/recipient-dialog.c:444
#, fuzzy
msgid "Please select at least one recipient certificate."
msgstr "Välj åtminstone en mottagarnyckel."
#: src/recipient-dialog.c:445
msgid "Recipient Dialog"
msgstr "Mottagardialog"
#: src/verify-dialog.c:124
msgid "BAD signature!"
msgstr "FELAKTIG signatur!"
#: src/verify-dialog.c:126
msgid "Good signature"
msgstr "Korrekt signatur"
#: src/verify-dialog.c:128
#, fuzzy
msgid "Good signature from revoked certificate"
msgstr "Korrekt signatur från spärrad nyckel"
#: src/verify-dialog.c:130
#, fuzzy
msgid "Good signature from expired certificate"
msgstr "Korrekt signatur från utgången nyckel"
#: src/verify-dialog.c:132
msgid "Good expired signature"
msgstr "Korrekt utgången signatur"
#: src/verify-dialog.c:135
#, fuzzy
msgid "Could not check signature: missing certificate"
msgstr "Kunde inte kontrollera signaturen: saknar nyckel"
#: src/verify-dialog.c:139
msgid "Verification error"
msgstr "Valideringsfel"
#: src/verify-dialog.c:156
msgid "User-ID not found"
msgstr "Användaridentiteten hittades inte"
#: src/verify-dialog.c:168
msgid "This may be due to a wrong option setting"
msgstr "Det här kan bero på en felaktig inställning"
#: src/verify-dialog.c:174
#, c-format
msgid "Signature expired on %s"
msgstr "Signaturen gick ut den %s"
#: src/verify-dialog.c:186
#, fuzzy
msgid "Signature issued by a certificate we do NOT trust."
msgstr "Signaturen utfärdad av en nyckel som vi INTE litar på."
#: src/verify-dialog.c:193
#, fuzzy
msgid "Signature issued by a non-valid certificate."
msgstr "Signaturen utfärdad av en icke-giltig nyckel."
#: src/verify-dialog.c:209
msgid "Signature made"
msgstr ""
#: src/verify-dialog.c:210
msgid "using"
msgstr ""
#: src/verify-dialog.c:211
msgid "cert-ID"
msgstr ""
#: src/verify-dialog.c:212
msgid "from"
msgstr ""
#: src/verify-dialog.c:213
msgid "also known as"
msgstr ""
#: src/verify-dialog.c:244
#, fuzzy
msgid "PGP/MIME Verification Result"
msgstr "Resultat från validering"
#: src/verify-dialog.c:247
#, fuzzy
msgid "S/MIME Verification Result"
msgstr "Resultat från validering"
#~ msgid "&Decrypt and verify message"
#~ msgstr "&Dekryptera och validera meddelandet"
#, fuzzy
#~ msgid "&Verify signature"
#~ msgstr "FELAKTIG signatur!"
#, fuzzy
#~ msgid "Select this option to decrypt and verify the message."
#~ msgstr "Välj det här alternativet för att kryptera meddelandet."
#, fuzzy
#~ msgid "Select Certificate Manager"
#~ msgstr "GPG-nyckel&hanterare"
#, fuzzy
#~ msgid "Select this option to show information on the crypto status"
#~ msgstr "Välj det här alternativet för att signera meddelandet."
#, fuzzy
#~ msgid "Also encrypt message with the default certificate"
#~ msgstr "Kryptera meddelandet med GPG"
#, fuzzy
#~ msgid "The default certificate may not contain any spaces."
#~ msgstr "Standardnyckeln får inte innehålla några blanksteg."
#~ msgid "Select GPG Key Manager"
#~ msgstr "Välj GPG-nyckelhanterare"
#, fuzzy
#~ msgid "Encrypt message with GPG"
#~ msgstr "Signera meddelandet med GPG"
#~ msgid "Sign message with GPG"
#~ msgstr "Signera meddelandet med GPG"
#, fuzzy
#~ msgid "Select this option to select the OpenPGP protocol."
#~ msgstr "Välj det här alternativet för att kryptera meddelandet."
#, fuzzy
#~ msgid "OpenPGP Verification Result"
#~ msgstr "Resultat från validering"
#~ msgid "No valid OpenPGP data found."
#~ msgstr "Inget giltigt OpenPGP-data hittades."
#~ msgid "Decryption"
#~ msgstr "Dekryptering"
#~ msgid ""
#~ "[This is a PGP/MIME message]\r\n"
#~ "\r\n"
#~ "[Use the \"Decrypt\" button in the message window to show its content.]"
#~ msgstr ""
#~ "[Det här är ett PGP/MIME-meddelande]\r\n"
#~ "\r\n"
#~ "[Använd knappen \"Dekryptera\" i meddelandefönstret för att visa "
#~ "innehållet.]"
#, fuzzy
#~ msgid ""
#~ "Note: This is a PGP/MIME signed message. The GpgOL plugin is not always "
#~ "able to verify such a message due to missing support in Outlook.\n"
#~ "\n"
#~ "(This message will be shown only once per session)"
#~ msgstr ""
#~ "Observera: Det här är ett PGP/MIME-signerat meddelande. Insticksmodulen "
#~ "GPGol kan inte alltid validera ett sådant meddelande på grund av att stöd "
#~ "saknas i Outlook.\n"
#~ "\n"
#~ "(Det här meddelandet kommer endast att visas en gång per session)"
#~ msgid "Verification"
#~ msgstr "Validering"
#~ msgid "[This is a PGP/MIME message]"
#~ msgstr "[Det här är ett PGP/MIME-meddelande]"
#~ msgid "Problem decrypting PGP/MIME message"
#~ msgstr "Problem vid dekryptering av PGP/MIME-meddelande"
#~ msgid "Verification Failure"
#~ msgstr "Validering misslyckades"
#~ msgid "Decryption Failure"
#~ msgstr "Dekryptering misslyckades"
#~ msgid ""
#~ "The message text cannot be displayed.\n"
#~ "You have to save the decrypted message to view it.\n"
#~ "Then you need to re-open the message.\n"
#~ "\n"
#~ "Do you want to save the decrypted message?"
#~ msgstr ""
#~ "Meddelandetexten kan inte visas.\n"
#~ "Du måste spara det dekrypterade meddelandet\n"
#~ "för att visa det. Sedan måste du öppna det igen.\n"
#~ "\n"
#~ "Vill du spara det dekrypterade meddelandet?"
#~ msgid ""
#~ "Signed attachments found.\n"
#~ "\n"
#~ "@LIST@\n"
#~ "Do you want to verify the signatures?"
#~ msgstr ""
#~ "Signerade bilagor hittades.\n"
#~ "\n"
#~ "@LIST@\n"
#~ "Vill du validera signaturerna?"
#~ msgid "Attachment Verification"
#~ msgstr "Validering av bilaga"
#~ msgid ""
#~ "Encrypted attachments found.\n"
#~ "\n"
#~ "@LIST@\n"
#~ "Do you want to decrypt and save them?"
#~ msgstr ""
#~ "Krypterade bilagor hittades.\n"
#~ "\n"
#~ "@LIST@\n"
#~ "Vill du dekryptera och spara dem?"
#~ msgid "Attachment Decryption"
#~ msgstr "Dekryptering av bilaga"
#~ msgid "Attachment Encryption Failure"
#~ msgstr "Kryptering av bilaga misslyckades"
#~ msgid "Attachment Verification Failure"
#~ msgstr "Validering av bilaga misslyckades"
#~ msgid "Attachment Decryption Failure"
#~ msgstr "Dekryptering av bilaga misslyckades"
#~ msgid "Attachment Signing Failure"
#~ msgstr "Signering av bilaga misslyckades"
#~ msgid "[PGP/MIME message without plain text body]"
#~ msgstr "[PGP/MIME-meddelande utan vanlig meddelandetext]"
#~ msgid "[PGP/MIME signed message without a plain text body]"
#~ msgstr "[PGP/MIME-signerat meddelande utan vanlig meddelandetext]"
#~ msgid "[PGP/MIME signature]"
#~ msgstr "[PGP/MIME-signatur]"
#~ msgid "GPG &encrypt message"
#~ msgstr "GPG-&kryptera meddelandet"
#~ msgid "GPG &sign message"
#~ msgstr "GPG-&signera meddelandet"
#~ msgid "Decrypt and verify the message."
#~ msgstr "Dekryptera och validera meddelandet."
#~ msgid "Open GPG Key Manager"
#~ msgstr "Öppna GPG-nyckelhanteraren"
diff --git a/src/ChangeLog b/src/ChangeLog
index b4e3460..c53e9df 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,2218 +1,2227 @@
2008-10-27 Werner Koch <wk@g10code.com>
+ * mimemaker.c (mime_encrypt): Check for an empty message before
+ creating the filter. Return a suitable error code.
+ (do_mime_sign): Ditto.
+ (mime_sign_encrypt): Ditto.
+ (mime_sign): Return an error code.
+ * message.cpp (sign_encrypt): Show an error message for empty
+ messages.
+ (message_sign): Ditto.
+
* olflange.cpp (install_forms): Add gpgol-cs.
* mapihelp.cpp (get_internetcharsetbody_tag): New.
(mapi_get_body_as_stream): Try the new tag first.
(get_msgcls_from_pgp_lines): Ditto. Remove the simple access
method.
2008-10-24 Werner Koch <wk@g10code.com>
* mimeparser.c (struct mime_context): Add flag MAY_BE_OPAQUE_SIGNED.
(t2body): Set that flag.
(is_cms_signed_data): New.
(mime_decrypt): Try to verify if the content is opaque signed
without proper MIME headers.
2008-10-23 Werner Koch <wk@g10code.com>
* mapihelp.cpp (mapi_delete_gpgol_body_attachment): New.
* message-events.cpp (OnWriteComplete): Remove a body attachment.
* message.cpp (message_display_handler): Do not display PGP
clearsigned messages.
(message_display_handler): Do not update GpgOLStatus; it is not
used anyway.
(pgp_mime_from_clearsigned): Fix bogus trailing white space
removal code. Insert an empty line.
* mimeparser.c (mime_verify): Add arg MIMEHACK.
(message_verify): Use it.
2008-10-17 Werner Koch <wk@g10code.com>
* recipient-dialog.c (load_rsetbox): Remove superfluous check on
negativness for an unsigned variable.
* mimeparser.c (mime_verify_opaque): Remove extra semicolon which
shortcuted most of the code. Why didn't gcc notice that? Bug
was introduced on 2008-06-12.
* engine-assuan.c (create_io_pipe, send_options)
(op_assuan_encrypt, op_assuan_sign, op_assuan_decrypt)
(op_assuan_verify): Replace use of long in snprint by int to
workaround a bug in mingw32. Doesn't matter on w32 anyway.
2008-10-16 Werner Koch <wk@g10code.com>
* mimeparser.c (start_attachment): Take care not to set the file
name "smime.p7m".
* mapihelp.cpp (is_really_cms_encrypted): Extend to detect unknown
message types.
(mapi_change_message_class): Adjust for this change.
(mapi_change_message_class): Factor code out to ...
(change_message_class_ipm_note)
(change_message_class_ipm_note_smime)
(change_message_class_ipm_note_smime_multipartsigned)
(change_message_class_ipm_note_secure_cex): New.
(get_first_attach_mime_tag): New.
(change_message_class_ipm_note_secure_cex): Use it here for CexSig.
(has_smime_filename): Also look at the long filename.
2008-10-15 Werner Koch <wk@g10code.com>
* engine-assuan.c (op_assuan_sign): Send the new --protocol option
to the server.
2008-09-30 Werner Koch <wk@g10code.com>
* mapihelp.cpp (mapi_change_message_class): Special handling for
MultipartSigned if S/MIME support is disabled.
2008-08-06 Werner Koch <wk@g10code.com>
* olflange-dlgs.cpp (GPGOptionsDlgProc): Disable S/MIME notice.
2008-08-05 Werner Koch <wk@g10code.com>
* ext-commands.cpp (InstallCommands): Display protocolicons only
for OL2007.
* olflange.cpp (get_ol_main_version): New.
* message.cpp (message_decrypt): Save a signature verification
result.
* mimeparser.c (mime_decrypt): Implement verification of included
signatrues. This feature got lost during the removal of nested
crypto operations.
2008-08-04 Werner Koch <wk@g10code.com>
* olflange.cpp (install_forms): New.
(GpgolExt): Install forms if needed.
* common.c (get_data_dir): New.
* common.h (struct): Add field FORMS_REVISION.
* main.c (read_options, write_options): Read and write that option.
2008-07-31 Werner Koch <wk@g10code.com>
* ext-commands.h (class GpgolExtCommands): Add m_nCmdRevertFolder.
* ext-commands.cpp (GpgolExtCommands, InstallCommands): Ditto.
(DoCommand): Implement RevertFolder command.
* common.h (struct): Add variable DISABLE_GPGOL.
* session-events.cpp (OnDelivery): Make use of that variable.
* message.cpp (message_incoming_handler): Ditto.
* user-events.cpp (OnSelectionChange): Ditto
* message-events.cpp (OnRead, OnReadComplete, OnWrite)
(OnWriteComplete): Ditto
* mapihelp.cpp (mapi_get_int_prop): New.
* olflange.cpp (Install): Improve version check.
* revert.cpp, revert.h: New.
* mapihelp.cpp (mapi_attachment_to_body): New.
(mapi_get_old_message_class): New.
(mapi_change_message_class): Do not release newvalue when saving
the old class.
* olflange.cpp (parse_version_number, parse_version_string)
(compare_versions, gpgol_check_version): New.
* ext-commands.cpp (DoCommand): Support a "revert message class"
debug command.
2008-06-27 Werner Koch <wk@g10code.com>
* mapihelp.cpp (get_gpgololdmsgclass_tag): New.
(mapi_change_message_class): Save old message class.
2008-06-19 Werner Koch <wk@g10code.com>
* olflange-dlgs.cpp (GPGOptionsDlgProc): Change S/MIME enabled
message icon.
* olflange.cpp (GpgolExt): Ditto for the new version installed
notice.
2008-06-12 Werner Koch <wk@g10code.com>
* dialogs.rc: Add button for calling the engine's configuration.
* dialogs.h (IDC_GPG_CONF): New.
* engine.c (engine_start_confdialog): New.
* engine-assuan.c (op_assuan_start_confdialog): New.
* olflange-dlgs.cpp (GPGOptionsDlgProc): Act upon the button.
* mapihelp.cpp (mapi_get_from_address): New.
* engine.c (engine_decrypt_start, engine_verify_start): Add new
arg FROM_ADDRESS.
* engine-assuan.c (op_assuan_verify, op_assuan_decrypt): Ditto.
* mimeparser.c (mime_verify, mime_verify_opaque, mime_decrypt):
Pass FROM_ADDRESS to the backend.
* olflange.cpp (DllUnregisterServer): Delete CLSIDs.
2008-06-05 Werner Koch <wk@g10code.com>
* mimeparser.c (mime_decrypt): Set session number and title.
(mime_verify_opaque, mime_verify): Ditto.
* mapihelp.cpp (mapi_get_subject): New.
* engine.c (engine_set_session_number, engine_set_session_title)
(engine_set_sender_address): New.
(struct engine_filter_s): Add fields session_number, session_title
and sender_address.
(engine_private_get_session_number): New.
(engine_private_get_session_title): New.
(release_filter): Release them.
(engine_new_session_number): New.
* engine-assuan.c (send_session_info): New
(op_assuan_decrypt, op_assuan_verify): Call it.
(op_assuan_sign): Use the end-of-option option for the SENDER command.
2008-05-28 Werner Koch <wk@g10code.com>
* dialogs.h (IDC_BODY_AS_ATTACHMENT): New.
* dialogs.rc: Add body-as-attachemnt checkbox to the otpion
dialog.
* olflange-dlgs.cpp (set_labels, GPGOptionsDlgProc): Add it.
* main.c (write_options, read_options): Handle bodyAsAttachment
registry key.
* mimeparser.c (start_attachment): Do not set the hidden flag if
the new option is used.
* mapihelp.cpp (mapi_test_attach_hidden): New.
(mapi_get_gpgol_body_attachment): Make use of that flag.
2008-05-23 Werner Koch <wk@g10code.com>
* mimemaker.c (struct sink_s): Add field ENC_COUNTER.
(write_buffer_for_cb): Update that.
(mime_encrypt): Bail out if no data has been encrypted.
(mime_sign_encrypt): Ditto.
2008-05-07 Werner Koch <wk@g10code.com>
* mimeparser.c (t2body): Fix last change.
2008-05-02 Werner Koch <wk@g10code.com>
* mimeparser.c (t2body): Detect non-inline text parts.
* rfc822parse.c (rfc822parse_query_parameter): Add special mode
for an ATTR of NULL.
2008-04-16 Werner Koch <wk@g10code.com>
* message-events.h (class GpgolMessageEvents): Add M_GOTINSPECTOR.
* message.cpp (message_incoming_handler): Change return type.
* ext-commands.cpp (check_toolbar, check_menu_toolbar): New.
(update_protocol_menu): Explicitly update the toolbar.
2008-04-15 Werner Koch <wk@g10code.com>
* Outlook.gpl: New.
2008-04-14 Werner Koch <wk@g10code.com>
* display.cpp (is_inspector_display): New.
(find_message_window): Rewrote.
* message-events.cpp (OnRead): Use it.
* message.cpp (message_incoming_handler): Add arg FORCE.
* message-events.cpp (OnRead): Pass false for FORCE.
* item-events.cpp (OnOpen): Ditto.
* ext-commands.cpp (DoCommand): Let CmdCryptoState process and
display the current message again.
(GpgolExtCommands): Remove m_nCmdCheckSig and m_nCmdDecrypt.
2008-04-10 Werner Koch <wk@g10code.com>
* ol-ext-callback.cpp (is_preview_pane_visible)
(show_preview_pane): New.
* display.cpp (update_display): Add arg IS_SENSITIVE and do not
use the OOM method if this is set.
* mapihelp.h (mapi_save_changes): New. Use if everywhere.
(mapi_delete_body_props): Use it to delete body parts.
* mapihelp.cpp (mapi_do_save_changes): New.
* mimemaker.c (finalize_message): Do no delete body parts because
mapi_save_changes does this now.
* mimeparser.c (finish_message): Remove the body property in
protect mode.
2008-04-04 Werner Koch <wk@g10code.com>
* engine-assuan.c (worker_start_read, worker_check_read): Factor
common code out to ..
(write_to_callback): .. new.
(async_worker_thread): Better comments and minor changes.
(enqueue_callback): Add arg INACTIVE.
(set_items_active): New.
(start_command): Set items active.
(op_assuan_encrypt): Create input and output items as inactive.
(async_worker_thread): Handle the inactive flag.
* common.c (gpgol_spawn_detached): Do not inherit handles.
2008-04-02 Werner Koch <wk@g10code.com>
* engine-assuan.c (destroy_command): Add arg FORCE.
(op_assuan_encrypt_bottom): Call destroy_command.
* mimeparser.c (struct mime_context): Use parser_error to return
gpg error codes.
* main.c (read_options): Allow names for debug flags.
* common.c (trim_spaces): New.
2008-03-31 Werner Koch <wk@g10code.com>
* engine-assuan.c (struct work_item_s): Add SWITCH_COUNTER.
(switch_threads, clear_switch_threads): New.
(worker_start_write): Use it.
* engine.c (struct engine_filter_s): Add SWITCH_COUNTER.
(switch_threads, clear_switch_threads): New.
(filter_gpgme_read_cb): Use it.
* ext-commands.h (class GpgolExtCommands): Add m_nCmdCryptoState.
* ext-commands.cpp (InstallCommands): Add a toolbar crypto state
button.
(DoCommand): Show a message when trying to select the disabled
S/MIME protocol.
* message.cpp (message_sign, message_verify, message_decrypt)
(sign_encrypt): Display message boxes only in debug mode.
* olflange-dlgs.cpp: Remove G-Data 2001 copyright because all that
old code has gone.
* dialogs.rc (IDD_EXT_OPTIONS): Remove option to select the key
manager.
(IDD_GPG_OPTIONS): Remove caching time, reorder options, add group
boxes.
* olflange-dlgs.cpp (GPGOptionsDlgProc): Clean up accordingly.
* config-dialog.c (config_dlg_proc): Ditto.
(get_open_file_name, does_file_exist, error_box): Remove.
* ext-commands.cpp: Rename nCmdShowInfo to nCmdDebug0 and enable
it only in debug mode.
2008-03-26 Werner Koch <wk@g10code.com>
* engine-gpgme.c (cleanup): Implement.
(op_gpgme_init): Save thread handle.
(waiter_thread): Check shutdown flags.
* engine-assuan.c (get_uiserver_name): Fallback to GPA.
2008-03-19 Werner Koch <wk@g10code.com>
* mapihelp.cpp (mapi_change_message_class): Look into
multipart/mixed for PGP messages.
* mapihelp.cpp (mapi_get_attach): Add arg UNPROTECT and changed
all callers.
* common.h (DBG_MIME_PARSER, DBG_MIME_DATA): New.
* mimeparser.c (debug_mime_parser, debug_mime_data): New to
replace DEBUG_PARSER.
(struct mime_context): Add field is_opaque_signed.
(t2body): Set it.
(mime_decrypt): Handle an embedded opaque signed S/MIME part.
(mime_verify_opaque): Add arg INBUFER, INBUFFERLEN and
START_PART_COUNTER.
2008-03-18 Werner Koch <wk@g10code.com>
* mimeparser.c (message_cb): Clear all mimestruct fields. Fixes
segv introduced 2008-03-07.
* engine-assuan.c (async_worker_thread): Handle broken pipe.
2008-03-13 Werner Koch <wk@g10code.com>
* mimeparser.c (message_cb): Skip the OPEN event in non-MIME mode.
* rfc822parse.c (rfc822parse_open): Reset ERRNO.
2008-03-11 Werner Koch <wk@g10code.com>
* engine-assuan.c (op_assuan_encrypt): Factor some code out to ..
(op_assuan_encrypt_bottom): .. new.
(engine_assuan_encstate_s): New.
* engine.c (engine_encrypt_start): Split some code into ..
(engine_encrypt_prepare): .. new.
(engine_cancel): Cancel prepared encryption.
* mimemaker.c (mime_encrypt): Use engine_encrypt_prepare and _start.
(mime_sign_encrypt): Likewise, but do the _start only after
completing the signing.
2008-03-10 Werner Koch <wk@g10code.com>
* engine.c (FILTER_BUFFER_SIZE): Increase to 4k.
(engine_filter, engine_wait, engine_wait): Replace Sleep by
SwitchToThread.
* engine-assuan.c (struct work_item_s): Increase buffer to 1k.
(worker_start_write, async_worker_thread): Replace Sleep by
SwitchToThread.
2008-03-07 Werner Koch <wk@g10code.com>
* mapihelp.cpp (mapi_get_sender): New.
* mymapitags.h (PR_PRIMARY_SEND_ACCT): New.
* mimemaker.c (do_mime_sign): Pass the sender to the engine.
* common.h (opt): Add field SVN_REVISION.
* main.c (read_options, write_options): Set it.
* olflange.cpp (GpgolExt): Print a warning on program update.
* engine.c (struct engine_filter_s): Add field ADD_EXTRA_LF.
(engine_request_exra_lf): New.
(engine_wait): Implement that.
* mimeparser.c (mime_decrypt): Add arg SIMPLE_PGP and call
engine_request_exra_lf.
(struct mime_context): Add field NO_MAIL_HEADER.
(message_cb): Implement it.
* message.cpp (message_decrypt): Set that flag for old style PGP.
* common.h (DBG_COMMANDS, debug_commands): New.
* ext-commands.cpp: Use it.
2008-03-06 Werner Koch <wk@g10code.com>
* mimemaker.c (do_mime_sign): Figure out the protocol to use.
* engine.c (engine_sign_start): Add new args SENDER and R_PROTOCOL.
* engine-assuan.c (op_assuan_sign): Ditto. Send SENDER command.
2008-03-05 Werner Koch <wk@g10code.com>
* main.c (read_options): Insert the debug registry key.
(write_options): More debug output.
2008-02-28 Werner Koch <wk@g10code.com>
* olflange-dlgs.cpp (GPGOptionsDlgProc): Fix initial setting of
openpgp and smime state. I wish C would haved used := for
assignments.
2008-02-26 Werner Koch <wk@g10code.com>
* common.c (qp_decode): Add arg S_LBRK.
* mimeparser.c (plaintext_handler, ciphertext_handler): Handle
soft line breaks.
* mapihelp.cpp (mapi_change_message_class): Handle opaque S/MIME
messages without an smime-type parameter.
2008-02-25 Werner Koch <wk@g10code.com>
* message.cpp (message_verify): Show message boxes for non-signed
messages.
(message_decrypt): Likewise.
2008-02-19 Marcus Brinkmann <marcus@g10code.de>
* engine-assuan.c (get_uiserver_name): Change default uiserver
path and remove work-around.
2008-02-18 Werner Koch <wk@g10code.com>
* message.cpp (pgp_body_to_attachment): New.
(message_decrypt): Use it.
(message_wipe_body_cruft): Also wipe already processed PGP
encrypted messages. Factor common code out to ...
(do_wipe_body): .. new.
* mapihelp.h (ATTACHTYPE_PGPBODY): New.
2008-02-15 Werner Koch <wk@g10code.com>
* olflange-dlgs.cpp: Remove code for IDC_ENCRYPT_WITH_STANDARD_KEY
and IDC_ENCRYPT_TO.
* dialogs.rc: Ditto.
2008-02-13 Werner Koch <wk@g10code.com>
* mapihelp.cpp (get_gpgolcharset_tag, mapi_get_gpgol_charset)
(mapi_set_gpgol_charset): New.
(mapi_get_gpgol_body_attachment): Transcode from Latin-1.
* mimeparser.c (start_attachment): Set the charset property.
(struct mime_context): Remove is_utf8 field.
2008-02-11 Werner Koch <wk@g10code.com>
* common.h (tlvinfo_t): New.
* common.c (parse_tlv): New. Based on code from libksba.
* mapihelp.cpp (has_smime_filename): New.
(is_really_cms_encrypted): New.
(mapi_change_message_class): Use this here to work around a
CryptoEx bug.
2008-02-08 Werner Koch <wk@g10code.com>
* mapihelp.cpp (mapi_change_message_class): Improve detecion of
CryptoEx messages.
2008-02-07 Werner Koch <wk@g10code.com>
* engine.c (engine_verify_start): Enable opaque signature for the
assuan backend.
* engine-assuan.c (op_assuan_verify): New arg OUTDATA. Add
support for opaque signatures.
* mimeparser.c (mime_verify_opaque): New.
* message.cpp (message_verify): Handle opaque signed S/MIME.
* message.cpp (message_wipe_body_cruft): Delete only encrypted
messages.
2008-02-06 Werner Koch <wk@g10code.com>
* mimeparser.c (mime_decrypt): New arg IS_RFC822.
* message.cpp (message_decrypt): Add code to see whether to use
the new arg.
2008-02-01 Werner Koch <wk@g10code.com>
* mimeparser.c (ciphertext_handler, ciphermessage_cb)
(ciphermessage_t2body): New.
(mime_decrypt): Use an rfc822 parser to pass the message to the
engine.
* mapihelp.cpp (mapi_get_attach_as_stream): Add arg R_ATTACH.
(mapi_set_attach_hidden): New.
2008-01-31 Werner Koch <wk@g10code.com>
* message.cpp (message_verify): Check that the body attachment is
available before shortcutting the verification.
* user-events.cpp (OnSelectionChange): Change SMIME message
class.
* mapihelp.cpp (mapi_change_message_class): Add arg
SYNC_OVERRIDE. Changed all callers to pass false.
(mapi_test_sig_status): Take care of sent messages.
(mapi_get_gpgol_body_attachment): Change args to allow use as
testing fucntion too. Adjusted caller.
2008-01-29 Werner Koch <wk@g10code.com>
* mimemaker.c (do_mime_sign): Set CTE for SMIME.
(delete_all_attachments): Remove extra semicolon accidently
inserted with revision 916.
2008-01-18 Marcus Brinkmann <marcus@g10code.de>
* mimeparser.c (mime_verify): New variable sig_len, and pass it on
to engine_verify_start.
* engine.h (engine_verify_start): Add new argument sig_len.
* engine.c (engine_verify_start): Add new argument sig_len and
pass it on to op_assuan_verify and op_gpgme_verify.
* engine-assuan.h (op_asssuan_verify): Add new argument sig_len.
* engine-gpgme.c (op_gpgme_verify): New argument sig_len and use
it instead of string length of signature.
* engine-assuan.c (op_assuan_verify): Likewise.
2008-01-11 Werner Koch <wk@g10code.com>
* mimemaker.c (finalize_message): Add args PROTOCOL and ENCRYPT
and use them to set the override message class.
(mime_sign, mime_encrypt, mime_sign_encrypt): Pass this info via
the new args.
(do_mime_sign): Set micalg to sha1 for CMS.
* message.cpp (message_decrypt): Add hack fro seldgenerated messages.
2008-01-10 Werner Koch <wk@g10code.com>
* mapihelp.cpp (get_gpgolmsgclass_tag, mapi_set_gpgol_msg_class):
New.
(mapi_change_message_class, mapi_get_message_type): Try override
first.
* message.cpp (message_incoming_handler): Remove arg MSGTYE and
let the function retrieve it. Changed all callers. Retry after a
sucessful message class change.
* olflange.cpp (getMsgtype): Remove. The caching might lead to
problems and makes it all more complex. Changed all callers to
use mapi_get_message_type.
* mimemaker.c (create_top_encryption_header) <SMIME>: Write empty
line after header.
2008-01-09 Werner Koch <wk@g10code.com>
* mimeparser.c (finish_saved_body): New.
(finish_attachment): Keep the body attachment open.
(mime_decrypt, mime_verify): Close the saved body data.
(t2body): Continue body attachments.
* message.cpp (message_verify): Save changes.
* mapihelp.cpp (mapi_change_message_class): Handle case of
PGP/MIME signed with IPM.Note. Save only of really needed, use
FORCE_SAVE and keep it open for read and write.
2008-01-07 Marcus Brinkmann <marcus@g10code.de>
* engine-assuan.c (replace_dollar_s): Remove obsolete function.
(get_quoted_socket_name): Remove obsolete function.
(get_uiserver_name): Invoke GUI server with --daemon. Fix buglet
in assignment.
(destroy_command): Change return type to void to suppress compiler
warning.
2008-01-04 Werner Koch <wk@g10code.com>
* engine-assuan.c (send_options): Call AllowSetForegroundWindow.
* main.c (read_options): Allo other values than 1 for enableDebug.
* common.h (DBG_IOWORKER, DBG_IOWORKER_EXTRA, DBG_FILTER)
(DBG_FILTER): New.
* engine.c (debug_filter): Turn it into a macro.
(debug_filter_extra): New macro, used instead of checking the
value of debug_filter.
* engine-assuan.c (debug_ioworker, debug_ioworker_extra): new.
Use them all over the file to enable debugging.
* engine.c (engine_encrypt_start): Add arg HWND.
(engine_sign_start, engine_decrypt_start, engine_verify_start)
(engine_start_keymanager): Ditto.
* mimemaker.c (mime_encrypt, mime_sign_encrypt, mime_sign)
(do_mime_sign): Add arg HWND and pass it to the engine.
* mimeparser.c (mime_verify, mime_decrypt): Pass HWND.
* message.cpp (message_sign, sign_encrypt): Pass HWND.
(message_incoming_handler, message_verify, message_decrypt): Add
arg HWND and pass it on.
* message-events.cpp (OnRead): Pass HWND to message function.
* ext-commands.cpp (DoCommand): Ditto.
2008-01-03 Werner Koch <wk@g10code.com>
* mimemaker.c (mime_sign_encrypt): Fix result test of do_mime_sign.
(write_tempsign_attachment): Remove.
(do_mime_sign): Change last ark to a sink_t.
(mime_sign_encrypt): Rework to use a temporary stream instead of a
temporary attachment.
(create_mapi_attachment): Remove arg TEMPSIGN.
2007-12-18 Werner Koch <wk@g10code.com>
* mapihelp.cpp (get_msgcls_from_pgp_lines): Limit check to the
first 1 k and stop testing after the first PGP armor line.
(mapi_get_message_type): Return MSGTYPE_SMIME.
(mapi_change_message_class): Take care of CryptoEx signatures.
* mapihelp.h (MSGTYPE_SMIME): New.
* message.cpp (message_incoming_handler): Check message class for
unknown and unchecked messages. Take care MSGTYPE_SMIME.
* ext-commands.cpp (DoCommand): Add debug command change message class.
2007-12-07 Werner Koch <wk@g10code.com>
* ext-commands.cpp (InstallCommands): Removed toolbar button fro
decrypt as this is not anymore needed. Fixes bug#860.
(QueryHelpText): Ditto.
2007-11-12 Werner Koch <wk@g10code.com>
* olflange.h (class GpgolExt): Rename m_gpgSelectSmime to
m_protoSelection.
* message-events.cpp (OnWriteComplete): Use it accordingly.
* main.c (write_options, read_options): Load and save it.
* dialogs.rc: Add new check box for OpenPGP default protocol.
* olflange-dlgs.cpp (GPGOptionsDlgProc): Adjust for above chnages.
2007-11-09 Werner Koch <wk@g10code.com>
* main.c (read_options): New option ENABLE_DEBUG to be enabled
only using the Registry.
(read_options): Show warning for certain option combinations.
* olflange-dlgs.cpp (GPGOptionsDlgProc): Hide the Advanced options
button unless in debug mode.
* mapihelp.cpp (get_gpgollastdecrypted_tag): New.
(mapi_test_last_decrypted): New.
(mapi_has_last_decrypted): new.
* mimeparser.c (finish_message): Update the Last Decrypted property.
* message.cpp (message_decrypt): Use it here.
(message_wipe_body_cruft): New.
* main.c (do_log_window_hierarchy): Factor some code out to ..
(do_log_window_info): .. this.
(log_window_hierarchy): Log parent window info.
(get_64bit_session_marker): New.
(initialize_session_key): Init session marker.
* Makefile.am (gpgol_SOURCES): Remove item-events.cpp
* olflange.cpp (GpgolExt): Disable the GpgOLItemEvents as they can
only be used with the undocumented ECF file.
2007-10-29 Werner Koch <wk@g10code.com>
* mimemaker.c (create_top_signing_header): Add arg FIRST.
(mime_sign): Factor allmost all code out to ..
(do_mime_sign): .. new function.
(create_mapi_attachment): Add arg TEMPSIGN.
(delete_all_attachments): Adjust for that.
(mime_encrypt): Factor some code out to ..
(create_top_encryption_header): .. new.
(write_tempsign_attachment): New.
(mime_sign_encrypt): Implement.
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.
* dialogs.rc: Renamed from olflange-rsrcs.rc.
* dialogs.h: Rename for olflange-ids.h. Changed all includers.
* Makefile.am: Adjust accordingly.
* verify-dialog.c (verify_dialog_box): Do not distinguish
languages.
(verify_dlg_set_labels): New.
(verify_dlg_proc): Call it.
* passphrase-dialog.c (passphrase_callback_box): Do not
distinguish languages.
(decrypt_key_dlg_set_labels): New.
(decrypt_key_dlg_proc): Call it.
(decrypt_key_ext_dlg_set_labels): New.
(decrypt_key_ext_dlg_proc): Call it.
* recipient-dialog.c (recipient_dialog_box): Do not distinguish
languages.
(recipient_dialog_box2): Ditto.
(recipient_dlg_set_labels): New.
(recipient_dlg_proc): Call it.
2007-10-11 Werner Koch <wk@g10code.com>
* ext-commands.cpp (toolbar_add_menu): USe "@" to indicate a
separator and "" to ski the entry. Changed callers.
* common.h (struct): Remove AUTO_SIGN_ATTACH. Add ENABLE_SMIME.
* main.c (read_options, write_options): Save the new option.
* olflange-dlgs.cpp (GPGOptionsDlgProc): Implement new option and
print warning.
* mapihelp.cpp (mapi_change_message_class): Take care of enable_smime.
* olflange-ids.h: Renumbered.
* olflange-rsrcs.rc: Keep only the english dialog and changed all
text to dummy texts.
* olflange-dlgs.cpp (set_labels): New.
(GPGOptionsDlgProc): Call it.
* property-sheets.cpp (GetPages): Do not distinguish languages.
* config-dialog.c (config_dialog_box): Ditto.
(config_dlg_set_labels): New.
* gpgol-rsrcs.rc (IDD_OPT): Move to olflange-rsrcs.rc and rename
to IDD_EXT_OPTIONS.
(IDD_OPT_DE): Remove.
2007-10-10 Werner Koch <wk@g10code.com>
* main.c (read_options): Remove saveDecryptedAttachment. Add
smimeDefault.
2007-10-08 Werner Koch <wk@g10code.com>
* main.c (do_log): Remove trailing LF from w32 error message and
also print the numeric error code.
2007-09-25 Werner Koch <wk@g10code.com>
* Makefile.am (gpgol_LDADD): Link against libassuan.
* util.h (DIM, DIMof): New.
* engine.c (filter_gpgme_read_cb): Implement nonblock feature.
(filter_gpgme_write_cb): Ditto.
2007-09-24 Werner Koch <wk@g10code.com>
* common.c (standard_homedir, default_homedir): New.
(w32_shgetfolderpath): Make static.
2007-09-21 Werner Koch <wk@g10code.com>
* mimeparser.c (build_mimeinfo): New.
(finish_message): Store the mime structure.
* mapihelp.cpp (mapi_get_message_class): New.
(mapi_get_sig_status): New.
(get_gpgolprotectiv_tag, get_gpgolsigstatus_tag)
(get_gpgolattachtype_tag): Factored code out to ...
(create_gpgol_tag): .. New.
(get_gpgolmimeinfo_tag): New.
(mapi_get_mime_info): New.
2007-09-20 Werner Koch <wk@g10code.com>
* user-events.cpp, user-events.h: New.
* olflange.h (class GpgolExt): Add member for it.
* olflange.cpp (QueryInterface): Hook it in.
2007-09-19 Werner Koch <wk@g10code.com>
* mapihelp.cpp (mapi_has_sig_status): Return true if any sig
status is present.
(mapi_test_sig_status): New. Take semantics of the former
mapi_has_sig_status. Changed all callers.
(mapi_change_message_class): Set sign status to n/a for other
message classed.
* mimemaker.c (finalize_message): Mark created messages.
(write_buffer_for_cb): Rename from write_buffer_voidarg and return
number of bytes written.
(collect_signature): Return number of bytes written.
* mapihelp.h (struct mapi_attach_item_s): New member
PRIVATE_MAPITABLE.
* mapihelp.cpp (mapi_create_attach_table)
(mapi_release_attach_table): Keep the mapi table oben and put
PR_ATATCH_NUM into the MAPIPOS member.
(mapi_get_gpgol_body_attachment): Use PR_ATATCH_NUM.
* mimeparser.c (finish_message): New.
(mime_decrypt, mime_verify): Call it.
2007-09-17 Werner Koch <wk@g10code.com>
* olflange.cpp: Print gpgme version.
2007-09-14 Werner Koch <wk@g10code.com>
* engine-gpgme.c: Rewrote most of it.
2007-09-13 Werner Koch <wk@g10code.com>
* common.c (xrealloc): New.
2007-09-11 Werner Koch <wk@g10code.com>
* engine-gpgme.c (op_encrypt_data): New.
2007-09-08 Werner Koch <wk@g10code.com>
* engine.c: New.
* engine.h: Rewrite. Factor existing stuff out to ..
* engine-gpgme.h: .. new.
* engine-assuan.h, engine-assuan.c: New.
2007-09-07 Werner Koch <wk@g10code.com>
* common.c (qp_decode): Handle softe line breaks.
2007-09-06 Werner Koch <wk@g10code.com>
* mapihelp.cpp (mapi_get_body): New.
* mimeparser.c (protocol_t): Move to .. common.h.
2007-09-05 Werner Koch <wk@g10code.com>
* mimemaker.c, mimemaker.h: New.
2007-08-31 Werner Koch <wk@g10code.com>
* mapihelp.cpp (mapi_set_header): New.
* message.cpp (pgp_mime_from_clearsigned): New.
(message_verify): Use it.
* main.c: Call srand ().
* util.h (trailing_ws_p): New.
* common.c (generate_boundary): New.
2007-08-30 Werner Koch <wk@g10code.com>
* message-events.h (class GpgolMessageEvents): Rename M_IS_SMIME
to M_PROCESSED.
* message-events.cpp (OnRead, OnReadComplete): Ditto.
(OnReadComplete): Remove preview decryption stuff.
(OnWriteComplete): Remove GpgMsg based code.
* ext-commands.cpp (DoCommand): Ditto
(InstallCommands): Do not init the watcher.
* olflange.cpp (GpgolExt): Do not init the watcher.
(GpgolExt): Do not clanup the watcher.
* main.c (DllMain): Ditto.
* gpgmsg.cpp, gpgmsg.hh: Remove.
* watcher.cpp: Remove
* pgpmime.c, pgpmime.h: Remove.
* mapihelp.h (MSGTYPE_GPGOL_CLEAR_SIGNED)
(MSGTYPE_GPGOL_PGP_MESSAGE): New.
* mapihelp.cpp (mapi_get_message_type): Map them.
(get_msgcls_from_pgp_lines): New.
(mapi_change_message_class): Detect old old style PGP messages.
(mapi_get_body_as_stream): New.
* message.cpp (message_verify, message_decrypt): Handle them.
* message-events.cpp (OnRead): Ditto.
2007-08-29 Werner Koch <wk@g10code.com>
* ext-commands.h (class GpgolExtCommands): Add members
M_NCMDKEYMANAGER and M_NCMDDECRYPT.
* ext-commands.cpp (GpgolExtCommands): Initialize it.
(InstallCommands): Use them here instead of reusing another variable.
(DoCommand, Help, QueryHelpText, QueryButtonInfo): Restructured
for better readibility.
2007-08-21 Werner Koch <wk@g10code.com>
* w32-gettext.c (SUBLANG_BENGALI_BANGLADESH): Fix to 2 as per MSDN.
(SUBLANG_PUNJABI_PAKISTAN): Remove as it is not in MSDN.
(SUBLANG_ROMANIAN_MOLDOVA): Remove as it is not in MSDN.
(SUBLANG_ROMANIAN_ROMANIA): Change to value 1 as per MSDN.
2007-08-13 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (gpgol_SOURCES): Add common.h.
2007-08-06 Werner Koch <wk@g10code.com>
Lots of changes to support S/MIME and to revamp most of the old
code. More changes to follow. The list of changes below is not
complete as it does not identfy all newly written code.
* mimeparser.c: New. Based on pgpmime.c
* display.cpp (update_display): Removed unused arg MSG.
(update_display): Set the body to an empty string even if it is
not HTML.
* olflange.cpp (Install): Print OL version only once.
* verify-dialog.c (verify_dialog_box): Add arg PROTOCOL.
(load_sigbox): Ditto.
(verify_dlg_proc): Changed title acccording to used protocol.
* Makefile.am (gpgol_LDADD): Add libadvapi due to our use of
CryptGenRandom.
* main.c (get_crypt_random, initialize_session_key): New.
(DllMain): Initialize the session key.
(get_128bit_session_key, create_initialization_vector): New.
* serpent.c: New. Taken from libgcrypt 1.3.0 and stripped down to
fit our needs. Add CFB encryption API.
* serpent.h: New.
* mapihelp.cpp (mapi_mark_moss_attach): New.
* mymapitags.h (PR_ATTACHMENT_HIDDEN): New.
* display.cpp (open_inspector): New.
* mapihelp.cpp (mapi_get_binary_prop): New.
* engine-gpgme.c (op_verify_detached_sig_gpgme): Add arg
PROTOCOL. Changed all callers to pass the OPENPGP protocol.
* common.c (b64_decode): Renamed from base64_decode and use new
type for the context.
(b64_init): New.
* pgpmime.c (qp_decode, base64_decode): Move to common.c and make
public.
* common.h (STRICT): Remove.
* intern.h: Rename to common.h.
2007-07-20 Werner Koch <wk@g10code.com>
* myexchext.h (IOutlookExtItemEvents.): New.
* item-events.h, item-events.cpp: New.
* olflange.cpp (GpgolExt, QueryInterface): Hook it in.
2007-07-19 Werner Koch <wk@g10code.com>
* attached-file-events.cpp: Renamed from attach.c.
* attached-file-events.h: Renamed from attach.h. Removed some
inlines to the impl file.
* Makefile.am (gpgol_LDADD): Add libole32.
2007-07-18 Werner Koch <wk@g10code.com>
* mapihelp.c (log_mapi_property): Support STRIGN8 and UNICODE.
* myexchext.h (IExchExtUserEvents, IExchExtSessionEvents): New
declarations.
* session-events.cpp, session-events.h: New.
* olflange.cpp (GpgolExt, QueryInterface): Hook session-events in.
* olflange.cpp (DllRegisterServer): Register only for interfaces
we really use.
(ext_context_name): New. Factored out from several places.
(Install): Initialize for Session context.
Renamed all CGPGExchExt* classes to Gpgol*.
* olflange.h, olflange.cpp: Factor most code out to ..
* ext-commands.cpp, ext-commands.h, message-events.cpp
* message-events.h, property-sheets.cpp, property-sheets.h
* ol-ext-callback.cpp, ol-ext-callback.h: .. New.
2007-07-17 Werner Koch <wk@g10code.com>
* Makefile.am (gpgol_LDADD): Add ws2_32.
* main.c (log_window_hierarchy, do_log_window_hierarchy): New.
* olflange.cpp (show_window_hierarchy): Replace by
log_window_hierarchy.
(g_initdll): Make static.
(InstallCommands): Factor some code out to ..
(toolbar_from_tbe, toolbar_add_menu): .. new.
* mapihelp.c, mapihelp.h: New.
* olflange.cpp (show_mapi_property): Factor out to mapihelp.c
and rename to log_mapi_property.
2007-04-10 Werner Koch <wk@g10code.com>
* display.cpp (find_message_window): Add arg LEVEL for debugging.
Ignore MsoCommand* Windows. Fixes bug 735.
2006-10-14 Timo Schulz <ts@g10code.de>
* recipient-dialog.c (lv_get_item_param): New.
(copy_item): Use it here to copy the opaque param.
(recipient_dlg_proc): And here to avoid the hidden column.
(initialize_rsetbox): Localize column names.
* olflange.cpp (get_outlook_property): Free returned BSTR.
(InstallCommands): Likewise.
2009-09-06 Timo Schulz <ts@g10code.de>
* recipient-dialog.c (recipient_dialog2): Do not free
key array here.
2008-08-21 Timo Schulz <ts@g10code.de>
* engine-gpgme.c (op_lookup_keys): Only add useable keys
and add all invalid keys to unknown.
* recipient-dialog.c (copy_item): Rewritten.
(initialize_keybox): Add comment to clarify use of fnd_keys.
(recipient_dialog_box): Simplified.
(find_item): Support partial search.
2006-08-19 Timo Schulz <ts@g10code.de>
* olflange-rsrcs.rc: Correct some dialog sizes.
* passphrase-dialog.c (decrypt_key_dlg_proc): Automatically
select the secret key if only one is available.
* config-dialog.c (GPGOptionsDlgProc): Passphrase cache
time is now requested in minutes but still internally
stored as seconds.
2006-08-15 Timo Schulz <ts@g10code.de>
* decrypt.bmp, encrypt.bmp: Restore format.
* olflange.cpp (OnWriteComplete): Correct exit code handling.
* recipient-dialog.c (initialize_rsetbox): Correct column width.
(recipient_dlg_proc): Do not show the cancel error any longer.
* passphrase-dialog.c (decrypt_key_dlg_proc): Likewise.
(decrypt_key_ext_dlg_proc): Ditto.
* olgpgcore.def: Deleted unused file.
2006-06-14 Timo Schulz <ts@g10code.com>
* gpgol-rscs.rc (IDD_OPT): The English version of the dialog
has no log file item. Add it.
2006-05-22 Timo Schulz <ts@g10code.com>
* verify-dialog.c (load_sigbox): A sigsum of 0 also indicates
a valid (good) signature.
2006-04-25 Werner Koch <wk@g10code.com>
* xmalloc.h: New. Moved prototypes from util.h
* w32-gettext.h: Include it.
* common.c (utf8_to_wincp): Removed and replaced all callers by
utf8_to_native.
* common.c (wchar_to_utf8, utf8_to_wchar): Moved to ..
* w32-gettext.c: .. here.
(utf8_to_native): Make sure that we always return
a string and never NULL.
(native_to_utf8): New.
(native_to_wchar): New.
* gpgmsg.cpp (decrypt): Use native_to_utf8 for i18n strings
expected to be utf-8.
* pgpmime.c (pgpmime_decrypt, pgpmime_verify): Ditto.
2006-04-24 Werner Koch <wk@g10code.com>
* gpgmsg.cpp (decrypt): New arg INFO_ONLY.
* olflange.cpp (OnReadComplete): Add code to call decrypt but with
INFO_ONLY if preview decryption has not been requested.
* main.c (read_options): New compatibility option no_preview_info.
* gpgmsg.cpp (getRecipients): Don't add the default key here.
(encrypt_and_sign): But do it here.
* engine-gpgme.c (op_get_one_key): New.
2006-04-22 Timo Schulz <ts@g10code.com>
* common.c (utf8_to_wincp): Corrected utf8 decoding.
* passphrase-dialog.c (load_recipbox): Likewise.
* olflange-dlg.cpp (GPGOptionsDlgProc): Activate the
'confirm' button when the dialog state has been changed.
* olflange-rsrcs.rc (IDD_GPG_OPTIONS_DE): Change description.
2006-03-28 Werner Koch <wk@g10code.com>
* olflange-rsrcs.rc (IDD_GPG_OPTIONS_DE): Add new control box.
(IDD_GPG_OPTIONS): Updated to match German version.
* olflange-dlgs.cpp (GPGOptionsDlgProc): Ditto.
* gpgmsg.cpp (decrypt): Implemented PREFER_HTML option.
(get_long_attach_data): New.
2006-03-27 Werner Koch <wk@g10code.com>
* engine-gpgme.c (op_verify_detached_sig_gpgme): New.
* pgpmime.c (pgpmime_verify): New. First take on a PGP/MIME
signature verification.
* gpgmsg.cpp (is_pgpmime): Renamed to is_pgpmime_enc.
(class GpgMsgImpl): Niew members media_type. media_subtype and
ct_protocol.
(get_msg_content_type): New.
(decrypt): Show a warning for PGP/MIME signed messages.
2006-03-26 Werner Koch <wk@g10code.com>
* intern.h: New option PREFER_HTML.
* main.c (write_options, read_options): Ditto.
2006-03-20 Werner Koch <wk@g10code.com>
* olflange.cpp (Install): Also check major part of build version.
2006-03-17 Timo Schulz <ts@g10code.com>
* w32-gettext.c (utf8_to_native): Make it global.
* config-dialog.c (get_open_file_name): Make sure the selected
file really exists.
* passphrase-dialog.c (decrypt_dlg_proc): UTF8 conversion.
(passphrase_callback_box): Likewise.
* recipient-dialog.c (recipient_dlg_proc): Likewise.
* verify-dialog.c (load_akalist): Likewise.
(load_sigbox): Likewise.
* common.c (utf8_to_wincp): New.
2006-03-15 Werner Koch <wk@g10code.com>
* olflange.cpp (Install): Print gpgol version for debugging.
2006-03-14 Timo Schulz <ts@g10code.com>
* passphrase-dialog.c (decrypt_dlg_proc): When used
as a signing key selection dialog, use a different title.
* gpgol-rsrcs.rc: Use German titles for German dialog versions.
2006-02-23 Werner Koch <wk@g10code.com>
* main.c (read_options): Set default caching time to 10 minutes.
2006-01-16 Werner Koch <wk@g10code.com>
* verify-dialog.c (load_sigbox): Give a hint in case of a bad
signature.
* gpgol-rsrcs.rc (IDD_ENC_DE): Add an informational header.
2005-12-07 Werner Koch <wk@g10code.com>
* olflange.cpp (Install): Check the version and print a warning.
* olflange-dlgs.cpp (GPGOptionsDlgProc): Simplified the default
key code.
* config-dialog.c (store_config_value): Create key if it does not
exists.
(load_config_value_ext): Removed.
2005-12-06 Werner Koch <wk@g10code.com>
* config-dialog.c (start_key_manager): Don't pass the options to
access.
2005-12-06 Werner Koch <wk@g10code.com>
* gpgmsg.cpp (getRecipients): Add the default key to the list of
recipients.
* recipient-dialog.c (recipient_dlg_proc): Add the already found
keys to the selected ones.
* olflange.cpp (OnWriteComplete): Need to disable the deleting of
HTML bodys.
2005-12-05 Werner Koch <wk@g10code.com>
* Makefile.am (gpgol_LDADD): Add -loleaut32.
* engine-gpgme.c (op_verify_detached_sig_mem): New.
* olflange.cpp (OnWriteComplete): Pass HTML flag to sign call.
(put_outlook_property): Need to use a BSTR for the sake of putting
HTMLBody.
* gpgmsg.cpp (sign): Add arg WANT_HTML.
(free_attach_info): New. Use it in the destructor.
(createHtmlAttachment): New.
(encrypt_and_sign, sign): Use it here.
(writeAttestation): Don't write an empty attestation.
2005-12-02 Werner Koch <wk@g10code.com>
* verify-dialog.c (verify_dialog_box): Actually allow for German
dialog.
* recipient-dialog.c (recipient_dialog_box)
(recipient_dialog_box2): Ditto.
* passphrase-dialog.c (signer_dialog_box)
(passphrase_callback_box): Ditto.
* intern.h (struct): New field PREVIEW_DECRYPT. Use it instead os
the old compatibility flags.
* main.c (write_options, read_options): Store/load preview decrypt.
* config-dialog.c (config_dlg_proc): Removed homedir and gpgbinary
options as they are deprecated. Put logfile entry here.
* olflange-dlgs.cpp (GPGOptionsDlgProc): Remove logfile entry. Add
preview-decrypt checkbox.
* olflange.cpp (InstallCommands): Remove experimental preview
command.
* w32-gettext.c (gettext_localename): New.
* config-dialog.c (config_dialog_box): Use it here to match the
gettext behaviour.
(GetPages): Ditto.
2005-12-01 Werner Koch <wk@g10code.com>
* engine-gpgme.c (op_decrypt_stream_to_gpgme, decrypt_stream)
(op_decrypt): Add arg PREVIEW_MODE.
* pgpmime.c (pgpmime_decrypt): New arg PREVIEW_MODE.
(struct pgpmime_context): New field PREVIEW.
(message_cb, plaintext_handler): Handle preview mode.
* gpgmsg.cpp (class GpgMsgImpl): Renamed SILENT to PREVIEW.
(setSilent): Renamed to ..
(setPreview): .. this.
(decrypt): Handle preview mode. Display a string while decrypting
PGP/MIME messages.
* display.cpp (update_display): New arg TEXT.
* gpgmsg.cpp (class GpgMsgImpl): Removed BODY_PLAIN and BODY.
(getDisplayText): Removed.
(loadBody): Changes to return the allocated body.
(getOrigText): Removed.
(getMessageType): Rewritten to take the body text as argument.
(decrypt): Pass plaintext directly to update_display. Free
plaintext.
(sign, encrypt_and_sign): Likewise.
* olflange.cpp (OnWriteComplete): Always delete PR_BODY on error.
2005-11-30 Werner Koch <wk@g10code.com>
* gpgmsg.cpp: Made more strings translatable.
* olflange.cpp: Replaced all LoadStrings by gettext calls.
* olflange-ids.h: Removed the IDS_ constants.
* olflange-rsrcs.rc: Removed the stringtables.
* common.c (get_root_key, read_w32_registry_string): New. Taken
for libgpg-error.
* main.c (i18n_init): New.
(DllMain): Call it.
(get_locale_dir, drop_locale_dir): New.
* w32-gettext.c, w32-gettext.h: New. Taken form libgpg-error.
Slightly modified due to the fact that gpgol is W32-only.
* util.h (_, N_): Define standard i18n macros.
* display.cpp (set_message_body): Do not delete a RTF property.
* util.h (SRCNAME): New. Changed all __FILE__ to this.
* main.c (log_srcname): New.
2005-11-20 Werner Koch <wk@g10code.com>
* gpgmsg.cpp (loadBody): For HTML try to read the HTMLBody from
the OOM as a last resort.
* olflange.cpp (get_outlook_property): New.
(put_outlook_property_int): New.
2005-11-15 Werner Koch <wk@g10code.com>
* Makefile.am (gpgol_LDADD): Remove -lintl for now.
* olflange.cpp (OnWriteComplete): Make sure that we don't sent out
unencrypted stuff on error.
* display.cpp (set_message_body): Add arg IS_HTML.
(update_display): Ditto.
* gpgmsg.cpp (loadBody): New arg WANT_HTML.
(getOrigText): Ditto.
* olflange.h (class CGPGExchExtMessageEvents): Add M_WANT_HTML.
* olflange.cpp (OnWrite): Set it.
(OnWriteComplete): Pass its value to the encrypt functions.
2005-11-10 Werner Koch <wk@g10code.com>
* config-dialog.c (start_key_manager): Changed invocation of
default keymanager.
2005-10-21 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (libgpgme.a, libgpgme.a): New targets.
(gpgol_DEPENDENCIES): Add libgpgme.a and libgpg-error.a.
(clean-local): Likewise.
(gpgol_LDADD): Link to these local versions statically.
2005-10-20 Marcus Brinkmann <marcus@g10code.de>
* mapi32.def: New file.
* Makefile.am (gpgol_DEPENDENCIES): New variable.
(libmapi32.a): New target.
(gpgol_LDADD): Replace mapi32.dll with "-L . -lmapi32".
(clean-local): New target.
2005-10-19 Werner Koch <wk@g10code.com>
* gpgmsg.cpp (sign, encrypt_and_sign): Don't set the body first to
empty. If this is really required we should do this in
set_message_body.
(sign): Save changes. Set content type to text/plain.
(encrypt_and_sign): Save changes also for empty bodies.
2005-10-06 Werner Koch <wk@g10code.com>
* gpgmsg.cpp (writeAttestation): Use gpgme_free for BUFFER.
* engine-gpgme.c (data_to_file): Ditto.
2005-10-06 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (gpgol_DEPENDENCIES): New variable.
(libmapi32.a): New target.
(gpgol_LDADD): Replace mapi32.dll with "-L . -lmapi32".
* Makefile.am (gpgol_LDADD): Prefix gpgol.def and mapi32.dll with
$(srcdir).
* Makefile.am (.rc.o): Invoke windres with "-I .".
* Makefile.am (.rc.o): Invoke windres with -I $(srcdir).
* Makefile.am (gpgol_SOURCES): Add util.h.
2005-09-29 Werner Koch <wk@g10code.com>
* gpgmsg.cpp (encrypt_and_sign): Pass signing key to encryption
function.
* passphrase-dialog.c (signer_dialog_box): New arg encrypting.
* gpgmsg.cpp (encrypt_and_sign): Set content type.
* engine-gpgme.c (op_lookup_keys): Fixed multiple key detection.
2005-09-28 Werner Koch <wk@g10code.com>
* olflange.cpp (DoCommand): Catch close command and resend to
avoid the "save changes?".
* display.cpp (update_display): Take care of utf-8 issues.
* common.c (latin1_to_utf8): New.
* pgpmime.c (latin1_data_write): New.
(plaintext_handler): Use it here.
(message_cb): Detect utf-8 encoding.
* main.c (read_options): Make sure that compat flags are always
properly initialized.
* display.cpp (find_message_window): First try to find the window
by class name.
* common.c (wchar_to_utf8_2): New.
2005-09-27 Werner Koch <wk@g10code.com>
* pgpmime.c (pgpmime_decrypt): Pass a pseduo filename to the
decryption function.
* verify-dialog.c (load_sigbox): Get key direct from gpgme.
* passphrase-dialog.c (load_secbox, load_recipbox): Reworked.
(decrypt_key_dlg_proc, decrypt_key_ext_dlg_proc): Reworked.
(count_keys, release_keyarray): New.
(signer_dialog_box, passphrase_callback_box): Adjusted to above
changes.
* engine-gpgme.c (op_deinit): Remove keycache cleanup.
* Makefile.am (gpgol_SOURCES): Removed keycache.c, keycache.h.
* keycache.c, keycache.h: Removed.
* recipient-dialog.c (recipient_dialog_box)
(recipient_dialog_box2): Rewritten and changed interface.
(load_rsetbox): Removed keycache stuff and rewrote to make use of
the keyarray.
(copy_item, initialize_keybox, recipient_dlg_proc): Ditto.
(keycache_to_key_array): Removed.
* engine-gpgme.c (op_lookup_keys): Rewritten, changed interface.
* gpgmsg.cpp (count_recipients): Renamed to ..
(count_strings): .. this.
(count_keys): New.
(free_recipient_array): Renamed to ..
(free_string_array): .. this.
(encrypt_and_sign): Adjusted for changes in op_lookup_keys and
recipient_dialog_box2.
2005-09-26 Werner Koch <wk@g10code.com>
* passphrase-dialog.c (get_pubkey_algo_str): Add DSA and old Elgamal.
* gpgmsg.cpp (gatherAttachmentInfo): Ignore attachments we can't
open.
* main.c (write_options): Print message on error. Rearranged to
make use of a table for all options.
2005-09-23 Werner Koch <wk@g10code.com>
* recipient-dialog.c (recipient_dlg_proc): Removed
IDC_ENC_OPTARMOR stuff; it was not used.
(load_rsetbox): Fixed detection of encryption capability.
* gpgol-ids.h, gpgol-rsrcs.rc: Ditto.
2005-09-22 Werner Koch <wk@g10code.com>
* engine-gpgme.c (decrypt_stream): Use gpgme_op_decrypt_verify.
* gpgmsg.cpp (gatherAttachmentInfo): Ignore attestations when
checking for pgp/mime.
* pgpmime.c (pgpmime_decrypt): Added arg HWND.
(message_cb, plaintext_handler): Write attachments.
* pgpmime.c (base64_decode): New.
* rfc822parse.c (parse_field): Treat Content-Disposition special.
* gpgmsg.cpp (get_save_filename): Moved to ..
* common.c (get_save_filename): .. here.
2005-09-20 Timo Schulz <ts@g10code.com>
* attach.c: New.
* attach.h: New.
* olflange.cpp (CGPGExchExt): Allocate class for
attached file events.
(QueryInterface): Return interface pointer for
attached file events.
* passphrase-dialog.c (load_secbox): Use new GPGME
interface.
(get_pubkey_algo_str): New.
* verify-dialog.c (load_sigbox): Likewise.
* recipient-dialog.c (load_recipbox): Likewise.
2005-09-19 Werner Koch <wk@g10code.com>
* msgcache.c (flush_if_needed): New.
(msgcache_put): use it.
* intern.h (opt): New compatibility flags AUTO_DECRYPT and
NO_ATTESTATION.
* olflange.cpp (InstallCommands): Use watcher stuff only when this
option has been enabled.
* gpgmsg.cpp (decrypt): Take care of NO_ATTESTATION.
* main.c (DllMain): Removed debug output; this should not be
used before initialization!
* watcher.cpp: Include config.h. Removed weird line endings.
* gpgmsg.cpp (encrypt_and_sign): Call SaveChanges.
2005-09-15 Timo Schulz <ts@g10code.com>
* util.h: Provider watcher prototypes.
* watcher.cpp (watcher_init_hook): New.
(watcher_free_hook): New.
(watcher_set_callback_ctx): New.
(cbt_proc): New.
* display.cpp (find_message_window): Removed GpgMsg param.
Changed all callers.
2005-09-15 Werner Koch <wk@g10code.com>
* olflange.cpp (OnWriteComplete): Take care of EEME_FAILED.
(OnWrite): Check that we are encrypting only plain text messages.
* myexchext.h: Add flags used by OnReadComplete.
2005-09-14 Werner Koch <wk@g10code.com>
* gpgmsg.cpp (writeAttestation): Add a content type.
(gatherAttachmentInfo): Detect whether we already have an attestation.
(decrypt): Don't create duplicate attestations.
(writeAttestation): Translate LF to CRLF.
2005-09-13 Werner Koch <wk@g10code.com>
* pgpmime.c (pgpmime_decrypt): New arg ATTESTATION.
* engine-gpgme.c (add_verify_attestation): New.
(op_decrypt, op_verify_detached_sig, op_verify_detached_sig)
(op_verify_detached_sig): Add new arg ATTESTATION. Changed all
callers.
(at_sig_summary, at_sig_validity, add_verify_attestation): New.
The code has been taken and modified from Mutt's crypt-gpgme.c and
entirely been writen by g10 Code.
(at_fingerprint): Ditto.
* gpgmsg.cpp (class GpgMsgImpl): New member ATTESTATION. Use it
in all calls to the functions above.
* gpgmsg.cpp (decryptAttachment, decrypt): Save plaintext back
into the MAPI if desired.
2004-09-08 Timo Schulz <ts@g10code.com>
* passphrase-dialog.c (lod_recipbox): Use gpgme directly
to resolve the keyids to userids.
* usermap.c, usermap.h: Removed.
* HashTable.cpp, HashTable.h: Removed.
2005-09-07 Timo Schulz <ts@g10code.com>
* common.c: Removed unused code.
* intern.h: Likewise.
2005-09-07 Timo Schulz <ts@g10code.com>
* olflange.cpp (ul_release): New. Wrapper with error checking
around UlRelease.
(InstallCommands): Separate test for type and if string is empty.
2005-09-06 Werner Koch <wk@g10code.com>
* engine-gpgme.c (op_decrypt_stream): Factored most code out to ..
(decrypt_stream): .. new.
(op_decrypt_stream_to_buffer): Simplified accordingly. Fixed
possible buffer overflow when trying to make it a string.
(op_decrypt_stream_to_gpgme): New.
* pgpmime.c, pgpmime.h: New.
* rfc822parse.h, rfc822parse.c: New. Taken from GnuPG 1.9.
2005-09-06 Timo Schulz <ts@g10code.com>
* config-dialog.c (get_open_file_name): Correctly terminated filter.
New parameter for the title. Changed all callers.
(get_folder): Likewise.
2005-09-01 Werner Koch <wk@g10code.com>
* gpgmsg.cpp (get_pgp_armor_type): New.
(gatherAttachmentInfo): Enhanced to detect text/plain pgp.
(verify): Removed.
(decrypt): Do clearsig verification here.
* gpgmsg.cpp (decrypt): Kludge to workaround OL not updating a
window.
* msgcache.c (msgcache_get_from_mapi): New.
* display.cpp (find_message_window): Don't use the GpgMsg function
to to the string compare.
* gpgmsg.cpp (matchesString): Removed.
* msgcache.c (msgcache_set_active): Removed.
(msgcache_get): Rewritten.
(msgcache_put): Now uses PR_CONVERSATION_INDEX as key. Update
existing entries.
* olflange.cpp (OnRead): Removed msgcache_set_active.
(InstallCommands): Now uses the ConversationIndex to match the
reply with the message.
2005-08-31 Werner Koch <wk@g10code.com>
* olflange.cpp (DllRegisterServer): Define a CLSID and set the
ThreadingModel.
2005-08-30 Werner Koch <wk@g10code.com>
Renamed from "outlgpg" to "gpgol".
More or less finished this major rewrite.
2005-08-26 Werner Koch <wk@g10code.com>
* MapiGPGME.cpp, MapiGPGME.h: Removed.
* display.cpp, display.h: New.
2005-08-23 Werner Koch <wk@g10code.com>
* msgcache.c, msgcache.h: New.
2005-08-22 Werner Koch <wk@g10code.com>
* olflange.cpp: Major cleanups and partly rewrites.
2005-08-18 Werner Koch <wk@g10code.com>
* gpgmsg.cpp, gpgmsg.hh: New.
2005-08-17 Werner Koch <wk@g10code.com>
* MapiGPGME.cpp (setMessageAccess): Removed as it was only used at
one place.
(setRTFBody): Use the above code here directly..
(setWindow, setMessage): Removed. We can't use that because there
is only one instance of this class.
(decrypt): Add args HWND and MSG. Changed caller.
(getBody): Changed to ..
(get_body): .. plain function and add new arg MSG. Changed all
callers.
(isHtmlMessage): Likewise changed to ..
(is_html_message): .. plain function and add new arg MSG.
(doCmd): Removed.
* common.c (utf8_to_wchar): New.
* MapiGPGME.cpp (passphraseCallback): Removed.
(getPassphrase, clearPassphrase, storePassphrase): Removed.
(add_html_line_endings): Rewritten.
* engine-gpgme.c (op_sign_encrypt_start): Removed because it is
not used anywhere.
(op_sign): Renamed to ..
(do_sign): .. this and made local.
2005-08-16 Werner Koch <wk@g10code.com>
* MapiGPGME.cpp (signAttachment): Simplified.
* engine-gpgme.c (op_sign_file): Add arg TTL.
(op_sign_file_ext): Removed.
(op_sign_file_next): Renamed to ..
(do_sign_file): .. this and made local.
(do_sign_file): Updated to use new passphrase callback
semantics.
(op_decrypt_file): Ditto.
(free_recipients): Need to use gpgme_key_release and not just
free.
* engine-gpgme.c (do_decrypt): Factored some code out to ..
(update_passphrase_cache): .. new.
(op_sign_encrypt_file): Updated to use new passphrase callback
semantics.
* MapiGPGME.cpp (getBody): Properly distinguish property types.
(delete_buf): Removed macro. We now use malloc for the body
string. Changed other places to use delete directly for clarity.
(fail_if_null): Removed. Replaced by direct tests and a call to
out_of_core.
(setDefaultKey): Now use malloc/free instead of new/delete.
Changed at other places too.
(getDefaultKey): Changed to return a const char *.
* common.c (wchar_to_utf8): New.
(out_of_core): Made global and call abort after displaying the
message box.
2005-08-14 Werner Koch <wk@g10code.com>
* MapiGPGME.cpp (log_debug_w32): New.
(do_log): New arg W32ERR. Make sure to print a trailing LF.
* passphrase-dialog.c (passphrase_callback_box): Revamped.
(free_decrypt_key): Wipe out a passphrase. Remove superfluous
variable clearing.
* util.h (wipememory2, wipememory): New.
(wipestring): New.
* engine-gpgme.c (op_decrypt): Renamed to ..
(do_decrypt): .. this and made local.
(clear_error_if_cancel): Removed as we inlined the code.
(do_decrypt): Cleaned up.
* main.c (DllMain): Initialize passcaching subsystem.
* passcache.c, passcache.h: New.
* intern.h: Include it here.
* util.h: New.
* olflange.cpp (DllRegisterServer): Remove key for the old
versions of this plugin.
Merged olgpgmain.dll and olgpgcore.dll into outlgpg.dll.
* Makefile.am: Renamed target to outlgpg. Added required files.
* olflange.cpp, olflange.h: Renamed from GPGExch.cpp and
GPGExch.h. Removed all the MFC cruft as it is not required - it
was only used to get hands on the hInstance of the DLL; chnaged
that to use the glob_hinst which gets set by DllMain.
* outlgpg.def: New.
* olflange-def.h: New.
* olflange-dlgs.cpp: Renamed from GPGOptionsDlgs.cpp.
* olflange-ids.h: Renamed from ../olflange/resource.h
* olflange-rsrcs.rc: Renamed from ..olflange/olgpgmaindlgs.rc and
stripped off unneedded stuff.
* olgpgcoredlgs.rc: Renamed to ..
* outlgpg-rsrcs.rc: .. this and stripped of cruft.
* olgpgcoredlgs.h: Renamed to ..
* outlgpg-ids.h: .. this.
* versioninfo.rc.in: New.
2005-08-12 Timo Schulz <ts@g10code.com>
* config-dialog.c (sotre_extension_value, load_extension_value):
Adjust registry key.
2005-08-12 Werner Koch <wk@g10code.com>
* intern.h: Moved keycache prototypes to keycache.h.
* MapiGPGME.cpp (lock_log, unlock_log): New.
* engine-gpgme.c (op_init): Check GPGME version.
* main.c (outlook_gpg_get_version): Removed as it is now derived
from config.h.
(DllMain): Initializes gpgme and mapigpgme.
* MapiGPGME.cpp (initialize_mapi_gpgme): New.
* config-dialog.c (store_extension_value, load_extension_value):
Changed key to "OutlGPG".
* MapiGPGME.h (class MapiGPGME): New methods versionString and
showVersion. Breaks ABI but it doesn't matter as we are also
going to change the name of the project.
* Makefile.am: Renamed target to olgpgcore.
* resource.h: Renamed to ...
* olgpgcoredlgs.h: .. and removed cruft from generator.
* gpgmedlgs.rc: Renamed to ..
* olgpgcoredlgs.rc: ... and removed cruft.
* libgpgmedlgs.def: Renamed to ..
* olgpgcore.def: .. this.
2005-08-11 Werner Koch <wk@g10code.com>
* MapiGPGME.cpp (log_debug): New. Rewrote the whole log stuff.
It is not anymore per instance.
(logDebug): New version with va_list arg.
* MapiGPGME.cpp (passphraseCallback): Use gpgme_error_t becuase
C++ enforces enum types.
* engine-gpgme.c (op_lookup_keys): s/id/names/. id is a reved
word Obj-C and it is good style not to use it in plain C code.
(op_sign_file_next): Use gpgme_passphrase_cb_t in declaration.
(op_decrypt_next): Ditto.
* MapiGPGME.cpp (count_recipients): Renamed from countRecipients
method, made local and changed both callers.
(log_key_info): Changed output format. New arg PREFIX. Changed
callers.
(add_html_line_endings): Renamed from addHtmlLineEndings method
and made local.
(logDebug): Open in text mode. Removed all superfluous "\r" from
callers.
2005-08-09 Timo Schulz <ts@g10code.com>
* main.c (outlook_gpg_get_version): New.
Use same version as the Outlook GPG plugin.
* MapiGPGME.cpp [!__MINGW32__]: Changed sequence of include files.
2005-08-09 Werner Koch <wk@g10code.com>
* MapiGPGME.cpp (userid_from_key, keyid_from_key): New. Changed
all calls to the deprecated gpgme_key_get_string_attr function by
these.
* MapiGPGME.h, MapiGPGME.cpp: Splitted into interace and
implementation.
* HashTable.h (class HashTable): No need to dll export anything.
2005-08-08 Werner Koch <wk@g10code.com>
* common.c (w32_shgetfolderpath): Added.
* config-dialog.c (load_config_value_ext): use it here.
2005-07-21 Timo Schulz <twoaday@g10code.com>
* MapiGPGME.cpp (decrypt): Only return if no valid PGP
data was found and the message has no attachments.
* engine-gpgme.c (op_encrypt): Use --textmode to fix
problems when the recipient OS has different line endings.
For example Win32->Linux.
2005-07-20 Timo Schulz <twoaday@g10code.com>
* MapiGPGME.cpp (addHtmlLineEndings): New.
(encrypt):Use it here.
(signEncrypt): Likewise. Free memory in case of errors.
(decrypt): Free memory in case of the verify procedure.
Issue a warning when the text of the mail could not be
updated.
(isMessageEncrypted): New.
(countAttachments): Check for null pointers.
(clearPassphrase): Likewise.
* config-dialog.c (store_config_value): Support '%val%' input.
* verify-dialog.c (load_akalist): Return the number of user-ids
which were added.
* passphrase-dialog.c (load_secbox): Make sure we really start
to add the item data at the begin.
* intern.h: Fixed GCC compiler problem.
2005-07-19 Timo Schulz <twoaday@g10code.com>
* MapiGPGME.cpp (encrypt): Handle cancel.
(encryptAttachments): If no attachments exist, close the table.
(decryptAttachments): Likewise.
(signAttachments): Likewise.
(isHtmlBody): New.
(isHtmlMessage): New.
(setBody): Html support.
(encrypt): Figure out if message is html and encode the right body.
(signEncrypt): Likewise.
(verify): Always use the non-html body for GPG input.
(decrypt): Likewise.
* engine-gpgme.c (recipient_dialog_box2): Set cancel flag.
(op_sign_start): Handle cancel.
(recipient_dlg_proc): Make sure there is at least one selected
key. Disable armor checkbox.
2005-07-19 Timo Schulz <twoaday@g10code.com>
* MapiGPGME.cpp (~MapiGPGME): After releasing the
memory, set all pointers to NULL. It seems that NT5
bases operating systems are more pedantic with such
issues than 9X based systems.
(freeUnknownKeys): Likewise.
(freeRecipients): Likewise.
(encrypt): Outlook 2003 returns a body string which
is not NULL but \0 with a length of 0. Handle it.
(sign): Likewise.
(signEncrypt): Likewise.
* engine-gpgme.c (free_recipients): New.
(op_encrypt_start): Handle cancel and free memory.
2005-07-18 Timo Schulz <ts@g10code.com>
* gpgmedlgs.rc: Native language support for German.
2005-07-14 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp: Add some missing MAPI constants.
(passphrase_callback_box): Repair cancel button.
(decrypt): If the user cancels the operation, do not
alter the message text.
* config-dialog.c (expand_path): New. From WinPT.
(load_config_value): Support for REG_EXPAND_SZ.
Suggested by Sebastian.
2005-07-13 Timo Schulz <ts@g10code.de>
* MapiGPGME.cpp (sign): Ignore empty bodies.
(signEncrypt): Likewise. Free recipient memory.
(encrypt): Modify code so it really works.
(attachPublicKey): New.
* engine-gpgme.c (op_export_keys): New.
2005-07-12 Timo Schulz <ts@g10code.de>
* MapiGPGME.cpp (displayError): New.
(writeOptions): Use it here. Simplify the code.
(signAttachments): New.
(sign): Sign attachments. Noted by Ralf.
(processAttachment): Support for sign-only.
2005-07-08 Timo Schulz <ts@g10code.de>
* MapiGPGME.cpp (setEnableLogging): New.
(getEnableLogging): New.
(logDebug): Move all logging code to this function.
(readOptions): Automatically enable logging if the
'LogFile' registry entry is valid.
(prepareLogging): New.
(readOptions): Properly handle ""-strings.
* config-dialog.c (does_file_exist): Allow to have
parameters like '--keymanager' and cut them off before
checking the existence.
(start_key_manager): Free memory.
(config_dlg_proc): Initialize pointer to 'NULL'.
(SHFree): New. Special function to handle shell memory.
(get_folder): Free memory.
(does_folder_exist): New.
2005-07-06 Timo Schulz <ts@g10code.de>
* MapiGPGME.cpp: s/ATTR_/ATT_.
(saveDecryptedAttachment): Cut off the prefix.
(clearConfig): New.
(clearObject): New.
(MapiGPGME): Use it here.
Use ATT_PREFIX instead of a hardcoded string.
* engine-gpgme.c
(op_sign_file_next): New.
(op_sign_file): Call op_sign_file2.
(op_sign_file_ext): New.
2005-07-05 Timo Schulz <ts@g10code.de>
* MapiGPGME.cpp (readOptions, writeOptions):
Support for the new 'auto sign attachment' flag.
(signAttachment): New.
(setSignAttachments): New.
(getSignAttachments): New.
* engine-gpgme.c (op_sign_file): Enable armor.
2005-07-03 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (processAttachment): Implement
the decryption part and only use it if the 'save
decrypted attachment' flag is set.
(saveDecryptedAttachment): New.
(writeOptions): Save 'decrypt attachment' flag.
(readOptions): Load it here.
(cleanupTempFiles): Check handle.
(encrypt): If the message has no body skip the
procedure.
(op_decrypt_file): Set recipient callback.
(decryptAttachments): We do not alter the attachment
so there is no need to release it again.
Replace all 'free' with 'xfree'.
2005-07-01 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (processAttachment): Check that
the file has a valid PGP extension before we try
to decrypt the attachment.
(checkAttachmentExtension): Check if the file
extension is a vliad PGP extension.
2005-06-30 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (processAttachment): Use a unique
temp name to make a cleanup at the end easier.
(cleanupTempFiles): Delete possible left over
temp files.
(~MapiGPGME): Use it here.
2005-06-22 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (processAttachment): Close attachment
before we delete it.
(streamOnFile): Directly use the attachment.
(streamFromFile): Likewise.
(closeAttachment): Renamed to..
(releaseAttachment): ..this.
2005-06-21 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (getMessageType): Support all types.
(streamOnFile): More straight forward now.
(encryptAttachments): Get the attachment table first.
(getAttachPathname): New.
(processAttachment): Add new parameter for the position
of the attachment.
(streamFromFile): New.
(generateTempname): New.
* engine-gpgme.c (op_sign_encrypt_file): New.
2005-06-17 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (MapiGPGME): Initialize all attachment
components to zero. Thanks to Sebstian for pointing this out.
2005-06-16 Timo Schulz <ts@g10code.com>
* engine-gpgme.c (check_encrypt_result): New. Check if
the encrypt procedure returned some invalid recipients.
(op_encrypt): Use it here.
(op_encrypt_file): Likewise.
(op_sign_encrypt): Likewise.
* missing.h: Removed unused constants.
* verify-dialog.c (load_sigbox): Handle v3 RSA keys.
* passphrase-dialog.c (load_secbox): Make sure the index
from the first loop matche the second. Which means skip
all invalid keys also.
2005-06-13 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (writeOptions): New Option 'defaultKey'.
(readOptions): Likewise. Force overwrite 'addDefaultKey'.
2005-06-07 Timo Schulz <ts@g10code.com>
* passphrase-dialog.c (decrypt_key_dlg_proc): Add a
reference to the key object so it will be still valid
after the dialog is destroyed.
* MapiGPGME.cpp (freeUnknownKeys): Do not try to free
the context if no keys are available. Fixed a segv.
(signEncrypt): The new code now gets a persistent pointer
to the key.
* engine-gpgme.c (op_sign_encrypt): Load the right
dialog to request the passphrase.
2005-06-05 Timo Schulz <ts@g10code.com>
* passphrase-dialog.c (load_recipbox): Check ctx if null.
(passphrase_callback_box): Different dialogs for sign
and decrypt.
(signer_dialog_box): Do not zero the context too early.
* keycache.c (enum_gpg_seckeys): Also reload if ctx
is NULL.
* MapiGPGME.cpp (signEncrypt): Return if the user
cancelled the signer selection dialog.
* recipient-dialog.c (recipient_dlg_proc): Check 'Text Mode'
button.
* keycache.c (enum_gpg_keys, enum_gpg_seckeys): Fully
reset the keycache initializing it again. Thanks to Ralf.
2005-06-04 Timo Schulz <ts@g10code.com>
* verify-dialog.c (load_sigbox): Only issue a warning
if the key exists but is not valid.
Get pkalgo from the signature.
Fixed format string problem s/%d/%s.
* config-dialog.c (load_config_value): Close reg handle.
(config_dlg_proc): Show error if the values could not
be written to the registry.
2005-06-03 Timo Schulz <ts@g10code.com>
* mapuser.c (new_usermap): New.
(free_usermap): New.
* engine-gpgme.c (op_decrypt): Return 'No_Seckey' if
appropriate and not just 'Decrypt_Failed'.
Set the gpgme_ctx_t object in the callback to allow
to list the 'encrypt_to' entries.
* passphrase-dialog.c (decrypt_key_dlg_proc): Make sure
we only warn when there is a valid callback context.
(load_secbox): New parameter 'ctlid'. Changed all callers.
(load_recipbox): New. Use usermap to lookup user-id's.
(decrypt_key_ext_dlg_proc): New dialog procedure for
the callback mode.
* HashTable.cpp (HashTable_new): New. C-interface.
(HashTable_free): Likewise.
(HashTable_get): Likewise.
(HashTable_put): Likewise.
(HashTable_get_i): Likewise.
(HashTable_size): Likewise.
2005-05-29 Timo Schulz <ts@g10code.com>
* passphrase-dialog.c (decrypt_key_dlg_proc): Warning
if the user cancels the signing process.
Make the passphrase field invisible if the key is used
in selection mode.
(recipient_dlg_proc): Likewise.
(signer_dialog_box): Return -1 if the user cancelled the
dialog.
* engine-gpgme.c (op_sign): Set flags to '1' to indicate
signing process.
* config-dialog.c (does_file_exist): Use appropriate
length for xmalloc. Noted by Sebastian.
2005-05-24 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (setXHeader): New.
(getXHeader): New.
* engine-gpgme.c (op_sign_file): Implemented.
2005-05-22 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (createAttachment): New.
(deleteAttachment): New.
(encryptAttachments): New.
(encrypt): Also encrypt the attachments if possible.
(signEncrypt): Likewise.
(setEncodingFormat): New.
(getEncodingFormat): New.
(readOptions, writeOptions): Store encoding format.
(MapiGPGME): The default encoding is 'CLASSIC'.
2005-05-21 Timo Schulz <ts@g10code.com>
* HashTable.h: Export functions.
* MapiGPGME.cpp (freeAttachments): New.
(getAttachments): New.
(openAttachment): New.
(closeAttachment): New.
(processAttachment): New.
(hasAttachments): New.
(countAttachments): New.
(doCmdFile): New. Can handle files.
(doCmdAttach): New. Can handle attachment action types.
(signEncrypt): Release locusr key.
* engine-gpgme.c (op_sign_file): New. Dummy.
(op_sign_encrypt_file): New. Dummy.
2005-05-11 Timo Schulz <ts@g10code.com>
* common.c (cache_item_new): New.
(cache_item_free): New.
* engine-gpgme.c (op_decrypt_start_ext): Return an cache item and
not just the passphrase. Changed all caller.
* MapiGPGME.cpp (passphraseCallback): Support caching.
(decrypt): Likewise.
(storePassphrase): Likewise.
(getPassphrase): Likewise.
* HashTable.cpp: New.
2005-05-10 Timo Schulz <ts@g10code.com>
* passphrase-dialog.c (decrypt_key_dlg_proc): Reset 'hide state'.
Show some text when the user entered a wrong passphrase.
* MapiGPGME.cpp (findMessageWindow): New.
(setRTFBody): New.
(decrypt): Just change the window text, not the MAPI object.
Call verify() if this is a clearsigned message.
(getMessageType): New.
(getAttachmentExtension): New.
(verify): Extract text and set it.
* engine-gpgme.c (op_decrypt): Spawn verify dialog if the text
was also signed.
(op_decrypt_file): New.
* verify-dialog.c (load_sigbox): Avoid key cache and give more
information.
* passphrase-dialog.c (decrypt_key_dlg_proc): Handle 'x' clicks.
* logging.c (log_debug): Disable it for release versions.
2005-05-08 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (readOptions): Handle logfile.
(writeOptions): Likewise.
(storePassphrase): New.
(clearPassphrase): New.
(passphraseCallback): New. Needs to be static...
(decrypt): Store passphrase if requested.
(~MapiGPGME): Free memory.
(streamOnFile): New.
(getAttachMethod): New.
(getAttachFilename): New.
(setAttachMethod): New.
(getAttachFilename): New.
(getMessageHasAttachments): New.
(getMessageFlags): New.
* engine-gpgme.c (op_decrypt): New. Factoured out
code from...
(op_decrypt_start): ..here. Now call op_decrypt
with standard parameters.
(op_decrypt_next): Allow to use a pre-defined
passphrase callback. Needed for caching.
2005-05-02 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (fail_if_null, delete_buf): New
(doCmd): New.
(setBody): If the body to set is empty, do nothing.
(freeKeyArray): New.
(readOptions): New.
(writeOptions): New.
Implement all getters and setters for the config code.
* keycache.c: Now that we use a DLL, we create a
shared data segment for static data.
(load_keycache_objects): New.
2005-05-01 Timo Schulz <ts@g10code.com>
* MapiGPGME.cpp (rtfSync): New.
* logging.c (log_debug): New.
* common.c (xfree): New.
* engine-gpgme.c (op_lookup_keys): Corrected offsets.
2005-04-29 Timo Schulz <ts@g10code.com>
* engine-gpgme.c (op_encrypt_file): New.
2005-04-27 Timo Schulz <ts@g10code.com>
* config-dialog.c (config_dialog_box): Add dialog
item to select a GUI key manager.
Check that the entered files really exist.
(config_dlg_proc): Likewise.
(does_file_exist): New.
2005-04-24 Timo Schulz <ts@g10code.com>
* main.c (DllMain): New. With a static library it was not
possible to have a separate resource file. Thus we use a
DLL now which contains all needed dialogs.
* common.c (set_global_hinstance): New.
* libgpgmedlgs.def: New.
2005-04-18 Timo Schulz <ts@g10code.com>
* recipient-dialog.c (recipient_dialog_box2): New
way to show pre-selected keys.
(copy_item): New paramenter for the pos.
(find_item): Do not select the item.
* gpgmedlgs.rc (IDD_ENC): New label to describe
the listbox.
2005-04-15 Timo Schulz <ts@g10code.com>
* common.c (xmalloc, xcalloc, xstrdup): New.
(out_of_core): New.
* recipient-dialog.c (initialize_keybox): New.
(find_item): New.
* MapiGPGME.cpp (freeUnknownKeys): New.
(signEncrypt): Show dialog to select a key if no
default key was set.
* Replace all std-c alloc functions with x equivalents.
2005-04-13 Timo Schulz <ts@g10code.com>
* engine-gpgme.c (do_init): Alloc keycache objects.
(do_deinit): Cleanup the mess.
(op_lookup_keys): New. Allow to find keys via the email.
* GPGME.cpp (MapiGPGME): New. MAPI interface.
2005-04-07 Timo Schulz <ts@g10code.com>
* verify-dialog.c (load_akalist): New.
(load_sigbox): Handle bad signatures.
* keycache.c (enum_gpg_keys): Allow to reset the
enum context.
* config-dialog.c (get_open_file_name): Use MAX_PATH.
(get_folder): Likewise.
* recipient-dialog.c (load_rsetbox): Modify code to
add the last keycache item.
* passphrase-dialog.c (load_secbox): Likewise.
diff --git a/src/message.cpp b/src/message.cpp
index 647d4c4..e450bdf 100644
--- a/src/message.cpp
+++ b/src/message.cpp
@@ -1,1289 +1,1301 @@
/* message.cpp - Functions for message handling
* Copyright (C) 2006, 2007, 2008 g10 Code GmbH
*
* This file is part of GpgOL.
*
* 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 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <windows.h>
#include "mymapi.h"
#include "mymapitags.h"
#include "myexchext.h"
#include "common.h"
#include "mapihelp.h"
#include "mimeparser.h"
#include "mimemaker.h"
#include "display.h"
#include "ol-ext-callback.h"
#include "message.h"
#define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
SRCNAME, __func__, __LINE__); \
} while (0)
static void
ul_release (LPVOID punk, const char *func)
{
ULONG res;
if (!punk)
return;
res = UlRelease (punk);
if (opt.enable_debug & DBG_MEMORY)
log_debug ("%s:%s: UlRelease(%p) had %lu references\n",
SRCNAME, func, punk, res);
}
/* A helper function used by OnRead and OnOpen to dispatch the
message. If FORCE is true, the force flag is passed to the
verification or decryption. Returns:
0 = Message has not been processed by us.
1 = Message has been processed and was not encrypted.
2 = Message has been processed by us and was possibly encrypted.
*/
int
message_incoming_handler (LPMESSAGE message, HWND hwnd, bool force)
{
int retval = 0;
msgtype_t msgtype;
int pass = 0;
retry:
pass++;
msgtype = mapi_get_message_type (message);
switch (msgtype)
{
case MSGTYPE_UNKNOWN:
/* If this message has never passed our change message class
code it won't have an unknown msgtype _and_ no sig status
flag. Thus we look at the message class now and change it if
required. It won't get displayed correctly right away but a
latter decrypt command or when viewed a second time all has
been set. Note that we should have similar code for some
message classes in GpgolUserEvents:OnSelectionChange; but
tehre are a couple of problems. */
if (pass == 1 && !force && !mapi_has_sig_status (message)
&& !opt.disable_gpgol)
{
log_debug ("%s:%s: message class not yet checked - doing now\n",
SRCNAME, __func__);
if (mapi_change_message_class (message, 0))
goto retry;
}
break;
case MSGTYPE_SMIME:
if (pass == 1 && !force && opt.enable_smime && !opt.disable_gpgol)
{
log_debug ("%s:%s: message class not checked with smime enabled "
"- doing now\n", SRCNAME, __func__);
if (mapi_change_message_class (message, 0))
goto retry;
}
break;
case MSGTYPE_GPGOL:
log_debug ("%s:%s: ignoring unknown message of original SMIME class\n",
SRCNAME, __func__);
break;
case MSGTYPE_GPGOL_MULTIPART_SIGNED:
log_debug ("%s:%s: processing multipart signed message\n",
SRCNAME, __func__);
retval = 1;
message_verify (message, msgtype, force, hwnd);
break;
case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED:
log_debug ("%s:%s: processing multipart encrypted message\n",
SRCNAME, __func__);
retval = 2;
message_decrypt (message, msgtype, force, hwnd);
break;
case MSGTYPE_GPGOL_OPAQUE_SIGNED:
log_debug ("%s:%s: processing opaque signed message\n",
SRCNAME, __func__);
retval = 1;
message_verify (message, msgtype, force, hwnd);
break;
case MSGTYPE_GPGOL_CLEAR_SIGNED:
log_debug ("%s:%s: processing clear signed pgp message\n",
SRCNAME, __func__);
retval = 1;
message_verify (message, msgtype, force, hwnd);
break;
case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED:
log_debug ("%s:%s: processing opaque encrypted message\n",
SRCNAME, __func__);
retval = 2;
message_decrypt (message, msgtype, force, hwnd);
break;
case MSGTYPE_GPGOL_PGP_MESSAGE:
log_debug ("%s:%s: processing pgp message\n", SRCNAME, __func__);
retval = 2;
message_decrypt (message, msgtype, force, hwnd);
break;
}
return retval;
}
/* Common Code used by OnReadComplete and OnOpenComplete to display a
modified message. Returns true if the message was encrypted. */
bool
message_display_handler (LPEXCHEXTCALLBACK eecb, HWND hwnd)
{
int err;
HRESULT hr;
LPMESSAGE message = NULL;
LPMDB mdb = NULL;
int ishtml, wasprotected = false;
char *body;
hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
if (SUCCEEDED (hr))
{
if (mapi_get_message_type (message) == MSGTYPE_GPGOL_CLEAR_SIGNED)
{
/* We used to display the clearsigned data in the processed
form, that is without the PGP lines and without the dash
escaping. However, this poses the problem that the user
does not notice that he is viewing a mail which was
signed using a deprecated method and - far worse - it
might update the PR_BODY and thus all signature
information will get lost. Of course we could save the
body away first like we do it with encrypted mails, but
that is too much overhead and GpgOL will always be
required to show such a message, which contrdicts the
very reason of clearsigned messages. */
log_debug ("%s:%s: skipping display update for ClearSigned\n",
SRCNAME, __func__);
}
else
{
err = mapi_get_gpgol_body_attachment (message, &body, NULL,
&ishtml, &wasprotected);
if (!err && body)
{
/* put_outlook_property (eecb, "GpgOLStatus", */
/* mapi_get_sig_status (message)); */
update_display (hwnd, eecb, wasprotected, ishtml, body);
}
else
{
/* put_outlook_property (eecb, "GpgOLStatus", "?"); */
update_display (hwnd, NULL, 0, 0,
_("[Crypto operation failed - "
"can't show the body of the message]"));
}
xfree (body);
}
}
else
log_debug_w32 (hr, "%s:%s: error getting message", SRCNAME, __func__);
ul_release (message, __func__);
ul_release (mdb, __func__);
return !!wasprotected;
}
/* Helper for message_wipe_body_cruft. */
static void
do_wipe_body (LPMESSAGE message)
{
if (!mapi_delete_body_props (message, KEEP_OPEN_READWRITE))
log_debug ("%s:%s: body cruft removed", SRCNAME, __func__);
}
/* If the current message is an encrypted one remove the body
properties which might have come up due to OL internal
syncronization and a failing olDiscard feature. */
void
message_wipe_body_cruft (LPEXCHEXTCALLBACK eecb)
{
HRESULT hr;
LPMESSAGE message = NULL;
LPMDB mdb = NULL;
log_debug ("%s:%s: enter", SRCNAME, __func__);
hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
if (SUCCEEDED (hr))
{
switch (mapi_get_message_type (message))
{
case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED:
case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED:
{
if (mapi_has_last_decrypted (message))
do_wipe_body (message);
else
log_debug_w32 (hr, "%s:%s: "
"error getting message decryption status",
SRCNAME, __func__);
}
break;
case MSGTYPE_GPGOL_PGP_MESSAGE:
{
/* In general we can't delete the body of a message if it
is an inline PGP encrypted message because the body
holds the ciphertext. However, while decrypting, we
take a copy of the body and work on that in future; if
this has been done we can delete the body. */
mapi_attach_item_t *table;
int found = 0;
int tblidx;
table = mapi_create_attach_table (message, 0);
if (table)
{
for (tblidx=0; !table[tblidx].end_of_table; tblidx++)
if (table[tblidx].attach_type == ATTACHTYPE_PGPBODY
&& table[tblidx].filename
&& !strcmp (table[tblidx].filename, PGPBODYFILENAME))
{
found = 1;
break;
}
}
mapi_release_attach_table (table);
if (found)
do_wipe_body (message);
}
break;
default:
break;
}
ul_release (message, __func__);
ul_release (mdb, __func__);
}
}
/* Display some information about MESSAGE. */
void
message_show_info (LPMESSAGE message, HWND hwnd)
{
char *msgcls = mapi_get_message_class (message);
char *sigstat = mapi_get_sig_status (message);
char *mimeinfo = mapi_get_mime_info (message);
size_t buflen;
char *buffer;
buflen = strlen (msgcls) + strlen (sigstat) + strlen (mimeinfo) + 200;
buffer = (char*)xmalloc (buflen+1);
snprintf (buffer, buflen,
_("Signature status: %s\n"
"Message class ..: %s\n"
"MIME structure .:\n"
"%s"),
sigstat,
msgcls,
mimeinfo);
MessageBox (hwnd, buffer, _("GpgOL - Message Information"),
MB_ICONINFORMATION|MB_OK);
xfree (buffer);
xfree (mimeinfo);
xfree (sigstat);
xfree (msgcls);
}
static void
show_message (HWND hwnd, const char *text)
{
MessageBox (hwnd, text, _("GpgOL"), MB_ICONINFORMATION|MB_OK);
}
/* Convert the clear signed message from INPUT into a PGP/MIME signed
message and return it in a new allocated buffer. OUTPUTLEN
received the valid length of that buffer; the buffer is guaranteed
to be Nul terminated. Note: Because we need to insert an empty
line to indicate the end of MIME headers, the signature won't
verify unless we tell the signature verification routine to skip
this first line. */
static char *
pgp_mime_from_clearsigned (LPSTREAM input, size_t *outputlen)
{
HRESULT hr;
STATSTG statinfo;
ULONG nread;
char *body = NULL;
char *p, *p0, *dest, *mark;
char boundary[BOUNDARYSIZE+1];
char top_header[200 + 2*BOUNDARYSIZE];
char sig_header[100 + BOUNDARYSIZE];
char end_header[10 + BOUNDARYSIZE];
size_t reserved_space;
int state;
*outputlen = 0;
/* Note that our parser does not make use of the micalg parameter. */
generate_boundary (boundary);
snprintf (top_header, sizeof top_header,
"MIME-Version: 1.0\r\n"
"Content-Type: multipart/signed; boundary=\"%s\";\r\n"
" protocol=\"application/pgp-signature\"\r\n"
"\r\n"
"--%s\r\n\r\n", boundary, boundary);
snprintf (sig_header, sizeof sig_header,
"--%s\r\n"
"Content-Type: application/pgp-signature\r\n"
"\r\n", boundary);
snprintf (end_header, sizeof end_header,
"\r\n"
"--%s--\r\n", boundary);
reserved_space = (strlen (top_header) + strlen (sig_header)
+ strlen (end_header)+ 100);
hr = input->Stat (&statinfo, STATFLAG_NONAME);
if (hr)
{
log_debug ("%s:%s: Stat failed: hr=%#lx", SRCNAME, __func__, hr);
return NULL;
}
body = (char*)xmalloc (reserved_space
+ (size_t)statinfo.cbSize.QuadPart + 2);
hr = input->Read (body+reserved_space,
(size_t)statinfo.cbSize.QuadPart, &nread);
if (hr)
{
log_debug ("%s:%s: Read failed: hr=%#lx", SRCNAME, __func__, hr);
xfree (body);
return NULL;
}
body[reserved_space + nread] = 0;
body[reserved_space + nread+1] = 0; /* Just in case this is
accidently an wchar_t. */
if (nread != statinfo.cbSize.QuadPart)
{
log_debug ("%s:%s: not enough bytes returned\n", SRCNAME, __func__);
xfree (body);
return NULL;
}
/* We do in place conversion. */
state = 0;
dest = NULL;
for (p=body+reserved_space; p && *p; p = (p=strchr (p+1, '\n'))? (p+1):NULL)
{
if (!state && !strncmp (p, "-----BEGIN PGP SIGNED MESSAGE-----", 34)
&& trailing_ws_p (p+34) )
{
dest = stpcpy (body, top_header);
state = 1;
}
else if (state == 1)
{
/* Wait for an empty line. */
if (trailing_ws_p (p))
state = 2;
}
else if (state == 2 && strncmp (p, "-----", 5))
{
/* Copy signed data. */
p0 = p;
if (*p == '-' && p[1] == ' ')
p +=2; /* Remove escaping. */
mark = NULL;
while (*p && *p != '\n')
{
if (*p == ' ' || *p == '\t' || *p == '\r')
{
if (!mark)
mark = dest;
}
else
mark = NULL;
*dest++ = *p++;
}
if (mark)
dest = mark;
if (*p == '\n')
{
if (p > p0 && p[-1] == '\r')
*dest++ = '\r';
*dest++ = '\n';
}
if (p > p0)
p--; /* Adjust so that the strchr (p+1, '\n') can work. */
}
else if (state == 2)
{
/* Armor line encountered. */
p0 = p;
if (strncmp (p, "-----BEGIN PGP SIGNATURE-----", 29)
|| !trailing_ws_p (p+29) )
fprintf (stderr,"Invalid clear signed message\n");
state = 3;
dest = stpcpy (dest, sig_header);
while (*p && *p != '\n')
*dest++ = *p++;
if (*p == '\n')
{
if (p[-1] == '\r')
*dest++ = '\r';
*dest++ = '\n';
}
if (p > p0)
p--; /* Adjust so that the strchr (p+1, '\n') can work. */
}
else if (state == 3 && strncmp (p, "-----", 5))
{
/* Copy signature. */
p0 = p;
while (*p && *p != '\n')
*dest++ = *p++;
if (*p == '\n')
{
if (p[-1] == '\r')
*dest++ = '\r';
*dest++ = '\n';
}
if (p > p0)
p--; /* Adjust so that the strchr (p+1, '\n') can work. */
}
else if (state == 3)
{
/* Armor line encountered. */
p0 = p;
if (strncmp (p, "-----END PGP SIGNATURE-----", 27)
|| !trailing_ws_p (p+27) )
fprintf (stderr,"Invalid clear signed message (no end)\n");
while (*p && *p != '\n')
*dest++ = *p++;
if (*p == '\n')
{
if (p[-1] == '\r')
*dest++ = '\r';
*dest++ = '\n';
}
dest = stpcpy (dest, end_header);
if (p > p0)
p--; /* Adjust so that the strchr (p+1, '\n') can work. */
break; /* Ah well, we can stop here. */
}
}
if (!dest)
{
xfree (body);
return NULL;
}
*dest = 0;
*outputlen = strlen (body);
return body;
}
/* Verify MESSAGE and update the attachments as required. MSGTYPE
should be the type of the message so that the fucntion can decide
what to do. With FORCE set the verification is done regardlessless
of a cached signature result. */
int
message_verify (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
{
mapi_attach_item_t *table = NULL;
LPSTREAM opaquestream = NULL;
int moss_idx = -1;
int i;
char *inbuf = NULL;
size_t inbuflen = 0;
protocol_t protocol = PROTOCOL_UNKNOWN;
int err;
int mimehack = 0;
switch (msgtype)
{
case MSGTYPE_GPGOL_MULTIPART_SIGNED:
case MSGTYPE_GPGOL_OPAQUE_SIGNED:
case MSGTYPE_GPGOL_CLEAR_SIGNED:
break;
case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED:
case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED:
case MSGTYPE_GPGOL_PGP_MESSAGE:
log_debug ("%s:%s: message of type %d not expected",
SRCNAME, __func__, msgtype);
if (force)
show_message (hwnd, _("Signature verification of an encrypted message "
"is not possible."));
return -1; /* Should not be called for such a message. */
case MSGTYPE_GPGOL:
case MSGTYPE_SMIME:
case MSGTYPE_UNKNOWN:
log_debug ("%s:%s: message of type %d ignored",
SRCNAME, __func__, msgtype);
if (!force)
;
else if (msgtype == MSGTYPE_GPGOL)
show_message (hwnd, _("Signature verification of this "
"message class is not possible."));
else if (msgtype == MSGTYPE_SMIME)
show_message (hwnd, _("Signature verification of this "
"S/MIME message is not possible. Please check "
"that S/MIME processing has been enabled."));
else
show_message (hwnd, _("This message has no signature."));
return 0; /* Nothing to do. */
}
/* If a verification is forced, we set the cached signature status
first to "?" to mark that no verification has yet happened. If a
verification status has been set and the body attachment is
available we don't do a verification again. The need to check
for the body attachment is to avoid problems if that attachment
has accidently be deleted. */
if (force)
mapi_set_sig_status (message, "?");
else if (mapi_test_sig_status (message)
&& !mapi_get_gpgol_body_attachment (message, NULL,NULL,NULL,NULL))
return 0; /* Already checked that message. */
if (msgtype == MSGTYPE_GPGOL_CLEAR_SIGNED)
{
/* PGP's clear signed messages are special: All is contained in
the body and thus there is no requirement for an
attachment. */
LPSTREAM rawstream;
rawstream = mapi_get_body_as_stream (message);
if (!rawstream)
return -1;
inbuf = pgp_mime_from_clearsigned (rawstream, &inbuflen);
rawstream->Release ();
if (!inbuf)
return -1;
protocol = PROTOCOL_OPENPGP;
mimehack = 1; /* Required for our made up PGP/MIME. */
}
else if (msgtype == MSGTYPE_GPGOL_OPAQUE_SIGNED)
{
/* S/MIME opaque signed message: The data is expected to be in
an attachment. */
table = mapi_create_attach_table (message, 0);
if (!table)
return -1; /* No attachment - this should not happen. */
for (i=0; !table[i].end_of_table; i++)
if (table[i].content_type
&& (!strcmp (table[i].content_type, "application/pkcs7-mime")
|| !strcmp (table[i].content_type,
"application/x-pkcs7-mime"))
&& table[i].filename
&& !strcmp (table[i].filename, "smime.p7m"))
break;
if (table[i].end_of_table)
{
log_debug ("%s:%s: attachment for opaque signed S/MIME not found",
SRCNAME, __func__);
mapi_release_attach_table (table);
return -1;
}
opaquestream = mapi_get_attach_as_stream (message, table+i, NULL);
if (!opaquestream)
{
mapi_release_attach_table (table);
return -1; /* Problem getting the attachment. */
}
protocol = PROTOCOL_SMIME;
}
else
{
/* PGP/MIME or S/MIME stuff. */
table = mapi_create_attach_table (message, 0);
if (!table)
return -1; /* No attachment - this should not happen. */
for (i=0; !table[i].end_of_table; i++)
if (table[i].attach_type == ATTACHTYPE_MOSS)
{
moss_idx = i;
break;
}
if (moss_idx == -1 && !table[0].end_of_table && table[1].end_of_table)
{
/* No MOSS flag found in the table but there is only one
attachment. Due to the message type we know that this is
the original MOSS message. We mark this attachment as
hidden, so that it won't get displayed. We further mark
it as our original MOSS attachment so that after parsing
we have a mean to find it again (see above). */
moss_idx = 0;
mapi_mark_moss_attach (message, table+0);
}
if (moss_idx == -1)
{
mapi_release_attach_table (table);
return -1; /* No original attachment - this should not happen. */
}
inbuf = mapi_get_attach (message, 0, table+0, &inbuflen);
if (!inbuf)
{
mapi_release_attach_table (table);
return -1; /* Problem getting the attachment. */
}
}
if (opaquestream)
err = mime_verify_opaque (protocol, opaquestream,
NULL, 0, message, hwnd, 0, 0);
else
err = mime_verify (protocol, inbuf, inbuflen, message, hwnd, 0, mimehack);
log_debug ("mime_verify%s returned %d", opaquestream? "_opaque":"", err);
if (err && opt.enable_debug)
{
char buf[200];
snprintf (buf, sizeof buf, "Verify failed (%s)", gpg_strerror (err));
MessageBox (NULL, buf, "GpgOL", MB_ICONINFORMATION|MB_OK);
}
if (opaquestream)
opaquestream->Release ();
xfree (inbuf);
if (err)
{
char buf[200];
snprintf (buf, sizeof buf, "- %s", gpg_strerror (err));
mapi_set_sig_status (message, gpg_strerror (err));
}
else
mapi_set_sig_status (message, "! Good signature");
mapi_save_changes (message, KEEP_OPEN_READWRITE);
mapi_release_attach_table (table);
return 0;
}
/* Copy the MAPI body to a PGPBODY type attachment. */
static int
pgp_body_to_attachment (LPMESSAGE message)
{
HRESULT hr;
LPSTREAM instream;
ULONG newpos;
LPATTACH newatt = NULL;
SPropValue prop;
LPSTREAM outstream = NULL;
LPUNKNOWN punk;
instream = mapi_get_body_as_stream (message);
if (!instream)
return -1;
hr = message->CreateAttach (NULL, 0, &newpos, &newatt);
if (hr)
{
log_error ("%s:%s: can't create attachment: hr=%#lx\n",
SRCNAME, __func__, hr);
goto leave;
}
prop.ulPropTag = PR_ATTACH_METHOD;
prop.Value.ul = ATTACH_BY_VALUE;
hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);
if (hr)
{
log_error ("%s:%s: can't set attach method: hr=%#lx\n",
SRCNAME, __func__, hr);
goto leave;
}
/* Mark that attachment so that we know why it has been created. */
if (get_gpgolattachtype_tag (message, &prop.ulPropTag) )
goto leave;
prop.Value.l = ATTACHTYPE_PGPBODY;
hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);
if (hr)
{
log_error ("%s:%s: can't set %s property: hr=%#lx\n",
SRCNAME, __func__, "GpgOL Attach Type", hr);
goto leave;
}
prop.ulPropTag = PR_ATTACHMENT_HIDDEN;
prop.Value.b = TRUE;
hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);
if (hr)
{
log_error ("%s:%s: can't set hidden attach flag: hr=%#lx\n",
SRCNAME, __func__, hr);
goto leave;
}
prop.ulPropTag = PR_ATTACH_FILENAME_A;
prop.Value.lpszA = PGPBODYFILENAME;
hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);
if (hr)
{
log_error ("%s:%s: can't set attach filename: hr=%#lx\n",
SRCNAME, __func__, hr);
goto leave;
}
punk = (LPUNKNOWN)outstream;
hr = newatt->OpenProperty (PR_ATTACH_DATA_BIN, &IID_IStream, 0,
MAPI_CREATE|MAPI_MODIFY, &punk);
if (FAILED (hr))
{
log_error ("%s:%s: can't create output stream: hr=%#lx\n",
SRCNAME, __func__, hr);
goto leave;
}
outstream = (LPSTREAM)punk;
/* Insert a blank line so that our mime parser skips over the mail
headers. */
hr = outstream->Write ("\r\n", 2, NULL);
if (hr)
{
log_error ("%s:%s: Write failed: hr=%#lx", SRCNAME, __func__, hr);
goto leave;
}
{
ULARGE_INTEGER cb;
cb.QuadPart = 0xffffffffffffffffll;
hr = instream->CopyTo (outstream, cb, NULL, NULL);
}
if (hr)
{
log_error ("%s:%s: can't copy streams: hr=%#lx\n",
SRCNAME, __func__, hr);
goto leave;
}
hr = outstream->Commit (0);
if (hr)
{
log_error ("%s:%s: Commiting output stream failed: hr=%#lx",
SRCNAME, __func__, hr);
goto leave;
}
outstream->Release ();
outstream = NULL;
hr = newatt->SaveChanges (0);
if (hr)
{
log_error ("%s:%s: SaveChanges of the attachment failed: hr=%#lx\n",
SRCNAME, __func__, hr);
goto leave;
}
newatt->Release ();
newatt = NULL;
hr = mapi_save_changes (message, KEEP_OPEN_READWRITE);
leave:
if (outstream)
{
outstream->Revert ();
outstream->Release ();
}
if (newatt)
newatt->Release ();
instream->Release ();
return hr? -1:0;
}
/* Decrypt MESSAGE, check signature and update the attachments as
required. MSGTYPE should be the type of the message so that the
function can decide what to do. With FORCE set the decryption is
done regardless whether it has already been done. */
int
message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
{
mapi_attach_item_t *table = NULL;
int part1_idx, part2_idx;
int tblidx;
int retval = -1;
LPSTREAM cipherstream;
gpg_error_t err, sig_err;
int is_opaque = 0;
protocol_t protocol;
LPATTACH saved_attach = NULL;
int need_saved_attach = 0;
int need_rfc822_parser = 0;
int is_simple_pgp = 0;
switch (msgtype)
{
case MSGTYPE_UNKNOWN:
case MSGTYPE_SMIME:
case MSGTYPE_GPGOL:
case MSGTYPE_GPGOL_OPAQUE_SIGNED:
case MSGTYPE_GPGOL_MULTIPART_SIGNED:
case MSGTYPE_GPGOL_CLEAR_SIGNED:
if (force)
show_message (hwnd, _("This message is not encrypted."));
return -1; /* Should not have been called for this. */
case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED:
break;
case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED:
is_opaque = 1;
break;
case MSGTYPE_GPGOL_PGP_MESSAGE:
break;
}
if (!force && mapi_test_last_decrypted (message))
return 0; /* Already decrypted this message once during this
session. No need to do it again. */
if (msgtype == MSGTYPE_GPGOL_PGP_MESSAGE)
{
/* PGP messages are special: All is contained in the body and
thus there would be no requirement for an attachment.
However, due to problems with Outlook overwriting the body of
the message after decryption, we need to save the body away
before decrypting it. We then always look for that original
body attachment or create one if it does not exist. */
part1_idx = -1;
table = mapi_create_attach_table (message, 0);
if (!table)
;
else
{
for (tblidx=0; !table[tblidx].end_of_table; tblidx++)
if (table[tblidx].attach_type == ATTACHTYPE_PGPBODY
&& table[tblidx].filename
&& !strcmp (table[tblidx].filename, PGPBODYFILENAME))
{
part1_idx = tblidx;
break;
}
}
if (part1_idx == -1)
{
mapi_release_attach_table (table);
if (pgp_body_to_attachment (message))
table = NULL;
else
table = mapi_create_attach_table (message, 0);
if (table)
{
for (tblidx=0; !table[tblidx].end_of_table; tblidx++)
if (table[tblidx].attach_type == ATTACHTYPE_PGPBODY
&& table[tblidx].filename
&& !strcmp (table[tblidx].filename, PGPBODYFILENAME))
{
part1_idx = tblidx;
break;
}
}
}
if (!table || part1_idx == -1)
{
log_debug ("%s:%s: problem copying the PGP inline encrypted message",
SRCNAME, __func__);
goto leave;
}
cipherstream = mapi_get_attach_as_stream (message, table+part1_idx,
NULL);
if (!cipherstream)
goto leave; /* Problem getting the attachment. */
protocol = PROTOCOL_OPENPGP;
need_rfc822_parser = 1;
is_simple_pgp = 1;
}
else
{
/* PGP/MIME or S/MIME stuff. */
table = mapi_create_attach_table (message, 0);
if (!table)
goto leave; /* No attachment - this should not happen. */
if (is_opaque)
{
/* S/MIME opaque encrypted message: We expect one
attachment. As we don't know wether we are called the
first time, we first try to find this attachment by
looking at all attachments. Only if this fails we
identify it by its order. */
part2_idx = -1;
for (tblidx=0; !table[tblidx].end_of_table; tblidx++)
if (table[tblidx].attach_type == ATTACHTYPE_MOSSTEMPL)
{
/* This attachment has been generated by us in the
course of sending a new message. The content will
be multipart/signed because we used this to trick
out OL. We stop here and use this part for further
processing. */
part2_idx = tblidx;
need_rfc822_parser = 1;
break;
}
else if (table[tblidx].attach_type == ATTACHTYPE_MOSS)
{
if (part2_idx == -1 && table[tblidx].content_type
&& (!strcmp (table[tblidx].content_type,
"application/pkcs7-mime")
|| !strcmp (table[tblidx].content_type,
"application/x-pkcs7-mime")))
part2_idx = tblidx;
}
if (part2_idx == -1 && tblidx >= 1)
{
/* We have attachments but none are marked. Thus we
assume that this is the first time we see this
message and we will set the mark now if we see
appropriate content types. */
if (table[0].content_type
&& (!strcmp (table[0].content_type, "application/pkcs7-mime")
|| !strcmp (table[0].content_type,
"application/x-pkcs7-mime")))
part2_idx = 0;
if (part2_idx != -1)
mapi_mark_moss_attach (message, table+part2_idx);
}
if (part2_idx == -1)
{
log_debug ("%s:%s: this is not an S/MIME encrypted message",
SRCNAME, __func__);
goto leave;
}
protocol = PROTOCOL_SMIME;
}
else
{
/* Multipart/encrypted message: We expect 2 attachments.
The first one with the version number and the second one
with the ciphertext. As we don't know wether we are
called the first time, we first try to find these
attachments by looking at all attachments. Only if this
fails we identify them by their order (i.e. the first 2
attachments) and mark them as part1 and part2. */
part1_idx = part2_idx = -1;
for (tblidx=0; !table[tblidx].end_of_table; tblidx++)
if (table[tblidx].attach_type == ATTACHTYPE_MOSS)
{
if (part1_idx == -1 && table[tblidx].content_type
&& !strcmp (table[tblidx].content_type,
"application/pgp-encrypted"))
part1_idx = tblidx;
else if (part2_idx == -1 && table[tblidx].content_type
&& !strcmp (table[tblidx].content_type,
"application/octet-stream"))
part2_idx = tblidx;
}
if (part1_idx == -1 && part2_idx == -1 && tblidx >= 2)
{
/* At least 2 attachments but none are marked. Thus we
assume that this is the first time we see this
message and we will set the mark now if we see
appropriate content types. */
if (table[0].content_type
&& !strcmp (table[0].content_type,
"application/pgp-encrypted"))
part1_idx = 0;
if (table[1].content_type
&& !strcmp (table[1].content_type,
"application/octet-stream"))
part2_idx = 1;
if (part1_idx != -1 && part2_idx != -1)
{
mapi_mark_moss_attach (message, table+part1_idx);
mapi_mark_moss_attach (message, table+part2_idx);
}
}
if (part1_idx == -1 || part2_idx == -1
&& !table[0].end_of_table && table[1].end_of_table
&& table[0].attach_type == ATTACHTYPE_MOSS
&& table[0].filename
&& !strcmp (table[0].filename, MIMEATTACHFILENAME))
{
/* This is likely a PGP/MIME created by us. Due to the
way we created that message, the MAPI derived content
type is wrong and there is only one attachment
(gpgolXXX.dat). We simply assume that it is PGP/MIME
encrypted and pass it on to the mime parser. We also
keep the attachment open so that we can later set it
to hidden if not yet done. I can't remember whether
it is possible to set the hidden attribute when
creating the message - probably not. Thus we take
care of it here. */
log_debug ("%s:%s: "
"assuming self-created PGP/MIME encrypted message",
SRCNAME, __func__);
part2_idx = 0;
need_saved_attach = 1;
}
else if (part1_idx == -1 || part2_idx == -1)
{
log_debug ("%s:%s: this is not a PGP/MIME encrypted message",
SRCNAME, __func__);
goto leave;
}
protocol = PROTOCOL_OPENPGP;
}
cipherstream = mapi_get_attach_as_stream (message, table+part2_idx,
need_saved_attach?
&saved_attach : NULL );
if (!cipherstream)
goto leave; /* Problem getting the attachment. */
}
sig_err = gpg_error (GPG_ERR_NO_DATA);
err = mime_decrypt (protocol, cipherstream, message,
need_rfc822_parser, is_simple_pgp, hwnd, 0, &sig_err);
log_debug ("mime_decrypt returned %d (%s)", err, gpg_strerror (err));
if (err && opt.enable_debug)
{
char buf[200];
switch (gpg_err_code (err))
{
case GPG_ERR_NO_DATA:
/* The UI server already displayed a message. */
break;
default:
snprintf (buf, sizeof buf,
_("Decryption failed\n(%s)"), gpg_strerror (err));
MessageBox (NULL, buf, "GpgOL", MB_ICONINFORMATION|MB_OK);
break;
}
}
else if (!err)
{
if (saved_attach)
mapi_set_attach_hidden (saved_attach);
if (gpg_err_code (sig_err) != GPG_ERR_NO_DATA)
{
/* Note: Saving the result of the signature in a property
will reveal that there is a signature inside the
encrypted message - however it does reveal only a
common assumption and thus it is acceptable to do
this. */
if (sig_err)
{
char buf[200];
snprintf (buf, sizeof buf, "- %s", gpg_strerror (sig_err));
mapi_set_sig_status (message, gpg_strerror (sig_err));
}
else
mapi_set_sig_status (message, "! Good signature");
mapi_save_changes (message, KEEP_OPEN_READWRITE);
}
}
cipherstream->Release ();
retval = 0;
leave:
if (saved_attach)
saved_attach->Release ();
mapi_release_attach_table (table);
return retval;
}
/* Return an array of strings with the recipients of the message. On
success a malloced array is returned containing allocated strings
for each recipient. The end of the array is marked by NULL.
Caller is responsible for releasing the array. On failure NULL is
returned. */
static char **
get_recipients (LPMESSAGE message)
{
static SizedSPropTagArray (1L, PropRecipientNum) = {1L, {PR_EMAIL_ADDRESS}};
HRESULT hr;
LPMAPITABLE lpRecipientTable = NULL;
LPSRowSet lpRecipientRows = NULL;
unsigned int rowidx;
LPSPropValue row;
char **rset;
int rsetidx;
if (!message)
return NULL;
hr = message->GetRecipientTable (0, &lpRecipientTable);
if (FAILED (hr))
{
log_debug_w32 (-1, "%s:%s: GetRecipientTable failed", SRCNAME, __func__);
return NULL;
}
hr = HrQueryAllRows (lpRecipientTable, (LPSPropTagArray) &PropRecipientNum,
NULL, NULL, 0L, &lpRecipientRows);
if (FAILED (hr))
{
log_debug_w32 (-1, "%s:%s: HrQueryAllRows failed", SRCNAME, __func__);
if (lpRecipientTable)
lpRecipientTable->Release();
return NULL;
}
rset = (char**)xcalloc (lpRecipientRows->cRows+1, sizeof *rset);
for (rowidx=0, rsetidx=0; rowidx < lpRecipientRows->cRows; rowidx++)
{
if (!lpRecipientRows->aRow[rowidx].cValues)
continue;
row = lpRecipientRows->aRow[rowidx].lpProps;
switch (PROP_TYPE (row->ulPropTag))
{
case PT_UNICODE:
if ((rset[rsetidx] = wchar_to_utf8 (row->Value.lpszW)))
rsetidx++;
else
log_debug ("%s:%s: error converting recipient to utf8\n",
SRCNAME, __func__);
break;
case PT_STRING8: /* Assume ASCII. */
rset[rsetidx++] = xstrdup (row->Value.lpszA);
break;
default:
log_debug ("%s:%s: proptag=0x%08lx not supported\n",
SRCNAME, __func__, row->ulPropTag);
break;
}
}
if (lpRecipientTable)
lpRecipientTable->Release();
if (lpRecipientRows)
FreeProws(lpRecipientRows);
log_debug ("%s:%s: got %d recipients:\n", SRCNAME, __func__, rsetidx);
for (rsetidx=0; rset[rsetidx]; rsetidx++)
log_debug ("%s:%s: \t`%s'\n", SRCNAME, __func__, rset[rsetidx]);
return rset;
}
static void
release_recipient_array (char **recipients)
{
int idx;
if (recipients)
{
for (idx=0; recipients[idx]; idx++)
xfree (recipients[idx]);
xfree (recipients);
}
}
static int
sign_encrypt (LPMESSAGE message, protocol_t protocol, HWND hwnd, int signflag)
{
gpg_error_t err;
char **recipients;
recipients = get_recipients (message);
if (!recipients || !recipients[0])
{
MessageBox (hwnd, _("No recipients to encrypt to are given"),
"GpgOL", MB_ICONERROR|MB_OK);
err = gpg_error (GPG_ERR_GENERAL);
}
else
{
if (signflag)
err = mime_sign_encrypt (message, hwnd, protocol, recipients);
else
err = mime_encrypt (message, hwnd, protocol, recipients);
- if (err && opt.enable_debug)
+ if (gpg_err_code (err) == GPG_ERR_NO_DATA)
+ {
+ MessageBox (hwnd, _("Encrypting or signing an empty message "
+ "is not possible."),
+ "GpgOL", MB_ICONERROR|MB_OK);
+ }
+ else if (err && opt.enable_debug)
{
char buf[200];
snprintf (buf, sizeof buf,
_("Encryption failed (%s)"), gpg_strerror (err));
MessageBox (hwnd, buf, "GpgOL", MB_ICONERROR|MB_OK);
}
}
release_recipient_array (recipients);
return err;
}
/* Sign the MESSAGE. */
int
message_sign (LPMESSAGE message, protocol_t protocol, HWND hwnd)
{
gpg_error_t err;
err = mime_sign (message, hwnd, protocol);
- if (err && opt.enable_debug)
+ if (gpg_err_code (err) == GPG_ERR_NO_DATA)
+ {
+ MessageBox (hwnd, _("Encrypting or signing an empty message "
+ "is not possible."),
+ "GpgOL", MB_ICONERROR|MB_OK);
+ }
+ else if (err && opt.enable_debug)
{
char buf[200];
snprintf (buf, sizeof buf,
_("Signing failed (%s)"), gpg_strerror (err));
MessageBox (hwnd, buf, "GpgOL", MB_ICONERROR|MB_OK);
}
return err;
}
/* Encrypt the MESSAGE. */
int
message_encrypt (LPMESSAGE message, protocol_t protocol, HWND hwnd)
{
return sign_encrypt (message, protocol, hwnd, 0);
}
/* Sign+Encrypt the MESSAGE. */
int
message_sign_encrypt (LPMESSAGE message, protocol_t protocol, HWND hwnd)
{
return sign_encrypt (message, protocol, hwnd, 1);
}
diff --git a/src/mimemaker.c b/src/mimemaker.c
index 0b393eb..8358be3 100644
--- a/src/mimemaker.c
+++ b/src/mimemaker.c
@@ -1,1838 +1,1877 @@
/* mimemaker.c - Construct MIME message out of a MAPI
* Copyright (C) 2007, 2008 g10 Code GmbH
*
* This file is part of GpgOL.
*
* 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 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#define COBJMACROS
#include <windows.h>
#include <objidl.h>
#include "mymapi.h"
#include "mymapitags.h"
#include "common.h"
#include "engine.h"
#include "mapihelp.h"
#include "mimemaker.h"
#define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
SRCNAME, __func__, __LINE__); \
} while (0)
static const char oid_mimetag[] =
{0x2A, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x03, 0x0a, 0x04};
/* The base-64 list used for base64 encoding. */
static unsigned char bintoasc[64+1] = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/");
/* The object we use instead of IStream. It allows us to have a
callback method for output and thus for processing stuff
recursively. */
struct sink_s;
typedef struct sink_s *sink_t;
struct sink_s
{
void *cb_data;
sink_t extrasink;
int (*writefnc)(sink_t sink, const void *data, size_t datalen);
unsigned long enc_counter; /* Used by write_buffer_for_cb. */
/* struct { */
/* int idx; */
/* unsigned char inbuf[4]; */
/* int quads; */
/* } b64; */
};
/* Object used to collect data in a memory buffer. */
struct databuf_s
{
size_t len; /* Used length. */
size_t size; /* Allocated length of BUF. */
char *buf; /* Malloced buffer. */
};
/*** local prototypes ***/
static int write_multistring (sink_t sink, const char *text1,
...) GPGOL_GCC_A_SENTINEL(0);
/* Standard write method used with a sink_t object. */
static int
sink_std_write (sink_t sink, const void *data, size_t datalen)
{
HRESULT hr;
LPSTREAM stream = sink->cb_data;
if (!stream)
{
log_error ("%s:%s: sink not setup for writing", SRCNAME, __func__);
return -1;
}
if (!data)
return 0; /* Flush - nothing to do here. */
hr = IStream_Write (stream, data, datalen, NULL);
if (hr)
{
log_error ("%s:%s: Write failed: hr=%#lx", SRCNAME, __func__, hr);
return -1;
}
return 0;
}
/* Make sure that PROTOCOL is usable or return a suitable protocol.
On error PROTOCOL_UNKNOWN is returned. */
static protocol_t
check_protocol (protocol_t protocol)
{
switch (protocol)
{
case PROTOCOL_UNKNOWN:
return PROTOCOL_UNKNOWN;
case PROTOCOL_OPENPGP:
case PROTOCOL_SMIME:
return protocol;
}
log_error ("%s:%s: BUG", SRCNAME, __func__);
return PROTOCOL_UNKNOWN;
}
/* Create a new MAPI attchment for MESSAGE which will be used to
prepare the MIME message. On sucess the stream to write the data
to is stored at STREAM and the attachment object itself is
returned. The caller needs to call SaveChanges. Returns NULL on
failure in which case STREAM will be set to NULL. */
static LPATTACH
create_mapi_attachment (LPMESSAGE message, sink_t sink)
{
HRESULT hr;
ULONG pos;
SPropValue prop;
LPATTACH att = NULL;
LPUNKNOWN punk;
sink->cb_data = NULL;
sink->writefnc = NULL;
hr = IMessage_CreateAttach (message, NULL, 0, &pos, &att);
if (hr)
{
log_error ("%s:%s: can't create attachment: hr=%#lx\n",
SRCNAME, __func__, hr);
return NULL;
}
prop.ulPropTag = PR_ATTACH_METHOD;
prop.Value.ul = ATTACH_BY_VALUE;
hr = HrSetOneProp ((LPMAPIPROP)att, &prop);
if (hr)
{
log_error ("%s:%s: can't set attach method: hr=%#lx\n",
SRCNAME, __func__, hr);
goto failure;
}
/* Mark that attachment so that we know why it has been created. */
if (get_gpgolattachtype_tag (message, &prop.ulPropTag) )
goto failure;
prop.Value.l = ATTACHTYPE_MOSSTEMPL;
hr = HrSetOneProp ((LPMAPIPROP)att, &prop);
if (hr)
{
log_error ("%s:%s: can't set %s property: hr=%#lx\n",
SRCNAME, __func__, "GpgOL Attach Type", hr);
goto failure;
}
/* We better insert a short filename. */
prop.ulPropTag = PR_ATTACH_FILENAME_A;
prop.Value.lpszA = MIMEATTACHFILENAME;
hr = HrSetOneProp ((LPMAPIPROP)att, &prop);
if (hr)
{
log_error ("%s:%s: can't set attach filename: hr=%#lx\n",
SRCNAME, __func__, hr);
goto failure;
}
/* Even for encrypted messages we need to set the MAPI property to
multipart/signed. This seems to be a part of the trigger which
leads OL to process such a message in a special way. */
prop.ulPropTag = PR_ATTACH_TAG;
prop.Value.bin.cb = sizeof oid_mimetag;
prop.Value.bin.lpb = (LPBYTE)oid_mimetag;
hr = HrSetOneProp ((LPMAPIPROP)att, &prop);
if (!hr)
{
prop.ulPropTag = PR_ATTACH_MIME_TAG_A;
prop.Value.lpszA = "multipart/signed";
hr = HrSetOneProp ((LPMAPIPROP)att, &prop);
}
if (hr)
{
log_error ("%s:%s: can't set attach mime tag: hr=%#lx\n",
SRCNAME, __func__, hr);
goto failure;
}
punk = NULL;
hr = IAttach_OpenProperty (att, PR_ATTACH_DATA_BIN, &IID_IStream, 0,
(MAPI_CREATE|MAPI_MODIFY), &punk);
if (FAILED (hr))
{
log_error ("%s:%s: can't create output stream: hr=%#lx\n",
SRCNAME, __func__, hr);
goto failure;
}
sink->cb_data = (LPSTREAM)punk;
sink->writefnc = sink_std_write;
return att;
failure:
IAttach_Release (att);
return NULL;
}
/* Write data to a sink_t. */
static int
write_buffer (sink_t sink, const void *data, size_t datalen)
{
if (!sink || !sink->writefnc)
{
log_error ("%s:%s: sink not properly setup", SRCNAME, __func__);
return -1;
}
return sink->writefnc (sink, data, datalen);
}
/* Same as above but used for passing as callback function. This
fucntion does not return an error code but the number of bytes
written. */
static int
write_buffer_for_cb (void *opaque, const void *data, size_t datalen)
{
sink_t sink = opaque;
sink->enc_counter += datalen;
return write_buffer (sink, data, datalen) ? -1 : datalen;
}
/* Write the string TEXT to the IStream STREAM. Returns 0 on sucsess,
prints an error message and returns -1 on error. */
static int
write_string (sink_t sink, const char *text)
{
return write_buffer (sink, text, strlen (text));
}
/* Write the string TEXT1 and all folloing arguments of type (const
char*) to the SINK. The list of argumens needs to be terminated
with a NULL. Returns 0 on sucsess, prints an error message and
returns -1 on error. */
static int
write_multistring (sink_t sink, const char *text1, ...)
{
va_list arg_ptr;
int rc;
const char *s;
va_start (arg_ptr, text1);
s = text1;
do
rc = write_string (sink, s);
while (!rc && (s=va_arg (arg_ptr, const char *)));
va_end (arg_ptr);
return rc;
}
/* Helper to write a boundary to the output sink. The leading LF
will be written as well. */
static int
write_boundary (sink_t sink, const char *boundary, int lastone)
{
int rc = write_string (sink, "\r\n--");
if (!rc)
rc = write_string (sink, boundary);
if (!rc)
rc = write_string (sink, lastone? "--\r\n":"\r\n");
return rc;
}
/* Write DATALEN bytes of DATA to SINK in base64 encoding. This
creates a complete Base64 chunk including the trailing fillers. */
static int
write_b64 (sink_t sink, const void *data, size_t datalen)
{
int rc;
const unsigned char *p;
unsigned char inbuf[4];
int idx, quads;
char outbuf[4];
log_debug (" writing base64 of length %d\n", (int)datalen);
idx = quads = 0;
for (p = data; datalen; p++, datalen--)
{
inbuf[idx++] = *p;
if (idx > 2)
{
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];
if ((rc = write_buffer (sink, outbuf, 4)))
return rc;
idx = 0;
if (++quads >= (64/4))
{
quads = 0;
if ((rc = write_buffer (sink, "\r\n", 2)))
return rc;
}
}
}
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] = '=';
}
if ((rc = write_buffer (sink, outbuf, 4)))
return rc;
++quads;
}
if (quads)
if ((rc = write_buffer (sink, "\r\n", 2)))
return rc;
return 0;
}
/* Write DATALEN bytes of DATA to SINK in quoted-prinable encoding. */
static int
write_qp (sink_t sink, const void *data, size_t datalen)
{
int rc;
const unsigned char *p;
char outbuf[80]; /* We only need 76 octect + 2 for the lineend. */
int outidx;
/* Check whether the current character is followed by a line ending.
Note that the end of the etxt also counts as a lineending */
#define nextlf_p() ((datalen > 2 && p[1] == '\r' && p[2] == '\n') \
|| (datalen > 1 && p[1] == '\n') \
|| datalen == 1 )
/* Macro to insert a soft line break if needed. */
# define do_softlf(n) \
do { \
if (outidx + (n) > 76 \
|| (outidx + (n) == 76 && !nextlf_p())) \
{ \
outbuf[outidx++] = '='; \
outbuf[outidx++] = '\r'; \
outbuf[outidx++] = '\n'; \
if ((rc = write_buffer (sink, outbuf, outidx))) \
return rc; \
outidx = 0; \
} \
} while (0)
log_debug (" writing qp of length %d\n", (int)datalen);
outidx = 0;
for (p = data; datalen; p++, datalen--)
{
if ((datalen > 1 && *p == '\r' && p[1] == '\n') || *p == '\n')
{
/* Line break. */
outbuf[outidx++] = '\r';
outbuf[outidx++] = '\n';
if ((rc = write_buffer (sink, outbuf, outidx)))
return rc;
outidx = 0;
if (*p == '\r')
{
p++;
datalen--;
}
}
else if (*p == '\t' || *p == ' ')
{
/* Check whether tab or space is followed by a line break
which forbids verbatim encoding. If we are already at
the end of the buffer we take that as a line end too. */
if (nextlf_p())
{
do_softlf (3);
outbuf[outidx++] = '=';
outbuf[outidx++] = tohex ((*p>>4)&15);
outbuf[outidx++] = tohex (*p&15);
}
else
{
do_softlf (1);
outbuf[outidx++] = *p;
}
}
else if (!outidx && *p == '.' && nextlf_p () )
{
/* We better protect a line with just a single dot. */
outbuf[outidx++] = '=';
outbuf[outidx++] = tohex ((*p>>4)&15);
outbuf[outidx++] = tohex (*p&15);
}
else if (!outidx && datalen >= 5 && !memcmp (p, "From ", 5))
{
/* Protect the 'F' so that MTAs won't prefix the "From "
with an '>' */
outbuf[outidx++] = '=';
outbuf[outidx++] = tohex ((*p>>4)&15);
outbuf[outidx++] = tohex (*p&15);
}
else if (*p >= '!' && *p <= '~' && *p != '=')
{
do_softlf (1);
outbuf[outidx++] = *p;
}
else
{
do_softlf (3);
outbuf[outidx++] = '=';
outbuf[outidx++] = tohex ((*p>>4)&15);
outbuf[outidx++] = tohex (*p&15);
}
}
if (outidx)
{
outbuf[outidx++] = '\r';
outbuf[outidx++] = '\n';
if ((rc = write_buffer (sink, outbuf, outidx)))
return rc;
}
# undef do_softlf
# undef nextlf_p
return 0;
}
/* Write DATALEN bytes of DATA to SINK in plain ascii encoding. */
static int
write_plain (sink_t sink, const void *data, size_t datalen)
{
int rc;
const unsigned char *p;
char outbuf[100];
int outidx;
log_debug (" writing ascii of length %d\n", (int)datalen);
outidx = 0;
for (p = data; datalen; p++, datalen--)
{
if ((datalen > 1 && *p == '\r' && p[1] == '\n') || *p == '\n')
{
outbuf[outidx++] = '\r';
outbuf[outidx++] = '\n';
if ((rc = write_buffer (sink, outbuf, outidx)))
return rc;
outidx = 0;
if (*p == '\r')
{
p++;
datalen--;
}
}
else if (!outidx && *p == '.'
&& ( (datalen > 2 && p[1] == '\r' && p[2] == '\n')
|| (datalen > 1 && p[1] == '\n')
|| datalen == 1))
{
/* Better protect a line with just a single dot. We do
this by adding a space. */
outbuf[outidx++] = *p;
outbuf[outidx++] = ' ';
}
else if (outidx > 80)
{
/* We should never be called for too long lines - QP should
have been used. */
log_error ("%s:%s: BUG: line longer than exepcted",
SRCNAME, __func__);
return -1;
}
else
outbuf[outidx++] = *p;
}
if (outidx)
{
outbuf[outidx++] = '\r';
outbuf[outidx++] = '\n';
if ((rc = write_buffer (sink, outbuf, outidx)))
return rc;
}
return 0;
}
/* Infer the conent type from DATA and FILENAME. The return value is
a static string there won't be an error return. In case Bae 64
encoding is required for the type true will be stored at FORCE_B64;
however, this is only a shortcut and if that is not set, the caller
should infer the encoding by otehr means. */
static const char *
infer_content_type (const char *data, size_t datalen, const char *filename,
int is_mapibody, int *force_b64)
{
static struct {
char b64;
const char *suffix;
const char *ct;
} suffix_table[] =
{
{ 1, "3gp", "video/3gpp" },
{ 1, "abw", "application/x-abiword" },
{ 1, "ai", "application/postscript" },
{ 1, "au", "audio/basic" },
{ 1, "bin", "application/octet-stream" },
{ 1, "class", "application/java-vm" },
{ 1, "cpt", "application/mac-compactpro" },
{ 0, "css", "text/css" },
{ 0, "csv", "text/comma-separated-values" },
{ 1, "deb", "application/x-debian-package" },
{ 1, "dl", "video/dl" },
{ 1, "doc", "application/msword" },
{ 1, "dv", "video/dv" },
{ 1, "dvi", "application/x-dvi" },
{ 1, "eml", "message/rfc822" },
{ 1, "eps", "application/postscript" },
{ 1, "fig", "application/x-xfig" },
{ 1, "flac", "application/x-flac" },
{ 1, "fli", "video/fli" },
{ 1, "gif", "image/gif" },
{ 1, "gl", "video/gl" },
{ 1, "gnumeric", "application/x-gnumeric" },
{ 1, "hqx", "application/mac-binhex40" },
{ 1, "hta", "application/hta" },
{ 0, "htm", "text/html" },
{ 0, "html", "text/html" },
{ 0, "ics", "text/calendar" },
{ 1, "jar", "application/java-archive" },
{ 1, "jpeg", "image/jpeg" },
{ 1, "jpg", "image/jpeg" },
{ 1, "js", "application/x-javascript" },
{ 1, "latex", "application/x-latex" },
{ 1, "lha", "application/x-lha" },
{ 1, "lzh", "application/x-lzh" },
{ 1, "lzx", "application/x-lzx" },
{ 1, "m3u", "audio/mpegurl" },
{ 1, "m4a", "audio/mpeg" },
{ 1, "mdb", "application/msaccess" },
{ 1, "midi", "audio/midi" },
{ 1, "mov", "video/quicktime" },
{ 1, "mp2", "audio/mpeg" },
{ 1, "mp3", "audio/mpeg" },
{ 1, "mp4", "video/mp4" },
{ 1, "mpeg", "video/mpeg" },
{ 1, "mpega", "audio/mpeg" },
{ 1, "mpg", "video/mpeg" },
{ 1, "mpga", "audio/mpeg" },
{ 1, "msi", "application/x-msi" },
{ 1, "mxu", "video/vnd.mpegurl" },
{ 1, "nb", "application/mathematica" },
{ 1, "oda", "application/oda" },
{ 1, "odb", "application/vnd.oasis.opendocument.database" },
{ 1, "odc", "application/vnd.oasis.opendocument.chart" },
{ 1, "odf", "application/vnd.oasis.opendocument.formula" },
{ 1, "odg", "application/vnd.oasis.opendocument.graphics" },
{ 1, "odi", "application/vnd.oasis.opendocument.image" },
{ 1, "odm", "application/vnd.oasis.opendocument.text-master" },
{ 1, "odp", "application/vnd.oasis.opendocument.presentation" },
{ 1, "ods", "application/vnd.oasis.opendocument.spreadsheet" },
{ 1, "odt", "application/vnd.oasis.opendocument.text" },
{ 1, "ogg", "application/ogg" },
{ 1, "otg", "application/vnd.oasis.opendocument.graphics-template" },
{ 1, "oth", "application/vnd.oasis.opendocument.text-web" },
{ 1, "otp", "application/vnd.oasis.opendocument.presentation-template"},
{ 1, "ots", "application/vnd.oasis.opendocument.spreadsheet-template"},
{ 1, "ott", "application/vnd.oasis.opendocument.text-template" },
{ 1, "pdf", "application/pdf" },
{ 1, "png", "image/png" },
{ 1, "pps", "application/vnd.ms-powerpoint" },
{ 1, "ppt", "application/vnd.ms-powerpoint" },
{ 1, "prf", "application/pics-rules" },
{ 1, "ps", "application/postscript" },
{ 1, "qt", "video/quicktime" },
{ 1, "rar", "application/rar" },
{ 1, "rdf", "application/rdf+xml" },
{ 1, "rpm", "application/x-redhat-package-manager" },
{ 0, "rss", "application/rss+xml" },
{ 1, "ser", "application/java-serialized-object" },
{ 0, "sh", "application/x-sh" },
{ 0, "shtml", "text/html" },
{ 1, "sid", "audio/prs.sid" },
{ 0, "smil", "application/smil" },
{ 1, "snd", "audio/basic" },
{ 0, "svg", "image/svg+xml" },
{ 1, "tar", "application/x-tar" },
{ 0, "texi", "application/x-texinfo" },
{ 0, "texinfo", "application/x-texinfo" },
{ 1, "tif", "image/tiff" },
{ 1, "tiff", "image/tiff" },
{ 1, "torrent", "application/x-bittorrent" },
{ 1, "tsp", "application/dsptype" },
{ 0, "vrml", "model/vrml" },
{ 1, "vsd", "application/vnd.visio" },
{ 1, "wp5", "application/wordperfect5.1" },
{ 1, "wpd", "application/wordperfect" },
{ 0, "xhtml", "application/xhtml+xml" },
{ 1, "xlb", "application/vnd.ms-excel" },
{ 1, "xls", "application/vnd.ms-excel" },
{ 1, "xlt", "application/vnd.ms-excel" },
{ 0, "xml", "application/xml" },
{ 0, "xsl", "application/xml" },
{ 0, "xul", "application/vnd.mozilla.xul+xml" },
{ 1, "zip", "application/zip" },
{ 0, NULL, NULL }
};
int i;
char suffix_buffer[12+1];
const char *suffix;
*force_b64 = 0;
suffix = filename? strrchr (filename, '.') : NULL;
if (suffix && strlen (suffix) < sizeof suffix_buffer -1 )
{
suffix++;
for (i=0; i < sizeof suffix_buffer - 1; i++)
suffix_buffer[i] = tolower (*(const unsigned char*)suffix);
suffix_buffer[i] = 0;
for (i=0; suffix_table[i].suffix; i++)
if (!strcmp (suffix_table[i].suffix, suffix_buffer))
{
if (suffix_table[i].b64)
*force_b64 = 1;
return suffix_table[i].ct;
}
}
/* Not found via filename, look at the content. */
if (is_mapibody)
{
/* Fixme: This is too simple. */
if (datalen > 6 && (!memcmp (data, "<html>", 6)
||!memcmp (data, "<HTML>", 6)))
return "text/html";
return "text/plain";
}
return "application/octet-stream";
}
/* Figure out the best encoding to be used for the part. Return values are
0: Plain ASCII.
1: Quoted Printable
2: Base64 */
static int
infer_content_encoding (const void *data, size_t datalen)
{
const unsigned char *p;
int need_qp;
size_t len, maxlen, highbin, lowbin, ntotal;
ntotal = datalen;
len = maxlen = lowbin = highbin = 0;
need_qp = 0;
for (p = data; datalen; p++, datalen--)
{
len++;
if ((*p & 0x80))
highbin++;
else if ((datalen > 1 && *p == '\r' && p[1] == '\n') || *p == '\n')
{
len--;
if (len > maxlen)
maxlen = len;
len = 0;
}
else if (*p == '\r')
{
/* CR not followed by a linefeed. */
lowbin++;
}
else if (*p == '\t' || *p == ' ' || *p == '\f')
;
else if (*p < ' ' || *p == 127)
lowbin++;
else if (len == 1 && datalen > 2
&& *p == '-' && p[1] == '-' && p[2] == ' '
&& ( (datalen > 4 && p[3] == '\r' && p[4] == '\n')
|| (datalen > 3 && p[3] == '\n')
|| datalen == 3))
{
/* This is a "-- \r\n" line, thus it indicates the usual
signature line delimiter. We need to protect the
trailing space. */
need_qp = 1;
}
else if (len == 1 && datalen > 5 && !memcmp (p, "--=-=", 5))
{
/* This look pretty much like a our own boundary.
We better protect it by forcing QP encoding. */
need_qp = 1;
}
else if (len == 1 && datalen >= 5 && !memcmp (p, "From ", 5))
{
/* The usual From hack is required so that MTAs do not
prefix it with an '>'. */
need_qp = 1;
}
}
if (len > maxlen)
maxlen = len;
if (maxlen <= 76 && !lowbin && !highbin && !need_qp)
return 0; /* Plain ASCII is sufficient. */
/* Somewhere in the Outlook documentation 20% is mentioned as
discriminating value for Base64. Though our counting won't be
identical we use that value to behave closely to it. */
if (ntotal && ((float)(lowbin+highbin))/ntotal < 0.20)
return 1; /* Use quoted printable. */
return 2; /* Use base64. */
}
/* Write a MIME part to SINK. First the BOUNDARY is written (unless
it is NULL) then the DATA is analyzed and appropriate headers are
written. If FILENAME is given it will be added to the part's
header. IS_MAPIBODY should be passed as true if the data has been
retrieved from the body property. */
static int
write_part (sink_t sink, const char *data, size_t datalen,
const char *boundary, const char *filename, int is_mapibody)
{
int rc;
const char *ct;
int use_b64, use_qp, is_text;
if (filename)
{
/* If there is a filename strip the directory part. Take care
that there might be slashes of backslashes. */
const char *s1 = strrchr (filename, '/');
const char *s2 = strrchr (filename, '\\');
if (!s1)
s1 = s2;
else if (s1 && s2 && s2 > s1)
s1 = s2;
if (s1)
filename = s1;
if (*filename && filename[1] == ':')
filename += 2;
if (!*filename)
filename = NULL;
}
log_debug ("Writing part of length %d%s filename=`%s'\n",
(int)datalen, is_mapibody? " (body)":"",
filename?filename:"[none]");
ct = infer_content_type (data, datalen, filename, is_mapibody, &use_b64);
use_qp = 0;
if (!use_b64)
{
switch (infer_content_encoding (data, datalen))
{
case 0: break;
case 1: use_qp = 1; break;
default: use_b64 = 1; break;
}
}
is_text = !strncmp (ct, "text/", 5);
if (boundary)
if ((rc = write_boundary (sink, boundary, 0)))
return rc;
if ((rc=write_multistring (sink,
"Content-Type: ", ct,
(is_text || filename? ";\r\n" :"\r\n"),
NULL)))
return rc;
/* OL inserts a charset parameter in many cases, so we do it right
away for all text parts. We can assume us-ascii if no special
encoding is required. */
if (is_text)
if ((rc=write_multistring (sink,
"\tcharset=\"",
(!use_qp && !use_b64? "us-ascii" : "utf-8"),
filename ? "\";\r\n" : "\"\r\n",
NULL)))
return rc;
if (filename)
if ((rc=write_multistring (sink,
"\tname=\"", filename, "\"\r\n",
NULL)))
return rc;
/* Note that we need to output even 7bit because OL inserts that
anyway. */
if ((rc = write_multistring (sink,
"Content-Transfer-Encoding: ",
(use_b64? "base64\r\n":
use_qp? "quoted-printable\r\n":"7bit\r\n"),
NULL)))
return rc;
if (filename)
if ((rc=write_multistring (sink,
"Content-Disposition: attachment;\r\n"
"\tfilename=\"", filename, "\"\r\n",
NULL)))
return rc;
/* Write delimiter. */
if ((rc = write_string (sink, "\r\n")))
return rc;
/* Write the content. */
if (use_b64)
rc = write_b64 (sink, data, datalen);
else if (use_qp)
rc = write_qp (sink, data, datalen);
else
rc = write_plain (sink, data, datalen);
return rc;
}
/* Return the number of attachments in TABLE to be put into the MIME
message. */
static int
count_usable_attachments (mapi_attach_item_t *table)
{
int idx, count = 0;
if (table)
for (idx=0; !table[idx].end_of_table; idx++)
if (table[idx].attach_type == ATTACHTYPE_UNKNOWN
&& table[idx].method == ATTACH_BY_VALUE)
count++;
return count;
}
/* Write out all attachments from TABLE separated by BOUNDARY to SINK.
This function needs to be syncronized with count_usable_attachments. */
static int
write_attachments (sink_t sink,
LPMESSAGE message, mapi_attach_item_t *table,
const char *boundary)
{
int idx, rc;
char *buffer;
size_t buflen;
if (table)
for (idx=0; !table[idx].end_of_table; idx++)
if (table[idx].attach_type == ATTACHTYPE_UNKNOWN
&& table[idx].method == ATTACH_BY_VALUE)
{
buffer = mapi_get_attach (message, 0, table+idx, &buflen);
if (!buffer)
log_debug ("Attachment at index %d not found\n", idx);
else
log_debug ("Attachment at index %d: length=%d\n", idx, (int)buflen);
if (!buffer)
return -1;
rc = write_part (sink, buffer, buflen, boundary,
table[idx].filename, 0);
xfree (buffer);
}
return 0;
}
/* Delete all attachments from TABLE except for the one we just created */
static int
delete_all_attachments (LPMESSAGE message, mapi_attach_item_t *table)
{
HRESULT hr;
int idx;
if (table)
for (idx=0; !table[idx].end_of_table; idx++)
{
if (table[idx].attach_type == ATTACHTYPE_MOSSTEMPL
&& table[idx].filename
&& !strcmp (table[idx].filename, MIMEATTACHFILENAME))
continue;
hr = IMessage_DeleteAttach (message, table[idx].mapipos, 0, NULL, 0);
if (hr)
{
log_error ("%s:%s: DeleteAttach failed: hr=%#lx\n",
SRCNAME, __func__, hr);
return -1;
}
}
return 0;
}
/* Commit changes to the attachment ATTACH and release the object.
SINK needs to be passed as well and will also be closed. Note that
the address of ATTACH is expected so that the fucntion can set it
to NULL. */
static int
close_mapi_attachment (LPATTACH *attach, sink_t sink)
{
HRESULT hr;
LPSTREAM stream = sink? sink->cb_data : NULL;
if (!stream)
{
log_error ("%s:%s: sink not setup", SRCNAME, __func__);
return -1;
}
hr = IStream_Commit (stream, 0);
if (hr)
{
log_error ("%s:%s: Commiting output stream failed: hr=%#lx",
SRCNAME, __func__, hr);
return -1;
}
IStream_Release (stream);
sink->cb_data = NULL;
hr = IAttach_SaveChanges (*attach, 0);
if (hr)
{
log_error ("%s:%s: SaveChanges of the attachment failed: hr=%#lx\n",
SRCNAME, __func__, hr);
return -1;
}
IAttach_Release (*attach);
*attach = NULL;
return 0;
}
/* Cancel changes to the attachment ATTACH and release the object.
SINK needs to be passed as well and will also be closed. Note that
the address of ATTACH is expected so that the fucntion can set it
to NULL. */
static void
cancel_mapi_attachment (LPATTACH *attach, sink_t sink)
{
LPSTREAM stream = sink? sink->cb_data : NULL;
if (stream)
{
IStream_Revert (stream);
IStream_Release (stream);
sink->cb_data = NULL;
}
if (*attach)
{
/* Fixme: Should we try to delete it or is there a Revert method? */
IAttach_Release (*attach);
*attach = NULL;
}
}
/* Do the final processing for a message. */
static int
finalize_message (LPMESSAGE message, mapi_attach_item_t *att_table,
protocol_t protocol, int encrypt)
{
HRESULT hr;
SPropValue prop;
/* Set the message class. */
prop.ulPropTag = PR_MESSAGE_CLASS_A;
prop.Value.lpszA = "IPM.Note.SMIME.MultipartSigned";
hr = IMessage_SetProps (message, 1, &prop, NULL);
if (hr)
{
log_error ("%s:%s: error setting the message class: hr=%#lx\n",
SRCNAME, __func__, hr);
return -1;
}
/* Set a special property so that we are later able to identify
messages signed or encrypted by us. */
if (mapi_set_sig_status (message, "@"))
return -1;
/* We also need to set the message class into our custom
property. This override is at leas required for encrypted
messages. */
if (mapi_set_gpgol_msg_class (message,
(encrypt?
(protocol == PROTOCOL_SMIME?
"IPM.Note.GpgOL.OpaqueEncrypted" :
"IPM.Note.GpgOL.MultipartEncrypted") :
"IPM.Note.GpgOL.MultipartSigned")))
return -1;
/* Now delete all parts of the MAPI message except for the one
attachment we just created. */
if (delete_all_attachments (message, att_table))
return -1;
return mapi_save_changes (message, KEEP_OPEN_READWRITE|FORCE_SAVE);
}
/* Sink write method used by mime_sign. We write the data to the
filter and also to the EXTRASINK but we don't pass a flush request
to EXTRASINK. */
static int
sink_hashing_write (sink_t hashsink, const void *data, size_t datalen)
{
int rc;
engine_filter_t filter = hashsink->cb_data;
if (!filter || !hashsink->extrasink)
{
log_error ("%s:%s: sink not setup for writing", SRCNAME, __func__);
return -1;
}
rc = engine_filter (filter, data, datalen);
if (!rc && data && datalen)
write_buffer (hashsink->extrasink, data, datalen);
return rc;
}
/* This function is called by the filter to collect the output which
is a detached signature. */
static int
collect_signature (void *opaque, const void *data, size_t datalen)
{
struct databuf_s *db = opaque;
if (db->len + datalen >= db->size)
{
db->size += datalen + 1024;
db->buf = xrealloc (db->buf, db->size);
}
memcpy (db->buf + db->len, data, datalen);
db->len += datalen;
return datalen;
}
/* Helper to create the signing header. This includes enough space
for later fixup of the micalg parameter. The MIME version is only
written if FIRST is set. */
static void
create_top_signing_header (char *buffer, size_t buflen, protocol_t protocol,
int first, const char *boundary, const char *micalg)
{
snprintf (buffer, buflen,
"%s"
"Content-Type: multipart/signed;\r\n"
"\tprotocol=\"application/%s\";\r\n"
"\tmicalg=%-15.15s;\r\n"
"\tboundary=\"%s\"\r\n"
"\r\n",
first? "MIME-Version: 1.0\r\n":"",
(protocol==PROTOCOL_OPENPGP? "pgp-signature":"pkcs7-signature"),
micalg, boundary);
}
/* Main body of mime_sign without the the code to delete the original
attachments. On success the function returns the current
attachment table at R_ATT_TABLE or sets this to NULL on error. If
TMPSINK is set no attachment will be created but the output
written to that sink. */
static int
do_mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol,
mapi_attach_item_t **r_att_table, sink_t tmpsink)
{
int result = -1;
int rc;
- LPATTACH attach;
+ LPATTACH attach = NULL;
struct sink_s sinkmem;
sink_t sink = &sinkmem;
struct sink_s hashsinkmem;
sink_t hashsink = &hashsinkmem;
char boundary[BOUNDARYSIZE+1];
char inner_boundary[BOUNDARYSIZE+1];
mapi_attach_item_t *att_table = NULL;
char *body = NULL;
int n_att_usable;
char top_header[BOUNDARYSIZE+200];
- engine_filter_t filter;
+ engine_filter_t filter = NULL;
struct databuf_s sigbuffer;
*r_att_table = NULL;
memset (sink, 0, sizeof *sink);
memset (hashsink, 0, sizeof *hashsink);
memset (&sigbuffer, 0, sizeof sigbuffer);
if (tmpsink)
{
attach = NULL;
sink = tmpsink;
}
else
{
attach = create_mapi_attachment (message, sink);
if (!attach)
return -1;
}
- /* Prepare the signing. */
- if (engine_create_filter (&filter, collect_signature, &sigbuffer))
- goto failure;
- if (engine_sign_start (filter, hwnd, protocol,
- mapi_get_sender (message), &protocol))
- goto failure;
-
- protocol = check_protocol (protocol);
- if (protocol == PROTOCOL_UNKNOWN)
- {
- log_error ("%s:%s: no protocol selected", SRCNAME, __func__);
- goto failure;
- }
-
-
/* Get the attachment info and the body. */
body = mapi_get_body (message, NULL);
if (body && !*body)
{
xfree (body);
body = NULL;
}
att_table = mapi_create_attach_table (message, 0);
n_att_usable = count_usable_attachments (att_table);
if (!n_att_usable && !body)
{
log_debug ("%s:%s: can't sign an empty message\n", SRCNAME, __func__);
+ result = gpg_error (GPG_ERR_NO_DATA);
goto failure;
}
+ /* Prepare the signing. */
+ if (engine_create_filter (&filter, collect_signature, &sigbuffer))
+ goto failure;
+ if (engine_sign_start (filter, hwnd, protocol,
+ mapi_get_sender (message), &protocol))
+ goto failure;
+
+ protocol = check_protocol (protocol);
+ if (protocol == PROTOCOL_UNKNOWN)
+ {
+ log_error ("%s:%s: no protocol selected", SRCNAME, __func__);
+ goto failure;
+ }
+
+
/* Write the top header. */
generate_boundary (boundary);
create_top_signing_header (top_header, sizeof top_header,
protocol, 1, boundary, "xxx");
if ((rc = write_string (sink, top_header)))
goto failure;
/* Create the inner boundary if we have a body and at least one
attachment or more than one attachment. */
if ((body && n_att_usable) || n_att_usable > 1)
generate_boundary (inner_boundary);
else
*inner_boundary = 0;
/* Write the boundary so that it is not included in the hashing. */
if ((rc = write_boundary (sink, boundary, 0)))
goto failure;
/* Create a new sink for hashing and write/hash our content. */
hashsink->cb_data = filter;
hashsink->extrasink = sink;
hashsink->writefnc = sink_hashing_write;
/* Note that OL2003 will add an extra line after the multipart
header, thus we do the same to avoid running all through an
IConverterSession first. */
if (*inner_boundary
&& (rc=write_multistring (hashsink,
"Content-Type: multipart/mixed;\r\n",
"\tboundary=\"", inner_boundary, "\"\r\n",
"\r\n", /* <-- extra line */
NULL)))
goto failure;
if (body)
rc = write_part (hashsink, body, strlen (body),
*inner_boundary? inner_boundary : NULL, NULL, 1);
if (!rc && n_att_usable)
rc = write_attachments (hashsink, message, att_table,
*inner_boundary? inner_boundary : NULL);
if (rc)
goto failure;
xfree (body);
body = NULL;
/* Finish the possible multipart/mixed. */
if (*inner_boundary && (rc = write_boundary (hashsink, inner_boundary, 1)))
goto failure;
/* Here we are ready with the hashing. Flush the filter and wait
for the signing process to finish. */
if ((rc = write_buffer (hashsink, NULL, 0)))
goto failure;
if ((rc = engine_wait (filter)))
goto failure;
filter = NULL; /* Not valid anymore. */
hashsink->cb_data = NULL; /* Not needed anymore. */
/* Write signature attachment. */
if ((rc = write_boundary (sink, boundary, 0)))
goto failure;
if ((rc=write_string (sink,
(protocol == PROTOCOL_OPENPGP
? "Content-Type: application/pgp-signature\r\n"
: ("Content-Transfer-Encoding: base64\r\n"
"Content-Type: application/pkcs7-signature\r\n")
))))
goto failure;
/* If we would add "Content-Transfer-Encoding: 7bit\r\n" to this
attachment, Outlooks does not proceed with sending and even does
not return any error. A wild guess is that while OL adds this
header itself, it detects that it already exists and somehow gets
into a problem. It is not a problem with the other parts,
though. Hmmm, triggered by the top levels CT protocol parameter?
Anyway, it is not required that we add it as we won't hash it.
Note, that this only holds for OpenPGP; for S/MIME we need to set
set CTE. We even write it before the CT because that is the same
as Outlook would do it for a missing CTE. */
if ((rc = write_string (sink, "\r\n")))
goto failure;
/* Write the signature. We add an extra CR,LF which should not harm
and a terminating 0. */
collect_signature (&sigbuffer, "\r\n", 3);
if ((rc = write_string (sink, sigbuffer.buf)))
goto failure;
/* Write the final boundary and finish the attachment. */
if ((rc = write_boundary (sink, boundary, 1)))
goto failure;
/* Fixup the micalg parameter. */
{
HRESULT hr;
LARGE_INTEGER off;
LPSTREAM stream = sink->cb_data;
off.QuadPart = 0;
hr = IStream_Seek (stream, off, STREAM_SEEK_SET, NULL);
if (hr)
{
log_error ("%s:%s: seeking back to the begin failed: hr=%#lx",
SRCNAME, __func__, hr);
goto failure;
}
create_top_signing_header (top_header, sizeof top_header,
protocol, 1, boundary,
protocol == PROTOCOL_SMIME? "sha1":"pgp-sha1");
hr = IStream_Write (stream, top_header, strlen (top_header), NULL);
if (hr)
{
log_error ("%s:%s: writing fixed micalg failed: hr=%#lx",
SRCNAME, __func__, hr);
goto failure;
}
/* Better seek again to the end. */
off.QuadPart = 0;
hr = IStream_Seek (stream, off, STREAM_SEEK_END, NULL);
if (hr)
{
log_error ("%s:%s: seeking back to the end failed: hr=%#lx",
SRCNAME, __func__, hr);
goto failure;
}
}
if (attach)
{
if (close_mapi_attachment (&attach, sink))
goto failure;
}
result = 0; /* Everything is fine, fall through the cleanup now. */
failure:
engine_cancel (filter);
if (attach)
cancel_mapi_attachment (&attach, sink);
xfree (body);
if (result)
mapi_release_attach_table (att_table);
else
*r_att_table = att_table;
xfree (sigbuffer.buf);
return result;
}
/* Sign the MESSAGE using PROTOCOL. If PROTOCOL is PROTOCOL_UNKNOWN
the engine decides what protocol to use. On return MESSAGE is
modified so that sending it will result in a properly MOSS (that is
PGP or S/MIME) signed message. On failure the function tries to
keep the original message intact but there is no 100% guarantee for
it. */
int
mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol)
{
int result = -1;
mapi_attach_item_t *att_table;
- if (!do_mime_sign (message, hwnd, protocol, &att_table, 0))
+ result = do_mime_sign (message, hwnd, protocol, &att_table, 0);
+ if (!result)
{
if (!finalize_message (message, att_table, protocol, 0))
result = 0;
}
mapi_release_attach_table (att_table);
return result;
}
/* Sink write method used by mime_encrypt. */
static int
sink_encryption_write (sink_t encsink, const void *data, size_t datalen)
{
engine_filter_t filter = encsink->cb_data;
if (!filter)
{
log_error ("%s:%s: sink not setup for writing", SRCNAME, __func__);
return -1;
}
return engine_filter (filter, data, 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.*/
/* Helper from mime_encrypt. BOUNDARY is a buffer of at least
BOUNDARYSIZE+1 bytes which will be set on return from that
function. */
static int
create_top_encryption_header (sink_t sink, protocol_t protocol, char *boundary)
{
int rc;
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"
"\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)
return rc;
/* Write the PGP/MIME encrypted part. */
rc = write_boundary (sink, boundary, 0);
if (rc)
return rc;
rc = write_multistring (sink,
"Content-Type: application/pgp-encrypted\r\n"
"\r\n"
"Version: 1\r\n", NULL);
if (rc)
return rc;
/* And start the second part. */
rc = write_boundary (sink, boundary, 0);
if (rc)
return rc;
rc = write_multistring (sink,
"Content-Type: application/octet-stream\r\n"
"\r\n", NULL);
}
return rc;
}
/* Encrypt the MESSAGE. */
int
mime_encrypt (LPMESSAGE message, HWND hwnd,
protocol_t protocol, char **recipients)
{
int result = -1;
int rc;
LPATTACH attach;
struct sink_s sinkmem;
sink_t sink = &sinkmem;
struct sink_s encsinkmem;
sink_t encsink = &encsinkmem;
char boundary[BOUNDARYSIZE+1];
char inner_boundary[BOUNDARYSIZE+1];
mapi_attach_item_t *att_table = NULL;
char *body = NULL;
int n_att_usable;
- engine_filter_t filter;
+ engine_filter_t filter = NULL;
memset (sink, 0, sizeof *sink);
memset (encsink, 0, sizeof *encsink);
attach = create_mapi_attachment (message, sink);
if (!attach)
return -1;
- /* Prepare the encryption. We do this early as it is quite common
- that some recipient keys are not available and thus the
- encryption will fail early. */
- if (engine_create_filter (&filter, write_buffer_for_cb, sink))
- goto failure;
- if (engine_encrypt_prepare (filter, hwnd, protocol, recipients, &protocol))
- goto failure;
- if (engine_encrypt_start (filter, 0))
- goto failure;
-
- protocol = check_protocol (protocol);
- if (protocol == PROTOCOL_UNKNOWN)
- goto failure;
-
- /* Get the attachment info and the body. */
+ /* Get the attachment info and the body. We need to do this before
+ creating the engine's filter sue problem sending the cancel to
+ the engine with nothing for the engine to process. This is
+ actually a bug in our engine code but we better avoid triggering
+ this bug because the engine sometimes hangs. Fixme: Needs a
+ proper fix. */
body = mapi_get_body (message, NULL);
if (body && !*body)
{
xfree (body);
body = NULL;
}
att_table = mapi_create_attach_table (message, 0);
n_att_usable = count_usable_attachments (att_table);
if (!n_att_usable && !body)
{
log_debug ("%s:%s: can't encrypt an empty message\n", SRCNAME, __func__);
+ result = gpg_error (GPG_ERR_NO_DATA);
goto failure;
}
+ /* Prepare the encryption. We do this early as it is quite common
+ that some recipient keys are not available and thus the
+ encryption will fail early. */
+ if (engine_create_filter (&filter, write_buffer_for_cb, sink))
+ goto failure;
+ if (engine_encrypt_prepare (filter, hwnd, protocol, recipients, &protocol))
+ goto failure;
+ if (engine_encrypt_start (filter, 0))
+ goto failure;
+
+ protocol = check_protocol (protocol);
+ if (protocol == PROTOCOL_UNKNOWN)
+ goto failure;
+
/* Write the top header. */
rc = create_top_encryption_header (sink, protocol, boundary);
if (rc)
goto failure;
/* Create a new sink for encrypting the following stuff. */
encsink->cb_data = filter;
encsink->writefnc = sink_encryption_write;
if ((body && n_att_usable) || n_att_usable > 1)
{
/* A body and at least one attachment or more than one attachment */
generate_boundary (inner_boundary);
if ((rc=write_multistring (encsink,
"Content-Type: multipart/mixed;\r\n",
"\tboundary=\"", inner_boundary, "\"\r\n",
NULL)))
goto failure;
}
else /* Only one part. */
*inner_boundary = 0;
if (body)
rc = write_part (encsink, body, strlen (body),
*inner_boundary? inner_boundary : NULL, NULL, 1);
if (!rc && n_att_usable)
rc = write_attachments (encsink, message, att_table,
*inner_boundary? inner_boundary : NULL);
if (rc)
goto failure;
xfree (body);
body = NULL;
/* Finish the possible multipart/mixed. */
if (*inner_boundary && (rc = write_boundary (encsink, inner_boundary, 1)))
goto failure;
/* Flush the encryption sink and wait for the encryption to get
ready. */
if ((rc = write_buffer (encsink, NULL, 0)))
goto failure;
if ((rc = engine_wait (filter)))
goto failure;
filter = NULL; /* Not valid anymore. */
encsink->cb_data = NULL; /* Not needed anymore. */
if (!sink->enc_counter)
{
log_debug ("%s:%s: nothing received from engine", SRCNAME, __func__);
goto failure;
}
/* 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;
if (finalize_message (message, att_table, protocol, 1))
goto failure;
result = 0; /* Everything is fine, fall through the cleanup now. */
failure:
engine_cancel (filter);
cancel_mapi_attachment (&attach, sink);
xfree (body);
mapi_release_attach_table (att_table);
return result;
}
/* Sign and Encrypt the MESSAGE. */
int
mime_sign_encrypt (LPMESSAGE message, HWND hwnd,
protocol_t protocol, char **recipients)
{
int result = -1;
int rc = 0;
HRESULT hr;
LPATTACH attach;
LPSTREAM tmpstream = NULL;
struct sink_s sinkmem;
sink_t sink = &sinkmem;
struct sink_s encsinkmem;
sink_t encsink = &encsinkmem;
struct sink_s tmpsinkmem;
sink_t tmpsink = &tmpsinkmem;
char boundary[BOUNDARYSIZE+1];
mapi_attach_item_t *att_table = NULL;
- engine_filter_t filter;
+ engine_filter_t filter = NULL;
memset (sink, 0, sizeof *sink);
memset (encsink, 0, sizeof *encsink);
memset (tmpsink, 0, sizeof *tmpsink);
attach = create_mapi_attachment (message, sink);
if (!attach)
return -1;
+ /* First check that we are not rying to process an empty message
+ which might lock up our engine. Unfortunately we need to
+ duplicate the code we use in do_mime_sign here. FIXME: The
+ engine should be fixed instead of using such a workaround. */
+ {
+ char *body;
+
+ body = mapi_get_body (message, NULL);
+ if (body && !*body)
+ {
+ xfree (body);
+ body = NULL;
+ }
+ att_table = mapi_create_attach_table (message, 0);
+ if (!count_usable_attachments (att_table) && !body)
+ result = gpg_error (GPG_ERR_NO_DATA);
+ xfree (body);
+ if (att_table)
+ {
+ mapi_release_attach_table (att_table);
+ att_table = NULL;
+ }
+ if (gpg_err_code (result) == GPG_ERR_NO_DATA)
+ {
+ log_debug ("%s:%s: can't sign+encrypt an empty message\n",
+ SRCNAME, __func__);
+ goto failure;
+ }
+ }
+
+
/* Create a temporary sink to construct the signed data. */
hr = OpenStreamOnFile (MAPIAllocateBuffer, MAPIFreeBuffer,
(SOF_UNIQUEFILENAME | STGM_DELETEONRELEASE
| STGM_CREATE | STGM_READWRITE),
NULL, "GPG", &tmpstream);
if (FAILED (hr))
{
log_error ("%s:%s: can't create temp file: hr=%#lx\n",
SRCNAME, __func__, hr);
rc = -1;
goto failure;
}
tmpsink->cb_data = tmpstream;
tmpsink->writefnc = sink_std_write;
/* Prepare the encryption. We do this early as it is quite common
that some recipients are not available and thus the encryption
will fail early. This is also required to allow the UIserver to
figure out the protocol to use if we have not forced one. */
if (engine_create_filter (&filter, write_buffer_for_cb, sink))
goto failure;
if ((rc=engine_encrypt_prepare (filter, hwnd,
protocol, recipients, &protocol)))
goto failure;
protocol = check_protocol (protocol);
if (protocol == PROTOCOL_UNKNOWN)
goto failure;
/* Now sign the message. This creates another attachment with the
complete MIME object of the signed message. We can't do the
encryption in streaming mode while running the encryption because
we need to fix up that ugly micalg parameter after having created
the signature. Note that the protocol to use is taken from the
encryption operation. */
if (do_mime_sign (message, hwnd, protocol, &att_table, tmpsink))
goto failure;
/* Now send the actual ENCRYPT command. This split up between
prepare and start is necessary to help with the implementarion of
the UI-server. If we would send the ENCRYPT command immediately
the UI-server might block while reading from the input stream
because we are first going to do a sign operation which in trun
needs the attention of the UI server. A more robust but
complicated approach to the UI-server would be to delay the
reading (and thus the start of the underlying encrypt operation)
until the first byte has been received. */
if ((rc=engine_encrypt_start (filter, 0)))
goto failure;
/* Write the top header. */
rc = create_top_encryption_header (sink, protocol, boundary);
if (rc)
goto failure;
/* Create a new sink for encrypting the temporary attachment with
the signed message. */
encsink->cb_data = filter;
encsink->writefnc = sink_encryption_write;
/* Copy the temporary stream to the encryption sink. */
{
LARGE_INTEGER off;
ULONG nread;
char buffer[4096];
off.QuadPart = 0;
hr = IStream_Seek (tmpstream, off, STREAM_SEEK_SET, NULL);
if (hr)
{
log_error ("%s:%s: seeking back to the begin failed: hr=%#lx",
SRCNAME, __func__, hr);
rc = gpg_error (GPG_ERR_EIO);
goto failure;
}
for (;;)
{
hr = IStream_Read (tmpstream, buffer, sizeof buffer, &nread);
if (hr)
{
log_error ("%s:%s: IStream::Read failed: hr=%#lx",
SRCNAME, __func__, hr);
rc = gpg_error (GPG_ERR_EIO);
goto failure;
}
if (!nread)
break; /* EOF */
rc = write_buffer (encsink, buffer, nread);
if (rc)
{
log_error ("%s:%s: writing tmpstream to encsink failed: %s",
SRCNAME, __func__, gpg_strerror (rc));
goto failure;
}
}
}
/* Flush the encryption sink and wait for the encryption to get
ready. */
if ((rc = write_buffer (encsink, NULL, 0)))
goto failure;
if ((rc = engine_wait (filter)))
goto failure;
filter = NULL; /* Not valid anymore. */
encsink->cb_data = NULL; /* Not needed anymore. */
if (!sink->enc_counter)
{
log_debug ("%s:%s: nothing received from engine", SRCNAME, __func__);
goto failure;
}
/* 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;
if (finalize_message (message, att_table, protocol, 1))
goto failure;
result = 0; /* Everything is fine, fall through the cleanup now. */
failure:
if (result)
log_debug ("%s:%s: failed rc=%d (%s) <%s>", SRCNAME, __func__, rc,
gpg_strerror (rc), gpg_strsource (rc));
engine_cancel (filter);
if (tmpstream)
IStream_Release (tmpstream);
mapi_release_attach_table (att_table);
return result;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, Aug 6, 10:08 PM (1 d, 14 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
77/c6/7dbed78493e3f43a102d6a001cce
Attached To
rO GpgOL
Event Timeline
Log In to Comment