Lots of changes to support S/MIME and to revamp most of the old
authorWerner Koch <wk@gnupg.org>
Mon, 6 Aug 2007 10:48:33 +0000 (10:48 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 6 Aug 2007 10:48:33 +0000 (10:48 +0000)
code.  More changes to follow.

42 files changed:
NEWS
TODO
configure.ac
po/POTFILES.in
po/de.po
po/sv.po
src/ChangeLog
src/Makefile.am
src/attached-file-events.cpp
src/common.c
src/common.h [moved from src/intern.h with 81% similarity]
src/config-dialog.c
src/display.cpp
src/display.h
src/engine-gpgme.c
src/engine.h
src/ext-commands.cpp
src/ext-commands.h
src/gpgmsg.cpp
src/gpgmsg.hh
src/main.c
src/mapihelp.cpp
src/mapihelp.h
src/message-events.cpp
src/message-events.h
src/myexchext.h
src/mymapi.h
src/mymapitags.h
src/ol-ext-callback.cpp
src/olflange-def.h
src/olflange-dlgs.cpp
src/olflange.cpp
src/olflange.h
src/passphrase-dialog.c
src/pgpmime.c
src/property-sheets.cpp
src/recipient-dialog.c
src/rfc822parse.c
src/session-events.cpp
src/util.h
src/verify-dialog.c
src/watcher.cpp

diff --git a/NEWS b/NEWS
index bd9283f..7460526 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
 Noteworthy changes for version 0.9.92
 ==================================================
 
+CURRENTLY UNDER HEAVY DEVELOPMENT - DO NOT USE. 
+
 
 Noteworthy changes for version 0.9.91 (2006-10-13)
 ==================================================
diff --git a/TODO b/TODO
index 9b2149e..682054b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -22,3 +22,8 @@
 * Please consider adding a few more options like key singing rules
   like Enigmail has.
 
+* We should not rite a decrupted file without user content.  A
+  possible solution in attach-file-events.c is to keep tarck of
+  prensented file names and decrypt them only on OpenSzFile.  Need to
+  get some documentaion first.
+
index 36eb723..d879ba1 100644 (file)
@@ -16,8 +16,8 @@ min_automake_version="1.9.4"
 # Remember to change the version number immediately *after* a release.
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
-m4_define([my_version], [0.9.91])
-m4_define([my_issvn], [no])
+m4_define([my_version], [0.9.92])
+m4_define([my_issvn], [yes])
 
 m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \
             || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q}')]))
index f80dd18..8099bf6 100644 (file)
@@ -1,5 +1,4 @@
 
-src/attach.cpp
 src/common.c
 src/config-dialog.c
 src/display.cpp
index 6857ae0..874d6d9 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: GPGol 0.9.4\n"
 "Report-Msgid-Bugs-To: bug-gpgol@g10code.com\n"
-"POT-Creation-Date: 2006-08-28 15:44+0200\n"
+"POT-Creation-Date: 2007-08-03 18:07+0200\n"
 "PO-Revision-Date: 2007-04-13 12:55+0200\n"
 "Last-Translator: Werner Koch <wk@gnupg.org>\n"
 "Language-Team: de\n"
@@ -15,70 +15,70 @@ msgstr ""
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: src/common.c:103
+#: src/common.c:131
 msgid "GPG - Save decrypted attachment"
 msgstr "GPG - Sichern der entschlüsselten Anlage"
 
-#: src/config-dialog.c:290
+#: src/config-dialog.c:289
 msgid "Select GPG Key Manager"
 msgstr "Das Schlüsselverwaltungsprogramm festlegen"
 
-#: src/engine-gpgme.c:979
+#: src/engine-gpgme.c:991
 msgid "Fingerprint: "
 msgstr "Fingerabdruck: "
 
-#: src/engine-gpgme.c:1036
+#: src/engine-gpgme.c:1048
 msgid "This signature is valid\n"
 msgstr "Diese Unterschrift ist korrekt\n"
 
-#: src/engine-gpgme.c:1038
+#: src/engine-gpgme.c:1050
 msgid "signature state is \"green\"\n"
 msgstr "Status der Unterschrift ist \"grün\"\n"
 
-#: src/engine-gpgme.c:1040
+#: src/engine-gpgme.c:1052
 msgid "signature state is \"red\"\n"
 msgstr "Status der Unterschrift ist \"rot\"\n"
 
-#: src/engine-gpgme.c:1044
+#: src/engine-gpgme.c:1056
 msgid "Warning: One of the keys has been revoked\n"
 msgstr "Warnung: Einer der Schlüssel wurde widerrufen\n"
 
-#: src/engine-gpgme.c:1054
+#: src/engine-gpgme.c:1066
 msgid "Warning: The key used to create the signature expired at: "
 msgstr ""
 "Warnung: Der Schlüssel mit der diese Unterschrift erzeugt wurde verfiel am: "
 
-#: src/engine-gpgme.c:1060
+#: src/engine-gpgme.c:1072
 msgid "Warning: At least one certification key has expired\n"
 msgstr ""
 "Warnung: Mindestens einer der Zertifizierungsschlüssel ist abgelaufen\n"
 
-#: src/engine-gpgme.c:1066
+#: src/engine-gpgme.c:1078
 msgid "Warning: The signature expired at: "
 msgstr "Die Unterschrift verfiel am: "
 
-#: src/engine-gpgme.c:1072
+#: src/engine-gpgme.c:1084
 msgid "Can't verify due to a missing key or certificate\n"
 msgstr ""
 "Aufrund eines fehlenden Schlüssels ist eine Überprüfung nicht möglich\n"
 
-#: src/engine-gpgme.c:1076
+#: src/engine-gpgme.c:1088
 msgid "The CRL is not available\n"
 msgstr "Die CRL ist nicht verfügbar\n"
 
-#: src/engine-gpgme.c:1082
+#: src/engine-gpgme.c:1094
 msgid "Available CRL is too old\n"
 msgstr "Die vorhandene CRL ist zu alt\n"
 
-#: src/engine-gpgme.c:1087
+#: src/engine-gpgme.c:1099
 msgid "A policy requirement was not met\n"
 msgstr "Eine Richtlinie wurde nicht erfüllt\n"
 
-#: src/engine-gpgme.c:1093
+#: src/engine-gpgme.c:1105
 msgid "A system error occured"
 msgstr "Ein Systemfehler ist aufgetreten"
 
-#: src/engine-gpgme.c:1130
+#: src/engine-gpgme.c:1142
 msgid ""
 "WARNING: We have NO indication whether the key belongs to the person named "
 "as shown above\n"
@@ -86,12 +86,12 @@ msgstr ""
 "WARNUNG: Es gibt keinen Hinweis darauf, ob der Schlüssel wirklich der Person "
 "gehört, die oben angezeigt ist\n"
 
-#: src/engine-gpgme.c:1137
+#: src/engine-gpgme.c:1149
 msgid "WARNING: The key does NOT BELONG to the person named as shown above\n"
 msgstr ""
 "WARNUNG: Der Schlüssel gehört NICHT der Person die oben angezeigt ist\n"
 
-#: src/engine-gpgme.c:1141
+#: src/engine-gpgme.c:1153
 msgid ""
 "WARNING: It is NOT certain that the key belongs to the person named as shown "
 "above\n"
@@ -99,56 +99,56 @@ msgstr ""
 "WARNING: Es ist nicht sicher, daß der Schlüssel der Person gehört, die oben "
 "angezeigt ist\n"
 
-#: src/engine-gpgme.c:1174
+#: src/engine-gpgme.c:1186
 msgid "Verification started at: "
 msgstr "Überprüfung begann am: "
 
-#: src/engine-gpgme.c:1179
+#: src/engine-gpgme.c:1191
 msgid "Verification result for: "
 msgstr "Prüfungsresultat für: "
 
-#: src/engine-gpgme.c:1180
+#: src/engine-gpgme.c:1192
 msgid "[unnamed part]"
 msgstr "[Unbenannter Teil]"
 
-#: src/engine-gpgme.c:1198 src/engine-gpgme.c:1228
+#: src/engine-gpgme.c:1210 src/engine-gpgme.c:1240
 msgid "Good signature from: "
 msgstr "Korrekte Unterschrift von: "
 
-#: src/engine-gpgme.c:1205
+#: src/engine-gpgme.c:1217
 msgid "                aka: "
 msgstr "                    alias: "
 
-#: src/engine-gpgme.c:1209 src/engine-gpgme.c:1231
+#: src/engine-gpgme.c:1221 src/engine-gpgme.c:1243
 msgid "            created: "
 msgstr "                  erzeugt: "
 
-#: src/engine-gpgme.c:1218
+#: src/engine-gpgme.c:1230
 msgid "*BAD* signature claimed to be from: "
 msgstr "*FALSCHE* Unterschrift, vorgeblich von: "
 
-#: src/engine-gpgme.c:1241
+#: src/engine-gpgme.c:1253
 msgid "Error checking signature"
 msgstr "Fehler beim Prüfen der Unterschrift"
 
-#: src/engine-gpgme.c:1257
+#: src/engine-gpgme.c:1269
 msgid "*** Begin Notation (signature by: "
 msgstr "*** Anfang Notation (Unterschrift von: "
 
-#: src/engine-gpgme.c:1277
+#: src/engine-gpgme.c:1289
 msgid "*** End Notation ***\n"
 msgstr "*** Ende Notation ***\n"
 
-#: src/gpgmsg.cpp:1194
+#: src/gpgmsg.cpp:1197
 msgid "No valid OpenPGP data found."
 msgstr "Keine gültigen OpenPGP Daten gefunden"
 
-#: src/gpgmsg.cpp:1195 src/gpgmsg.cpp:1306 src/gpgmsg.cpp:1320
-#: src/gpgmsg.cpp:1336 src/gpgmsg.cpp:1515
+#: src/gpgmsg.cpp:1198 src/gpgmsg.cpp:1309 src/gpgmsg.cpp:1323
+#: src/gpgmsg.cpp:1339 src/gpgmsg.cpp:1518
 msgid "Decryption"
 msgstr "Entschlüsselung"
 
-#: src/gpgmsg.cpp:1213
+#: src/gpgmsg.cpp:1216
 msgid ""
 "[This is a PGP/MIME message]\r\n"
 "\r\n"
@@ -159,7 +159,7 @@ msgstr ""
 "[Benutzen Sie den \"Entschlüsselungs\"-Button im großen\n"
 "Nachrichtenfenster um den Inhalt anzuzeigen.]"
 
-#: src/gpgmsg.cpp:1271
+#: src/gpgmsg.cpp:1274
 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"
@@ -172,27 +172,27 @@ msgstr ""
 "\n"
 "(Dieser Hinweis wird nur einmalig pro Sitzung angezeigt)"
 
-#: src/gpgmsg.cpp:1275
+#: src/gpgmsg.cpp:1278
 msgid "Verification"
 msgstr "Überprüfung"
 
-#: src/gpgmsg.cpp:1293
+#: src/gpgmsg.cpp:1296
 msgid "[This is a PGP/MIME message]"
 msgstr "[PGP/MIME Nachricht]"
 
-#: src/gpgmsg.cpp:1305 src/gpgmsg.cpp:1319 src/gpgmsg.cpp:1335
+#: src/gpgmsg.cpp:1308 src/gpgmsg.cpp:1322 src/gpgmsg.cpp:1338
 msgid "Problem decrypting PGP/MIME message"
 msgstr "Problem bei Entschlüsseln einer PGP/MIME Nachricht"
 
-#: src/gpgmsg.cpp:1470
+#: src/gpgmsg.cpp:1473
 msgid "Verification Failure"
 msgstr "Überprüfungsfehler"
 
-#: src/gpgmsg.cpp:1473
+#: src/gpgmsg.cpp:1476
 msgid "Decryption Failure"
 msgstr "Entschlüsselungsfehler"
 
-#: src/gpgmsg.cpp:1509
+#: src/gpgmsg.cpp:1512
 msgid ""
 "The message text cannot be displayed.\n"
 "You have to save the decrypted message to view it.\n"
@@ -208,7 +208,7 @@ msgstr ""
 
 #. TRANSLATORS: Keep the @LIST@ verbatim on a separate line; it
 #. will be expanded to a list of atatchment names.
-#: src/gpgmsg.cpp:1536
+#: src/gpgmsg.cpp:1539
 msgid ""
 "Signed attachments found.\n"
 "\n"
@@ -220,13 +220,13 @@ msgstr ""
 "@LIST@\n"
 "Möchten Sie diese Unterschriften überprüfen?"
 
-#: src/gpgmsg.cpp:1544
+#: src/gpgmsg.cpp:1547
 msgid "Attachment Verification"
 msgstr "Überprüfung der Anhänge"
 
 #. TRANSLATORS: Keep the @LIST@ verbatim on a separate line; it
 #. will be expanded to a list of atatchment names.
-#: src/gpgmsg.cpp:1565
+#: src/gpgmsg.cpp:1568
 msgid ""
 "Encrypted attachments found.\n"
 "\n"
@@ -238,15 +238,15 @@ msgstr ""
 "@LIST@\n"
 "Möchten Sie diese entschlüsseln und abspeichern?"
 
-#: src/gpgmsg.cpp:1572
+#: src/gpgmsg.cpp:1575
 msgid "Attachment Decryption"
 msgstr "Entschlüsselung eines Anhangs"
 
-#: src/gpgmsg.cpp:1641
+#: src/gpgmsg.cpp:1644
 msgid "Signing Failure"
 msgstr "Unterschrifterstellungsfehler"
 
-#: src/gpgmsg.cpp:1809
+#: src/gpgmsg.cpp:1812
 msgid ""
 "The configured default encryption key is not available or does not "
 "unambigiously specify a key. Please fix this in the option dialog.\n"
@@ -259,35 +259,35 @@ msgstr ""
 "\n"
 "Die Nachricht wird deswegen nicht für diesen Schlüssel verschlüsselt!"
 
-#: src/gpgmsg.cpp:1813
+#: src/gpgmsg.cpp:1816
 msgid "Encryption"
 msgstr "Verschlüsselung"
 
-#: src/gpgmsg.cpp:1856
+#: src/gpgmsg.cpp:1859
 msgid "Encryption Failure"
 msgstr "Verschlüsselungsfehler"
 
-#: src/gpgmsg.cpp:1910 src/gpgmsg.cpp:3276
+#: src/gpgmsg.cpp:1913 src/gpgmsg.cpp:3279
 msgid "Attachment Encryption Failure"
 msgstr "Verschlüsselungsfehler eines Anhangs"
 
-#: src/gpgmsg.cpp:2683
+#: src/gpgmsg.cpp:2686
 msgid "Attachment Verification Failure"
 msgstr "Überprüfungsfehler eines Anhangs"
 
-#: src/gpgmsg.cpp:2866 src/gpgmsg.cpp:2915
+#: src/gpgmsg.cpp:2869 src/gpgmsg.cpp:2918
 msgid "Attachment Decryption Failure"
 msgstr "Entschlüsselungsfehler eines Anhangs"
 
-#: src/gpgmsg.cpp:3085
+#: src/gpgmsg.cpp:3088
 msgid "Attachment Signing Failure"
 msgstr "Unterschrifterstellungsfehler eines Anhangs"
 
-#: src/olflange-dlgs.cpp:183
+#: src/olflange-dlgs.cpp:184
 msgid "The default key may not contain any spaces."
 msgstr "Der Standardschlüssel darf keine Leerzeichen enthalten."
 
-#: src/olflange.cpp:750
+#: src/olflange.cpp:479
 msgid ""
 "This version of Outlook is too old!\n"
 "\n"
@@ -304,65 +304,6 @@ msgstr ""
 "\n"
 "Bitte updaten Sie auf SP2 bevor Sie versuchen eine Nachricht zu versenden."
 
-#: src/olflange.cpp:946
-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/olflange.cpp:1337
-msgid "&Decrypt and verify message"
-msgstr "Entschlüsseln/Prüfen der Nachricht"
-
-#: src/olflange.cpp:1375
-msgid "GPG &encrypt message"
-msgstr "Mit GPG &verschlüsseln"
-
-#: src/olflange.cpp:1381
-msgid "GPG &sign message"
-msgstr "Mit GPG unter&schreiben"
-
-#: src/olflange.cpp:1427
-msgid "GPG Key &Manager"
-msgstr "GPG Schlüssel&verwaltung"
-
-#: src/olflange.cpp:1559
-msgid "Could not start Key-Manager"
-msgstr "Dei Schlüsselverwaltung konnte nicht aufgerufen werden"
-
-#: src/olflange.cpp:1605
-msgid "Decrypt and verify the message."
-msgstr "Entschlüsseln und Prüfen der Nachricht."
-
-#: src/olflange.cpp:1613
-msgid "Select this option to encrypt the message."
-msgstr "Wählen Sie diese Option zum Verschlüsseln der Nachricht."
-
-#: src/olflange.cpp:1619
-msgid "Select this option to sign the message."
-msgstr "Wählen Sie diese Option zum Unterschreiben der Nachricht."
-
-#: src/olflange.cpp:1628 src/olflange.cpp:1689 src/olflange.cpp:1771
-msgid "Open GPG Key Manager"
-msgstr "Die GPG Schlüsselverwaltung öffnen"
-
-#: src/olflange.cpp:1658 src/olflange.cpp:1722
-msgid "Decrypt message and verify signature"
-msgstr "Nachricht entschlüsseln und Unterschrift prüfen"
-
-#: src/olflange.cpp:1669 src/olflange.cpp:1740
-msgid "Encrypt message with GPG"
-msgstr "Nachricht mit GPG verschlüsseln"
-
-#: src/olflange.cpp:1678 src/olflange.cpp:1755
-msgid "Sign message with GPG"
-msgstr "Nachricht mit GPG unterschreiben"
-
 #: src/passphrase-dialog.c:85
 msgid "No key hint given."
 msgstr "Kein Hinweis auf den Schlüssel"
@@ -375,7 +316,7 @@ msgstr "Ungültige Passphrase; bitte nochmal versuchen..."
 msgid "Select Signing Key"
 msgstr "Signaturschlüssel auswählen"
 
-#: src/pgpmime.c:485
+#: src/pgpmime.c:356
 msgid ""
 "Error creating file\n"
 "Please select another one"
@@ -383,92 +324,164 @@ msgstr ""
 "Fehler bei der Erstellung der Datei.\n"
 "Bitte wählen Sie eine anderen Namen."
 
-#: src/pgpmime.c:487 src/pgpmime.c:638
+#: src/pgpmime.c:358 src/pgpmime.c:509
 msgid "I/O-Error"
 msgstr "Ein-/Ausgabefehler"
 
-#: src/pgpmime.c:637
+#: src/pgpmime.c:508
 msgid "Error writing file"
 msgstr "Dateischreibfehler"
 
-#: src/pgpmime.c:713
+#: src/pgpmime.c:584
 msgid "[PGP/MIME message]"
 msgstr "[PGP/MIME Nachricht]"
 
-#: src/pgpmime.c:733
+#: src/pgpmime.c:604
 msgid "[PGP/MIME message without plain text body]"
 msgstr "[PGP/MIME Nachricht ohne reinen Textkörper]"
 
-#: src/pgpmime.c:808
+#: src/pgpmime.c:679
 msgid "[PGP/MIME signed message without a plain text body]"
 msgstr "[PGP/MIME signierte Nachricht ohne reinen Textkörper]"
 
-#: src/pgpmime.c:820
+#: src/pgpmime.c:691
 msgid "[PGP/MIME signature]"
 msgstr "[PGP/MIME Signatur]"
 
-#: src/recipient-dialog.c:410
+#: src/recipient-dialog.c:89
+msgid "Name"
+msgstr ""
+
+#: src/recipient-dialog.c:94
+msgid "E-Mail"
+msgstr ""
+
+#: src/recipient-dialog.c:99
+msgid "Key-Info"
+msgstr ""
+
+#: src/recipient-dialog.c:104
+msgid "Key ID"
+msgstr ""
+
+#: src/recipient-dialog.c:109
+msgid "Validity"
+msgstr ""
+
+#: src/recipient-dialog.c:425
 msgid "Please select at least one recipient key."
 msgstr "Bitte wählen Sie mindestens einen Empfängerschlüssel."
 
-#: src/recipient-dialog.c:411
+#: src/recipient-dialog.c:426
 msgid "Recipient Dialog"
 msgstr "Auswahl des Empfängerschlüssels"
 
-#: src/verify-dialog.c:125
+#: src/verify-dialog.c:126
 msgid "BAD signature!"
 msgstr "FALSCHE Unterschrift!"
 
-#: src/verify-dialog.c:127
+#: src/verify-dialog.c:128
 msgid "Good signature"
 msgstr "Korrekte Unterschrift"
 
-#: src/verify-dialog.c:129
+#: src/verify-dialog.c:130
 msgid "Good signature from revoked key"
 msgstr "Korrekte Unterschrift; aber Schlüssel wurde widerrufen"
 
-#: src/verify-dialog.c:131
+#: src/verify-dialog.c:132
 msgid "Good signature from expired key"
 msgstr "Korrekte Unterschrift; allerdings ist der Schlüssel abgelaufen"
 
-#: src/verify-dialog.c:133
+#: src/verify-dialog.c:134
 msgid "Good expired signature"
 msgstr "Korrekte aber abgelaufene Unterschrift"
 
-#: src/verify-dialog.c:136
+#: src/verify-dialog.c:137
 msgid "Could not check signature: missing key"
 msgstr "Unterschrift konnte nicht geprüft werden:  Schlüssel fehlt"
 
-#: src/verify-dialog.c:140
+#: src/verify-dialog.c:141
 msgid "Verification error"
 msgstr "Überprüfungsfehler"
 
-#: src/verify-dialog.c:157
+#: src/verify-dialog.c:158
 msgid "User-ID not found"
 msgstr "User-ID nicht gefunden"
 
-#: src/verify-dialog.c:169
+#: src/verify-dialog.c:170
 msgid "This may be due to a wrong option setting"
 msgstr "Möglicherweise durch falsche Einstellungen verursacht"
 
-#: src/verify-dialog.c:175
+#: src/verify-dialog.c:176
 #, c-format
 msgid "Signature expired on %s"
 msgstr "Unterschrift abgelaufen am %s"
 
-#: src/verify-dialog.c:187
+#: src/verify-dialog.c:188
 msgid "Signature issued by a key we do NOT trust."
 msgstr "Die Unterschrift stammt von einem Schlüssel dem wir NICHT vertrauen."
 
-#: src/verify-dialog.c:194
+#: src/verify-dialog.c:195
 msgid "Signature issued by a non-valid key."
 msgstr "Die Unterschrift stammt von einem ungültigen Schlüssel."
 
-#: src/verify-dialog.c:216
-msgid "Verification Result"
+#: src/verify-dialog.c:222
+#, fuzzy
+msgid "OpenPGP Verification Result"
+msgstr "Prüfungsresultat"
+
+#: src/verify-dialog.c:225
+#, fuzzy
+msgid "S/MIME Verification Result"
 msgstr "Prüfungsresultat"
 
 #~ 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\")"
+
+#~ msgid "&Decrypt and verify message"
+#~ msgstr "Entschlüsseln/Prüfen der Nachricht"
+
+#~ msgid "GPG &encrypt message"
+#~ msgstr "Mit GPG &verschlüsseln"
+
+#~ msgid "GPG &sign message"
+#~ msgstr "Mit GPG unter&schreiben"
+
+#~ msgid "GPG Key &Manager"
+#~ msgstr "GPG Schlüssel&verwaltung"
+
+#~ msgid "Could not start Key-Manager"
+#~ msgstr "Dei Schlüsselverwaltung konnte nicht aufgerufen werden"
+
+#~ msgid "Decrypt and verify the message."
+#~ msgstr "Entschlüsseln und Prüfen der Nachricht."
+
+#~ msgid "Select this option to encrypt the message."
+#~ msgstr "Wählen Sie diese Option zum Verschlüsseln der Nachricht."
+
+#~ msgid "Select this option to sign the message."
+#~ msgstr "Wählen Sie diese Option zum Unterschreiben der Nachricht."
+
+#~ msgid "Open GPG Key Manager"
+#~ msgstr "Die GPG Schlüsselverwaltung öffnen"
+
+#~ msgid "Decrypt message and verify signature"
+#~ msgstr "Nachricht entschlüsseln und Unterschrift prüfen"
+
+#~ msgid "Encrypt message with GPG"
+#~ msgstr "Nachricht mit GPG verschlüsseln"
+
+#~ msgid "Sign message with GPG"
+#~ msgstr "Nachricht mit GPG unterschreiben"
+
+#~ msgid ""
 #~ "If you cancel this dialog, the message will be sent in cleartext!\n"
 #~ "\n"
 #~ "Do you really want to cancel?"
index a46190d..44a5fd8 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: GPGol\n"
 "Report-Msgid-Bugs-To: bug-gpgol@g10code.com\n"
-"POT-Creation-Date: 2006-12-12 23:08+0100\n"
+"POT-Creation-Date: 2007-08-03 18:07+0200\n"
 "PO-Revision-Date: 2006-12-12 23:52+0100\n"
 "Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
@@ -15,138 +15,136 @@ msgstr ""
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../src/common.c:103
+#: src/common.c:131
 msgid "GPG - Save decrypted attachment"
 msgstr "GPG - Spara dekrypterad bilaga"
 
-#: ../src/config-dialog.c:290
+#: src/config-dialog.c:289
 msgid "Select GPG Key Manager"
 msgstr "Välj GPG-nyckelhanterare"
 
-#: ../src/engine-gpgme.c:979
+#: src/engine-gpgme.c:991
 msgid "Fingerprint: "
 msgstr "Fingeravtryck: "
 
-#: ../src/engine-gpgme.c:1036
+#: src/engine-gpgme.c:1048
 msgid "This signature is valid\n"
 msgstr "Den här signaturen är giltig\n"
 
-#: ../src/engine-gpgme.c:1038
+#: src/engine-gpgme.c:1050
 msgid "signature state is \"green\"\n"
 msgstr "signaturens tillstånd är \"grön\"\n"
 
-#: ../src/engine-gpgme.c:1040
+#: src/engine-gpgme.c:1052
 msgid "signature state is \"red\"\n"
 msgstr "signaturens tillstånd är \"röd\"\n"
 
-#: ../src/engine-gpgme.c:1044
+#: src/engine-gpgme.c:1056
 msgid "Warning: One of the keys has been revoked\n"
 msgstr "Varning: En av nycklarna har spärrats\n"
 
-#: ../src/engine-gpgme.c:1054
+#: src/engine-gpgme.c:1066
 msgid "Warning: The key 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:1060
+#: src/engine-gpgme.c:1072
 msgid "Warning: At least one certification key has expired\n"
 msgstr "Varning: Åtminstone en certifieringsnyckel har gått ut\n"
 
-#: ../src/engine-gpgme.c:1066
+#: src/engine-gpgme.c:1078
 msgid "Warning: The signature expired at: "
 msgstr "Varning: Signaturen gick ut den: "
 
-#: ../src/engine-gpgme.c:1072
+#: src/engine-gpgme.c:1084
 msgid "Can't verify due to a missing key or certificate\n"
 msgstr "Kan inte validera på grund av en saknad nyckel eller certifikat\n"
 
-#: ../src/engine-gpgme.c:1076
+#: src/engine-gpgme.c:1088
 msgid "The CRL is not available\n"
 msgstr "Spärrlistan är inte tillgänglig\n"
 
-#: ../src/engine-gpgme.c:1082
+#: src/engine-gpgme.c:1094
 msgid "Available CRL is too old\n"
 msgstr "Tillgänglig spärrlista är för gammal\n"
 
-#: ../src/engine-gpgme.c:1087
+#: src/engine-gpgme.c:1099
 msgid "A policy requirement was not met\n"
 msgstr "Ett policykrav matchades inte\n"
 
-#: ../src/engine-gpgme.c:1093
+#: src/engine-gpgme.c:1105
 msgid "A system error occured"
 msgstr "Ett systemfel inträffade"
 
-#: ../src/engine-gpgme.c:1130
-msgid "WARNING: We have NO indication whether the key 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:1142
+msgid ""
+"WARNING: We have NO indication whether the key 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:1137
+#: src/engine-gpgme.c:1149
 msgid "WARNING: The key 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:1141
-msgid "WARNING: It is NOT certain that the key 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:1153
+msgid ""
+"WARNING: It is NOT certain that the key 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"
 
-#. Nothing yet written to the stream.  Insert the current time.
-#: ../src/engine-gpgme.c:1174
+#: src/engine-gpgme.c:1186
 msgid "Verification started at: "
 msgstr "Validering startad: "
 
-#: ../src/engine-gpgme.c:1179
+#: src/engine-gpgme.c:1191
 msgid "Verification result for: "
 msgstr "Valideringsresultat för: "
 
-#: ../src/engine-gpgme.c:1180
+#: src/engine-gpgme.c:1192
 msgid "[unnamed part]"
 msgstr "[ej namngiven del]"
 
-#. We can't decide (yellow) but this is a PGP key with a
-#. good signature, so we display what a PGP user
-#. expects: The name, fingerprint and the key validity
-#. (which is neither fully or ultimate).
-#: ../src/engine-gpgme.c:1198
-#: ../src/engine-gpgme.c:1228
+#: src/engine-gpgme.c:1210 src/engine-gpgme.c:1240
 msgid "Good signature from: "
 msgstr "Korrekt signatur från: "
 
-#: ../src/engine-gpgme.c:1205
+#: src/engine-gpgme.c:1217
 msgid "                aka: "
 msgstr "även känd som:"
 
-#: ../src/engine-gpgme.c:1209
-#: ../src/engine-gpgme.c:1231
+#: src/engine-gpgme.c:1221 src/engine-gpgme.c:1243
 msgid "            created: "
 msgstr "             skapad: "
 
-#: ../src/engine-gpgme.c:1218
+#: src/engine-gpgme.c:1230
 msgid "*BAD* signature claimed to be from: "
 msgstr "*FELAKTIG* signatur hävdades komma från: "
 
-#: ../src/engine-gpgme.c:1241
+#: src/engine-gpgme.c:1253
 msgid "Error checking signature"
 msgstr "Fel vid kontroll av signatur"
 
-#: ../src/engine-gpgme.c:1257
+#: src/engine-gpgme.c:1269
 msgid "*** Begin Notation (signature by: "
 msgstr "*** Notation start (signatur av: "
 
-#: ../src/engine-gpgme.c:1277
+#: src/engine-gpgme.c:1289
 msgid "*** End Notation ***\n"
 msgstr "*** Notation slut ***\n"
 
-#: ../src/gpgmsg.cpp:1194
+#: src/gpgmsg.cpp:1197
 msgid "No valid OpenPGP data found."
 msgstr "Inget giltigt OpenPGP-data hittades."
 
-#: ../src/gpgmsg.cpp:1195
-#: ../src/gpgmsg.cpp:1306
-#: ../src/gpgmsg.cpp:1320
-#: ../src/gpgmsg.cpp:1336
-#: ../src/gpgmsg.cpp:1515
+#: src/gpgmsg.cpp:1198 src/gpgmsg.cpp:1309 src/gpgmsg.cpp:1323
+#: src/gpgmsg.cpp:1339 src/gpgmsg.cpp:1518
 msgid "Decryption"
 msgstr "Dekryptering"
 
-#: ../src/gpgmsg.cpp:1213
+#: src/gpgmsg.cpp:1216
 msgid ""
 "[This is a PGP/MIME message]\r\n"
 "\r\n"
@@ -156,39 +154,40 @@ msgstr ""
 "\r\n"
 "[Använd knappen \"Dekryptera\" i meddelandefönstret för att visa innehållet.]"
 
-#: ../src/gpgmsg.cpp:1271
+#: src/gpgmsg.cpp:1274
 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"
+"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"
+"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)"
 
-#: ../src/gpgmsg.cpp:1275
+#: src/gpgmsg.cpp:1278
 msgid "Verification"
 msgstr "Validering"
 
-#: ../src/gpgmsg.cpp:1293
+#: src/gpgmsg.cpp:1296
 msgid "[This is a PGP/MIME message]"
 msgstr "[Det här är ett PGP/MIME-meddelande]"
 
-#: ../src/gpgmsg.cpp:1305
-#: ../src/gpgmsg.cpp:1319
-#: ../src/gpgmsg.cpp:1335
+#: src/gpgmsg.cpp:1308 src/gpgmsg.cpp:1322 src/gpgmsg.cpp:1338
 msgid "Problem decrypting PGP/MIME message"
 msgstr "Problem vid dekryptering av PGP/MIME-meddelande"
 
-#: ../src/gpgmsg.cpp:1470
+#: src/gpgmsg.cpp:1473
 msgid "Verification Failure"
 msgstr "Validering misslyckades"
 
-#: ../src/gpgmsg.cpp:1473
+#: src/gpgmsg.cpp:1476
 msgid "Decryption Failure"
 msgstr "Dekryptering misslyckades"
 
-#: ../src/gpgmsg.cpp:1509
+#: src/gpgmsg.cpp:1512
 msgid ""
 "The message text cannot be displayed.\n"
 "You have to save the decrypted message to view it.\n"
@@ -204,7 +203,7 @@ msgstr ""
 
 #. TRANSLATORS: Keep the @LIST@ verbatim on a separate line; it
 #. will be expanded to a list of atatchment names.
-#: ../src/gpgmsg.cpp:1536
+#: src/gpgmsg.cpp:1539
 msgid ""
 "Signed attachments found.\n"
 "\n"
@@ -216,13 +215,13 @@ msgstr ""
 "@LIST@\n"
 "Vill du validera signaturerna?"
 
-#: ../src/gpgmsg.cpp:1544
+#: src/gpgmsg.cpp:1547
 msgid "Attachment Verification"
 msgstr "Validering av bilaga"
 
 #. TRANSLATORS: Keep the @LIST@ verbatim on a separate line; it
 #. will be expanded to a list of atatchment names.
-#: ../src/gpgmsg.cpp:1565
+#: src/gpgmsg.cpp:1568
 msgid ""
 "Encrypted attachments found.\n"
 "\n"
@@ -234,146 +233,83 @@ msgstr ""
 "@LIST@\n"
 "Vill du dekryptera och spara dem?"
 
-#: ../src/gpgmsg.cpp:1572
+#: src/gpgmsg.cpp:1575
 msgid "Attachment Decryption"
 msgstr "Dekryptering av bilaga"
 
-#: ../src/gpgmsg.cpp:1641
+#: src/gpgmsg.cpp:1644
 msgid "Signing Failure"
 msgstr "Signering misslyckades"
 
-#: ../src/gpgmsg.cpp:1809
+#: src/gpgmsg.cpp:1812
 msgid ""
-"The configured default encryption key is not available or does not unambigiously specify a key. Please fix this in the option dialog.\n"
+"The configured default encryption key is not available or does not "
+"unambigiously specify a key. Please fix this in the option dialog.\n"
 "\n"
 "This message won't be be encrypted to this key!"
 msgstr ""
-"Den konfigurerade standardkrypteringsnyckeln är inte tillgänglig eller anger inte uttryckligen en nyckel. Rätta till det här i inställningarna.\n"
+"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/gpgmsg.cpp:1813
+#: src/gpgmsg.cpp:1816
 msgid "Encryption"
 msgstr "Kryptering"
 
-#: ../src/gpgmsg.cpp:1856
+#: src/gpgmsg.cpp:1859
 msgid "Encryption Failure"
 msgstr "Kryptering misslyckades"
 
-#: ../src/gpgmsg.cpp:1910
-#: ../src/gpgmsg.cpp:3276
+#: src/gpgmsg.cpp:1913 src/gpgmsg.cpp:3279
 msgid "Attachment Encryption Failure"
 msgstr "Kryptering av bilaga misslyckades"
 
-#: ../src/gpgmsg.cpp:2683
+#: src/gpgmsg.cpp:2686
 msgid "Attachment Verification Failure"
 msgstr "Validering av bilaga misslyckades"
 
-#: ../src/gpgmsg.cpp:2866
-#: ../src/gpgmsg.cpp:2915
+#: src/gpgmsg.cpp:2869 src/gpgmsg.cpp:2918
 msgid "Attachment Decryption Failure"
 msgstr "Dekryptering av bilaga misslyckades"
 
-#: ../src/gpgmsg.cpp:3085
+#: src/gpgmsg.cpp:3088
 msgid "Attachment Signing Failure"
 msgstr "Signering av bilaga misslyckades"
 
-#: ../src/olflange-dlgs.cpp:183
+#: src/olflange-dlgs.cpp:184
 msgid "The default key may not contain any spaces."
 msgstr "Standardnyckeln får inte innehålla några blanksteg."
 
-#: ../src/olflange.cpp:751
+#: src/olflange.cpp:479
 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"
+"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"
+"Å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"
 
-# A bit unclear in the original text
-#: ../src/olflange.cpp:947
-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/olflange.cpp:1337
-msgid "&Decrypt and verify message"
-msgstr "&Dekryptera och validera meddelandet"
-
-#: ../src/olflange.cpp:1375
-msgid "GPG &encrypt message"
-msgstr "GPG-&kryptera meddelandet"
-
-#: ../src/olflange.cpp:1381
-msgid "GPG &sign message"
-msgstr "GPG-&signera meddelandet"
-
-#: ../src/olflange.cpp:1427
-msgid "GPG Key &Manager"
-msgstr "GPG-nyckel&hanterare"
-
-#: ../src/olflange.cpp:1559
-msgid "Could not start Key-Manager"
-msgstr "Kunde inte starta nyckelhanteraren"
-
-#: ../src/olflange.cpp:1605
-msgid "Decrypt and verify the message."
-msgstr "Dekryptera och validera meddelandet."
-
-#: ../src/olflange.cpp:1613
-msgid "Select this option to encrypt the message."
-msgstr "Välj det här alternativet för att kryptera meddelandet."
-
-#: ../src/olflange.cpp:1619
-msgid "Select this option to sign the message."
-msgstr "Välj det här alternativet för att signera meddelandet."
-
-#: ../src/olflange.cpp:1628
-#: ../src/olflange.cpp:1689
-#: ../src/olflange.cpp:1771
-msgid "Open GPG Key Manager"
-msgstr "Öppna GPG-nyckelhanteraren"
-
-#: ../src/olflange.cpp:1658
-#: ../src/olflange.cpp:1722
-msgid "Decrypt message and verify signature"
-msgstr "Dekryptera meddelandet och validera signaturen"
-
-#: ../src/olflange.cpp:1669
-#: ../src/olflange.cpp:1740
-msgid "Encrypt message with GPG"
-msgstr "Kryptera meddelandet med GPG"
-
-#: ../src/olflange.cpp:1678
-#: ../src/olflange.cpp:1755
-msgid "Sign message with GPG"
-msgstr "Signera meddelandet med GPG"
-
-#: ../src/passphrase-dialog.c:85
+#: src/passphrase-dialog.c:85
 msgid "No key hint given."
 msgstr "Inget nyckeltips angivet."
 
-#: ../src/passphrase-dialog.c:330
-#: ../src/passphrase-dialog.c:458
+#: src/passphrase-dialog.c:330 src/passphrase-dialog.c:458
 msgid "Invalid passphrase; please try again..."
 msgstr "Ogiltig lösenfras; försök igen..."
 
-#: ../src/passphrase-dialog.c:357
+#: src/passphrase-dialog.c:357
 msgid "Select Signing Key"
 msgstr "Välj signeringsnyckel"
 
-#: ../src/pgpmime.c:485
+#: src/pgpmime.c:356
 msgid ""
 "Error creating file\n"
 "Please select another one"
@@ -381,109 +317,159 @@ msgstr ""
 "Fel vid skapande av fil\n"
 "Välj en annan"
 
-#: ../src/pgpmime.c:487
-#: ../src/pgpmime.c:638
+#: src/pgpmime.c:358 src/pgpmime.c:509
 msgid "I/O-Error"
 msgstr "In-/Ut-fel"
 
-#: ../src/pgpmime.c:637
+#: src/pgpmime.c:508
 msgid "Error writing file"
 msgstr "Fel vid skrivning av fil"
 
-#: ../src/pgpmime.c:713
+#: src/pgpmime.c:584
 msgid "[PGP/MIME message]"
 msgstr "[PGP/MIME-meddelande]"
 
-#: ../src/pgpmime.c:733
+#: src/pgpmime.c:604
 msgid "[PGP/MIME message without plain text body]"
 msgstr "[PGP/MIME-meddelande utan vanlig meddelandetext]"
 
-#: ../src/pgpmime.c:808
+#: src/pgpmime.c:679
 msgid "[PGP/MIME signed message without a plain text body]"
 msgstr "[PGP/MIME-signerat meddelande utan vanlig meddelandetext]"
 
-#: ../src/pgpmime.c:820
+#: src/pgpmime.c:691
 msgid "[PGP/MIME signature]"
 msgstr "[PGP/MIME-signatur]"
 
-#: ../src/recipient-dialog.c:89
+#: src/recipient-dialog.c:89
 msgid "Name"
 msgstr "Namn"
 
-#: ../src/recipient-dialog.c:94
+#: src/recipient-dialog.c:94
 msgid "E-Mail"
 msgstr "E-post"
 
-#: ../src/recipient-dialog.c:99
+#: src/recipient-dialog.c:99
 msgid "Key-Info"
 msgstr "Nyckelinfo"
 
-#: ../src/recipient-dialog.c:104
+#: src/recipient-dialog.c:104
 msgid "Key ID"
 msgstr "Nyckel-id"
 
-#: ../src/recipient-dialog.c:109
+#: src/recipient-dialog.c:109
 msgid "Validity"
 msgstr "Giltighet"
 
-#: ../src/recipient-dialog.c:425
+#: src/recipient-dialog.c:425
 msgid "Please select at least one recipient key."
 msgstr "Välj åtminstone en mottagarnyckel."
 
-#: ../src/recipient-dialog.c:426
+#: src/recipient-dialog.c:426
 msgid "Recipient Dialog"
 msgstr "Mottagardialog"
 
-#: ../src/verify-dialog.c:125
+#: src/verify-dialog.c:126
 msgid "BAD signature!"
 msgstr "FELAKTIG signatur!"
 
-#: ../src/verify-dialog.c:127
+#: src/verify-dialog.c:128
 msgid "Good signature"
 msgstr "Korrekt signatur"
 
-#: ../src/verify-dialog.c:129
+#: src/verify-dialog.c:130
 msgid "Good signature from revoked key"
 msgstr "Korrekt signatur från spärrad nyckel"
 
-#: ../src/verify-dialog.c:131
+#: src/verify-dialog.c:132
 msgid "Good signature from expired key"
 msgstr "Korrekt signatur från utgången nyckel"
 
-#: ../src/verify-dialog.c:133
+#: src/verify-dialog.c:134
 msgid "Good expired signature"
 msgstr "Korrekt utgången signatur"
 
-#: ../src/verify-dialog.c:136
+#: src/verify-dialog.c:137
 msgid "Could not check signature: missing key"
 msgstr "Kunde inte kontrollera signaturen: saknar nyckel"
 
-#: ../src/verify-dialog.c:140
+#: src/verify-dialog.c:141
 msgid "Verification error"
 msgstr "Valideringsfel"
 
-#: ../src/verify-dialog.c:157
+#: src/verify-dialog.c:158
 msgid "User-ID not found"
 msgstr "Användaridentiteten hittades inte"
 
-#: ../src/verify-dialog.c:169
+#: src/verify-dialog.c:170
 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:175
+#: src/verify-dialog.c:176
 #, c-format
 msgid "Signature expired on %s"
 msgstr "Signaturen gick ut den %s"
 
-#: ../src/verify-dialog.c:187
+#: src/verify-dialog.c:188
 msgid "Signature issued by a key we do NOT trust."
 msgstr "Signaturen utfärdad av en nyckel som vi INTE litar på."
 
-#: ../src/verify-dialog.c:194
+#: src/verify-dialog.c:195
 msgid "Signature issued by a non-valid key."
 msgstr "Signaturen utfärdad av en icke-giltig nyckel."
 
-#: ../src/verify-dialog.c:216
-msgid "Verification Result"
+#: src/verify-dialog.c:222
+#, fuzzy
+msgid "OpenPGP Verification Result"
+msgstr "Resultat från validering"
+
+#: src/verify-dialog.c:225
+#, fuzzy
+msgid "S/MIME Verification Result"
 msgstr "Resultat från validering"
 
+# A bit unclear in the original text
+#~ 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."
+
+#~ msgid "&Decrypt and verify message"
+#~ msgstr "&Dekryptera och validera meddelandet"
+
+#~ msgid "GPG &encrypt message"
+#~ msgstr "GPG-&kryptera meddelandet"
+
+#~ msgid "GPG &sign message"
+#~ msgstr "GPG-&signera meddelandet"
+
+#~ msgid "GPG Key &Manager"
+#~ msgstr "GPG-nyckel&hanterare"
+
+#~ msgid "Could not start Key-Manager"
+#~ msgstr "Kunde inte starta nyckelhanteraren"
+
+#~ msgid "Decrypt and verify the message."
+#~ msgstr "Dekryptera och validera meddelandet."
+
+#~ msgid "Select this option to encrypt the message."
+#~ msgstr "Välj det här alternativet för att kryptera meddelandet."
+
+#~ msgid "Select this option to sign the message."
+#~ msgstr "Välj det här alternativet för att signera meddelandet."
+
+#~ msgid "Open GPG Key Manager"
+#~ msgstr "Öppna GPG-nyckelhanteraren"
+
+#~ msgid "Decrypt message and verify signature"
+#~ msgstr "Dekryptera meddelandet och validera signaturen"
+
+#~ msgid "Encrypt message with GPG"
+#~ msgstr "Kryptera meddelandet med GPG"
+
+#~ msgid "Sign message with GPG"
+#~ msgstr "Signera meddelandet med GPG"
index c002a6a..0a3c103 100644 (file)
@@ -1,3 +1,57 @@
+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.
index b026da1..f188a07 100644 (file)
@@ -30,12 +30,14 @@ gpgol_SOURCES = \
        olflange-ids.h              \
        myexchext.h                 \
        display.cpp display.h       \
+       message.cpp message.h       \
        gpgmsg.cpp gpgmsg.hh        \
        pgpmime.c pgpmime.h         \
+       mimeparser.c mimeparser.h   \
        msgcache.c msgcache.h       \
         engine-gpgme.c engine.h    \
        rfc822parse.c rfc822parse.h \
-        common.c util.h intern.h xmalloc.h   \
+        common.c util.h xmalloc.h   \
        passcache.c passcache.h     \
         config-dialog.c                    \
         passphrase-dialog.c         \
@@ -43,6 +45,7 @@ gpgol_SOURCES = \
         verify-dialog.c             \
        mapihelp.cpp mapihelp.h     \
        mymapi.h  mymapitags.h      \
+       serpent.c serpent.h         \
         vasprintf.c                 \
        watcher.cpp \
        ext-commands.cpp ext-commands.h       \
@@ -50,6 +53,7 @@ gpgol_SOURCES = \
        message-events.cpp  message-events.h  \
        attached-file-events.cpp attached-file-events.h \
        property-sheets.cpp property-sheets.h \
+       item-events.cpp item-events.h         \
        ol-ext-callback.cpp ol-ext-callback.h \
        w32-gettext.c w32-gettext.h 
 
@@ -76,7 +80,7 @@ clean-local:
 
 gpgol_LDADD = $(srcdir)/gpgol.def  \
        -L . -lgpgme -lgpg-error -lmapi32 -lshell32 -lgdi32 -lcomdlg32 \
-        -lole32 -loleaut32 -lws2_32
+        -lole32 -loleaut32 -lws2_32 -ladvapi32
 
 resource.o: resource.rc versioninfo.rc gpgol-rsrcs.rc olflange-rsrcs.rc
 
index 2e0da27..9d0e920 100644 (file)
 #include <config.h>
 #endif
 #include <windows.h>
+#include <errno.h>
 
 #include "mymapi.h"
 #include "mymapitags.h"
 #include "myexchext.h"
-#include "intern.h"
+#include "common.h"
 #include "olflange-def.h"
 #include "olflange.h"
+#include "serpent.h"
 #include "attached-file-events.h"
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                                      SRCNAME, __func__, __LINE__); \
                         } while (0)
 
+#define COPYBUFFERSIZE 4096
+
+/* Copy STREAM to a new file FILENAME while decrypting it using the
+   context SYMENC.  */
+static int
+decrypt_and_write_file (LPSTREAM stream, const char *filename, symenc_t symenc)
+{
+  int rc = E_ABORT;
+  HRESULT hr;
+  ULONG nread;
+  char *buf = NULL;
+  FILE *fpout = NULL;
+
+  fpout = fopen (filename, "wb");
+  if (!fpout)
+    {
+      log_error ("%s:%s: fwrite failed: %s", SRCNAME, __func__,
+                 strerror (errno));
+      MessageBox (NULL,
+                  _("Error creating file for attachment."),
+                  "GpgOL", MB_ICONERROR|MB_OK);
+      goto leave;
+    }
+
+  buf = (char*)xmalloc (COPYBUFFERSIZE);
+  do
+    {
+      hr = stream->Read (buf, COPYBUFFERSIZE, &nread);
+      if (hr)
+        {
+          log_error ("%s:%s: Read failed: hr=%#lx", SRCNAME, __func__, hr);
+          MessageBox (NULL,
+                      _("Error reading attachment."),
+                      "GpgOL", MB_ICONERROR|MB_OK);
+          goto leave;
+        }
+      if (nread)
+        symenc_cfb_decrypt (symenc, buf, buf, nread);
+      if (nread && fwrite (buf, nread, 1, fpout) != 1)
+        {
+          log_error ("%s:%s: fwrite failed: %s", SRCNAME, __func__,
+                     strerror (errno));
+          MessageBox (NULL,
+                      _("Error writing attachment."),
+                      "GpgOL", MB_ICONERROR|MB_OK);
+          goto leave;
+        }
+    }
+  while (nread == COPYBUFFERSIZE);
+  
+  xfree (buf);
+  if (fclose (fpout))
+    {
+      log_error ("%s:%s: fclose failed: %s", 
+                 SRCNAME, __func__, strerror (errno));
+      MessageBox (NULL,
+                  _("Error writing attachment."),
+                  "GpgOL", MB_ICONERROR|MB_OK);
+      goto leave;
+    } 
+
+  rc = S_OK;
+
+ leave:
+  xfree (buf);
+  if (fpout)
+    fclose (fpout);
+  if (rc != S_OK)
+    remove (filename);
+  return rc;
+}
+
+
 
 
 /* Our constructor.  */
@@ -69,7 +144,10 @@ GpgolAttachedFileEvents::QueryInterface (REFIID riid, LPVOID FAR *ppvObj)
 
 /* Fixme: We need to figure out what this exactly does.  There is no
    public information available exepct for the MAPI book which is out
-   of print.  */
+   of print.  
+
+   This seems to be called if one adds a new attachment to a the composer.
+*/
 STDMETHODIMP 
 GpgolAttachedFileEvents::OnReadPattFromSzFile 
   (LPATTACH att, LPTSTR file, ULONG flags)
@@ -80,13 +158,77 @@ GpgolAttachedFileEvents::OnReadPattFromSzFile
 }
   
  
+/* This seems to be called if one clicks on Save in the context menu.
+   And also sometimes before an Open click. */
 STDMETHODIMP 
 GpgolAttachedFileEvents::OnWritePattToSzFile 
   (LPATTACH att, LPTSTR file, ULONG flags)
 {
+  HRESULT hr;
+  ULONG tag;
+  char *iv;
+  size_t ivlen;
+  symenc_t symenc;
+  LPSTREAM stream;
+  char tmpbuf[16];
+  ULONG nread;
+  int rc;
+
   log_debug ("%s:%s: att=%p file=`%s' flags=%lx\n", 
             SRCNAME, __func__, att, file, flags);
-  return S_FALSE;
+  if (!att)
+    return E_FAIL;
+
+  if (get_gpgolprotectiv_tag ((LPMESSAGE)att, &tag) )
+    return E_ABORT;
+  iv = mapi_get_binary_prop ((LPMESSAGE)att, tag, &ivlen);
+  if (!iv)
+    return S_FALSE; /* Not encrypted by us - Let OL continue as usual.  */
+
+  symenc = symenc_open (get_128bit_session_key (), 16, iv, ivlen);
+  xfree (iv);
+  if (!symenc)
+    {
+      log_error ("%s:%s: can't open encryption context", SRCNAME, __func__);
+      return E_ABORT;
+    }
+
+  hr = att->OpenProperty (PR_ATTACH_DATA_BIN, &IID_IStream, 
+                          0, 0, (LPUNKNOWN*) &stream);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: can't open data stream of attachment: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      symenc_close (symenc);
+      return E_ABORT;
+    }
+
+  hr = stream->Read (tmpbuf, 16, &nread);
+  if (hr)
+    {
+      log_debug ("%s:%s: Read failed: hr=%#lx", SRCNAME, __func__, hr);
+      stream->Release ();
+      symenc_close (symenc);
+      return E_ABORT;
+    }
+  symenc_cfb_decrypt (symenc, tmpbuf, tmpbuf, 16);
+  if (memcmp (tmpbuf, "GpgOL attachment", 16))
+    {
+      MessageBox (NULL,
+                  _("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."),
+                  "GpgOL", MB_ICONERROR|MB_OK);
+      stream->Release ();
+      symenc_close (symenc);
+      return E_ABORT;
+    }
+
+  rc = decrypt_and_write_file (stream, file, symenc);
+
+  stream->Release ();
+  symenc_close (symenc);
+  return rc;
 }
 
 
@@ -106,6 +248,7 @@ GpgolAttachedFileEvents::OnOpenPatt (LPATTACH att)
 }
 
 
+/* This seems to be called if one clicks on Open in the context menu.  */
 STDMETHODIMP 
 GpgolAttachedFileEvents::OnOpenSzFile (LPTSTR file, ULONG flags)
 {
index 4b0a203..d3ff477 100644 (file)
@@ -1,33 +1,61 @@
-/* common.c 
- *     Copyright (C) 2005 g10 Code GmbH
+/* common.c - Common routines used bu GpgOL
+ *     Copyright (C) 2005, 2007 g10 Code GmbH
  *
- * This file is part of GPGol.
+ * This file is part of GpgOL.
  *
- * GPGol is free software; you can redistribute it and/or
+ * 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,
+ * 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
  * General Public License for more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with GPGol; if not, write to the Free Software Foundation, 
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
  */
 
 #include <config.h>
 #include <windows.h>
 #include <time.h>
 
-#include "gpgme.h"
-#include "intern.h"
-#include "util.h"
+#include "common.h"
 
 HINSTANCE glob_hinst = NULL;
 
+
+/* The reverse base-64 list used for base-64 decoding. */
+static unsigned char const asctobin[256] = {
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 
+  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 
+  0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 
+  0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 
+  0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 
+  0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+  0xff, 0xff, 0xff, 0xff
+};
+
+
+
 void
 set_global_hinstance (HINSTANCE hinst)
 {
@@ -404,3 +432,103 @@ read_w32_registry_string (const char *root, const char *dir, const char *name)
   return result;
 }
 
+
+
+
+/* Do in-place decoding of quoted-printable data of LENGTH in BUFFER.
+   Returns the new length of the buffer. */
+size_t
+qp_decode (char *buffer, size_t length)
+{
+  char *d, *s;
+
+  for (s=d=buffer; length; length--)
+    if (*s == '=' && length > 2 && hexdigitp (s+1) && hexdigitp (s+2))
+      {
+        s++;
+        *(unsigned char*)d++ = xtoi_2 (s);
+        s += 2;
+        length -= 2;
+      }
+    else
+      *d++ = *s++;
+  
+  return d - buffer;
+}
+
+
+/* Initialize the Base 64 decoder state.  */
+void b64_init (b64_state_t *state)
+{
+  state->idx = 0;
+  state->val = 0;
+  state->stop_seen = 0;
+  state->invalid_encoding = 0;
+}
+
+
+/* Do in-place decoding of base-64 data of LENGTH in BUFFER.  Returns
+   the new length of the buffer. STATE is required to return errors and
+   to maintain the state of the decoder.  */
+size_t
+b64_decode (b64_state_t *state, char *buffer, size_t length)
+{
+  int idx = state->idx;
+  unsigned char val = state->val;
+  int c;
+  char *d, *s;
+
+  if (state->stop_seen)
+    return 0;
+
+  for (s=d=buffer; length; length--, s++)
+    {
+      if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
+        continue;
+      if (*s == '=')
+        { 
+          /* Pad character: stop */
+          if (idx == 1)
+            *d++ = val; 
+          state->stop_seen = 1;
+          break;
+        }
+
+      if ((c = asctobin[*(unsigned char *)s]) == 255) 
+        {
+          if (!state->invalid_encoding)
+            log_debug ("%s: invalid base64 character %02X at pos %d skipped\n",
+                       __func__, *(unsigned char*)s, (int)(s-buffer));
+          state->invalid_encoding = 1;
+          continue;
+        }
+
+      switch (idx) 
+        {
+        case 0: 
+          val = c << 2;
+          break;
+        case 1: 
+          val |= (c>>4)&3;
+          *d++ = val;
+          val = (c<<4)&0xf0;
+          break;
+        case 2: 
+          val |= (c>>2)&15;
+          *d++ = val;
+          val = (c<<6)&0xc0;
+          break;
+        case 3: 
+          val |= c&0x3f;
+          *d++ = val;
+          break;
+        }
+      idx = (idx+1) % 4;
+    }
+
+  
+  state->idx = idx;
+  state->val = val;
+  return d - buffer;
+}
+
similarity index 81%
rename from src/intern.h
rename to src/common.h
index b9a0172..d93aff2 100644 (file)
@@ -1,25 +1,26 @@
-/* intern.h
+/* common.h - Common declarations for GpgOL
  *     Copyright (C) 2004 Timo Schulz
- *     Copyright (C) 2005, 2006 g10 Code GmbH
+ *     Copyright (C) 2005, 2006, 2007 g10 Code GmbH
  *
- * This file is part of GPGol.
+ * This file is part of GpgOL.
  *
- * GPGol is free software; you can redistribute it and/or
+ * 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,
+ * 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
  * General Public License for more details.
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with GPGol; if not, write to the Free Software Foundation, 
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
  */
-#ifndef GPGOL_INTERN_H
-#define GPGOL_INTERN_H
+#ifndef GPGOL_COMMON_H
+#define GPGOL_COMMON_H
 
 #include <gpgme.h>
 
@@ -33,10 +34,6 @@ extern "C" {
 #endif
 #endif
 
-#ifndef STRICT
-#define STRICT
-#endif
-
 
 /* Possible options for the recipient dialog. */
 enum
@@ -119,6 +116,18 @@ struct
 } opt;
 
 
+/* The state object used by b64_decode.  */
+struct b64_state_s
+{
+  int idx;
+  unsigned char val;
+  int stop_seen;
+  int invalid_encoding;
+};
+typedef struct b64_state_s b64_state_t;
+
+
+
 /*-- common.c --*/
 void set_global_hinstance (HINSTANCE hinst);
 void center_window (HWND childwnd, HWND style);
@@ -127,6 +136,11 @@ char *utf8_to_wincp (const char *string);
 
 HRESULT w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e);
 
+size_t qp_decode (char *buffer, size_t length);
+void b64_init (b64_state_t *state);
+size_t b64_decode (b64_state_t *state, char *buffer, size_t length);
+
+
 /*-- watcher.cpp --*/
 int watcher_init_hook (void);
 int watcher_free_hook (void);
@@ -152,10 +166,12 @@ int store_extension_value (const char *key, const char *val);
 int load_extension_value (const char *key, char **val);
 
 /*-- verify-dialog.c --*/
-int verify_dialog_box (gpgme_verify_result_t res, const char *filename);
+int verify_dialog_box (gpgme_protocol_t protocol, 
+                       gpgme_verify_result_t res, 
+                       const char *filename);
+
 
 #ifdef __cplusplus
 }
 #endif
-
-#endif /*GPGOL_INTERN_H*/
+#endif /*GPGOL_COMMON_H*/
index 0dd7383..861e60e 100644 (file)
 #include <time.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#include <gpgme.h>
 
+#include "common.h"
 #include "gpgol-ids.h"
-#include "intern.h"
 
 /* Registry path to GnuPG */
 #define REGPATH "Software\\GNU\\GnuPG"
index 351ce9f..8cd3c2c 100644 (file)
 
 #include "mymapi.h"
 #include "mymapitags.h"
-#include "intern.h"
+#include "myexchext.h"
+#include "common.h"
+#include "mapihelp.h"
+#include "ol-ext-callback.h"
 #include "display.h"
 
 
@@ -176,7 +179,7 @@ find_message_window (HWND parent, int level)
 /* Update the display with TEXT using the message MSG.  Return 0 on
    success. */
 int
-update_display (HWND hwnd, GpgMsg *msg, void *exchange_cb, 
+update_display (HWND hwnd, void *exchange_cb, 
                 bool is_html, const char *text)
 {
   HWND window;
@@ -206,7 +209,7 @@ update_display (HWND hwnd, GpgMsg *msg, void *exchange_cb,
     }
   else if (exchange_cb && !opt.compat.no_oom_write)
     {
-      log_debug ("updating display using OOM\n");
+      log_debug ("%s:%s: updating display using OOM\n", SRCNAME, __func__);
       /* Bug in OL 2002 and 2003 - as a workaround set the body first
          to empty. */
       if (is_html)
@@ -272,3 +275,147 @@ set_message_body (LPMESSAGE message, const char *string, bool is_html)
 
   return 0;
 }
+
+
+
+int
+open_inspector (LPEXCHEXTCALLBACK peecb, LPMESSAGE message)
+{
+  HRESULT hr;
+  LPMAPISESSION session;
+  ULONG token; 
+  char *entryid, *store_entryid, *parent_entryid;
+  size_t entryidlen, store_entryidlen, parent_entryidlen;
+  LPMDB mdb;
+  LPMAPIFOLDER mfolder;
+  ULONG mtype;
+  LPMESSAGE message2;
+  
+  hr = peecb->GetSession (&session, NULL);
+  if (FAILED (hr) )
+    {
+      
+      log_error ("%s:%s: error getting session: hr=%#lx\n", 
+                 SRCNAME, __func__, hr);
+      return -1;
+      
+    }
+  
+  entryid = mapi_get_binary_prop (message, PR_ENTRYID, &entryidlen);
+  if (!entryid)
+    {
+      log_error ("%s:%s: PR_ENTRYID missing\n",  SRCNAME, __func__);
+      session->Release ();
+      return -1;
+    }
+  log_hexdump (entryid, entryidlen, "orig entryid=");
+  store_entryid = mapi_get_binary_prop (message, PR_STORE_ENTRYID,
+                                        &store_entryidlen);
+  if (!store_entryid)
+    {
+      log_error ("%s:%s: PR_STORE_ENTRYID missing\n",  SRCNAME, __func__);
+      session->Release ();
+      xfree (entryid);
+      return -1;
+    }
+  parent_entryid = mapi_get_binary_prop (message, PR_PARENT_ENTRYID,
+                                         &parent_entryidlen);
+  if (!parent_entryid)
+    {
+      log_error ("%s:%s: PR_PARENT_ENTRYID missing\n",  SRCNAME, __func__);
+      session->Release ();
+      xfree (store_entryid);
+      xfree (entryid);
+      return -1;
+    }
+
+  /* Open the message store by ourself.  */
+  hr = session->OpenMsgStore (0, store_entryidlen, (LPENTRYID)store_entryid,
+                              NULL,  MAPI_BEST_ACCESS | MDB_NO_DIALOG, 
+                              &mdb);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: OpenMsgStore failed: hr=%#lx\n", 
+                 SRCNAME, __func__, hr);
+      session->Release ();
+      xfree (parent_entryid);
+      xfree (store_entryid);
+      xfree (entryid);
+      return -1;
+    }
+
+  /* Open the parent folder.  */
+  hr = mdb->OpenEntry (parent_entryidlen,  (LPENTRYID)parent_entryid,
+                       &IID_IMAPIFolder, MAPI_BEST_ACCESS, 
+                       &mtype, (IUnknown**)&mfolder);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: OpenEntry failed: hr=%#lx\n", 
+                 SRCNAME, __func__, hr);
+      session->Release ();
+      xfree (parent_entryid);
+      xfree (store_entryid);
+      xfree (entryid);
+      mdb->Release ();
+      return -1;
+    }
+  log_debug ("%s:%s: mdb::OpenEntry succeeded type=%lx\n", 
+             SRCNAME, __func__, mtype);
+
+  /* Open the message.  */
+  hr = mdb->OpenEntry (entryidlen,  (LPENTRYID)entryid,
+                       &IID_IMessage, MAPI_BEST_ACCESS, 
+                       &mtype, (IUnknown**)&message2);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: OpenEntry[folder] failed: hr=%#lx\n", 
+                 SRCNAME, __func__, hr);
+      session->Release ();
+      xfree (parent_entryid);
+      xfree (store_entryid);
+      xfree (entryid);
+      mdb->Release ();
+      mfolder->Release ();
+      return -1;
+    }
+  log_debug ("%s:%s: mdb::OpenEntry[message] succeeded type=%lx\n", 
+             SRCNAME, __func__, mtype);
+
+  /* Prepare and display the form.  */
+  hr = session->PrepareForm (NULL, message2, &token);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: PrepareForm failed: hr=%#lx\n", 
+                 SRCNAME, __func__, hr);
+      session->Release ();
+      xfree (parent_entryid);
+      xfree (store_entryid);
+      xfree (entryid);
+      mdb->Release ();
+      mfolder->Release ();
+      message2->Release ();
+      return -1;
+    }
+
+  /* Message2 is now represented by TOKEN; we need to release it.  */
+  message2->Release(); message2 = NULL;
+
+  hr = session->ShowForm (0,
+                          mdb, mfolder, 
+                          NULL,  token,
+                          NULL,  
+                          0,
+                          0,  0,
+                          0,  "IPM.Note");
+  log_debug ("%s:%s: ShowForm result: hr=%#lx\n", 
+             SRCNAME, __func__, hr);
+  
+  session->Release ();
+  xfree (parent_entryid);
+  xfree (store_entryid);
+  xfree (entryid);
+  mdb->Release ();
+  mfolder->Release ();
+  return FAILED(hr)? -1:0;
+}
+
index 270ea52..eaa95ab 100644 (file)
 #ifndef DISPLAY_H
 #define DISPLAY_H
 
-#include "gpgmsg.hh"
-
 int is_html_body (const char *body);
 
 char *add_html_line_endings (const char *body);
 
-int update_display (HWND hwnd, GpgMsg *msg, void *exchange_cb,
+int update_display (HWND hwnd, void *exchange_cb,
                     bool is_html, const char *text);
 
 int set_message_body (LPMESSAGE message, const char *string, bool is_html);
 
-
-/*-- olflange.cpp --*/
-int put_outlook_property (void *pEECB, const char *key, const char *value);
-int put_outlook_property_int (void *pEECB, const char *key, int value);
-char *get_outlook_property (void *pEECB, const char *key);
+int open_inspector (LPEXCHEXTCALLBACK peecb, LPMESSAGE message);
 
 
 #endif /*DISPLAY_H*/
index 6cbe3ac..e4462fb 100644 (file)
@@ -34,8 +34,7 @@
 #include <windows.h>
 #include <objidl.h> /* For IStream. */
 
-#include "gpgme.h"
-#include "intern.h"
+#include "common.h"
 #include "passcache.h"
 #include "engine.h"
 
@@ -115,6 +114,14 @@ op_init (void)
                  gpgme_strerror (err));
       return err;
     }
+
+  err = gpgme_engine_check_version (GPGME_PROTOCOL_CMS);
+  if (err)
+    {
+      log_debug ("gpgme can't find a suitable CMS backend: %s\n",
+                 gpgme_strerror (err));
+      return err;
+    }
   
   init_done = 1;
   return 0;
@@ -538,7 +545,7 @@ op_decrypt (const char *inbuf, char **outbuf, int ttl, const char *filename,
       /* Now check the state of any signature. */
       res = gpgme_op_verify_result (ctx);
       if (res && res->signatures)
-        verify_dialog_box (res, filename);
+        verify_dialog_box (gpgme_get_protocol (ctx), res, filename);
       if (res && res->signatures && attestation)
         add_verify_attestation (attestation, ctx, res, filename);
     }
@@ -581,7 +588,8 @@ leave:
    is not NULL a text with the result of the signature verification
    will get printed to it. */
 static int
-decrypt_stream (gpgme_data_t in, gpgme_data_t out, int ttl,
+decrypt_stream (gpgme_protocol_t protocol,
+                gpgme_data_t in, gpgme_data_t out, int ttl,
                 const char *filename, gpgme_data_t attestation, 
                 int preview_mode)
 {    
@@ -597,7 +605,15 @@ decrypt_stream (gpgme_data_t in, gpgme_data_t out, int ttl,
   if (err)
     goto fail;
 
-  gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb);
+  err = gpgme_set_protocol (ctx, protocol);
+  if (err)
+    goto fail;
+
+  /* GPGME does not support a command handler for gpgsm.  Thus we
+     can't set the passphrase callback.  */
+  if (protocol != GPGME_PROTOCOL_CMS)
+    gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb);
+
   cb.ctx = ctx;
   if (preview_mode)
     err = gpgme_op_decrypt (ctx, in, out);
@@ -615,7 +631,7 @@ decrypt_stream (gpgme_data_t in, gpgme_data_t out, int ttl,
       /* Decryption succeeded.  Now check the state of the signatures. */
       res = gpgme_op_verify_result (ctx);
       if (res && res->signatures)
-        verify_dialog_box (res, filename);
+        verify_dialog_box (gpgme_get_protocol (ctx), res, filename);
       if (res && res->signatures && attestation)
         add_verify_attestation (attestation, ctx, res, filename);
     }
@@ -668,7 +684,8 @@ op_decrypt_stream (LPSTREAM instream, LPSTREAM outstream, int ttl,
   if (!err)
     err = gpgme_data_new_from_cbs (&out, &cbs, outstream);
   if (!err)
-    err = decrypt_stream (in, out, ttl, filename, attestation, 0);
+    err = decrypt_stream (GPGME_PROTOCOL_OpenPGP,
+                          in, out, ttl, filename, attestation, 0);
 
   if (in)
     gpgme_data_release (in);
@@ -701,7 +718,8 @@ op_decrypt_stream_to_buffer (LPSTREAM instream, char **outbuf, int ttl,
   if (!err)
     err = gpgme_data_new (&out);
   if (!err)
-    err = decrypt_stream (in, out, ttl, filename, attestation, 0);
+    err = decrypt_stream (GPGME_PROTOCOL_OpenPGP,
+                          in, out, ttl, filename, attestation, 0);
   if (!err)
     {
       /* Return the buffer but first make sure it is a string. */
@@ -725,7 +743,8 @@ op_decrypt_stream_to_buffer (LPSTREAM instream, char **outbuf, int ttl,
    FILENAME is not NULL it will be displayed along with status
    outputs. */
 int
-op_decrypt_stream_to_gpgme (LPSTREAM instream, gpgme_data_t out, int ttl,
+op_decrypt_stream_to_gpgme (gpgme_protocol_t protocol,
+                            LPSTREAM instream, gpgme_data_t out, int ttl,
                             const char *filename, gpgme_data_t attestation,
                             int preview_mode)
 {
@@ -738,7 +757,8 @@ op_decrypt_stream_to_gpgme (LPSTREAM instream, gpgme_data_t out, int ttl,
 
   err = gpgme_data_new_from_cbs (&in, &cbs, instream);
   if (!err)
-    err = decrypt_stream (in, out, ttl, filename, attestation, preview_mode);
+    err = decrypt_stream (protocol, 
+                          in, out, ttl, filename, attestation, preview_mode);
 
   if (in)
     gpgme_data_release (in);
@@ -798,7 +818,7 @@ op_verify (const char *inbuf, char **outbuf, const char *filename,
       res = gpgme_op_verify_result (ctx);
     }
   if (res) 
-    verify_dialog_box (res, filename);
+    verify_dialog_box (gpgme_get_protocol (ctx), res, filename);
   if (res && attestation)
     add_verify_attestation (attestation, ctx, res, filename);
 
@@ -852,7 +872,7 @@ op_verify_detached_sig (LPSTREAM data_stream,
     {
       res = gpgme_op_verify_result (ctx);
       if (res) 
-        verify_dialog_box (res, filename);
+        verify_dialog_box (gpgme_get_protocol (ctx), res, filename);
       if (res && attestation)
         add_verify_attestation (attestation, ctx, res, filename);
     }
@@ -902,7 +922,7 @@ op_verify_detached_sig_mem (const char *data_string,
     {
       res = gpgme_op_verify_result (ctx);
       if (res) 
-        verify_dialog_box (res, filename);
+        verify_dialog_box (gpgme_get_protocol (ctx), res, filename);
       if (res && attestation)
         add_verify_attestation (attestation, ctx, res, filename);
     }
@@ -924,7 +944,8 @@ op_verify_detached_sig_mem (const char *data_string,
    NULL a text with the result of the signature verification will get
    printed to it.  */ 
 int
-op_verify_detached_sig_gpgme (gpgme_data_t data, gpgme_data_t sig,
+op_verify_detached_sig_gpgme (gpgme_protocol_t protocol, 
+                              gpgme_data_t data, gpgme_data_t sig,
                               const char *filename, gpgme_data_t attestation)
 {
   gpgme_ctx_t ctx = NULL;
@@ -937,12 +958,16 @@ op_verify_detached_sig_gpgme (gpgme_data_t data, gpgme_data_t sig,
   if (err)
     goto leave;
 
+  err = gpgme_set_protocol (ctx, protocol);
+  if (err)
+    goto leave;
+
   err = gpgme_op_verify (ctx, sig, data, NULL);
   if (!err)
     {
       res = gpgme_op_verify_result (ctx);
       if (res) 
-        verify_dialog_box (res, filename);
+        verify_dialog_box (gpgme_get_protocol (ctx), res, filename);
       if (res && attestation)
         add_verify_attestation (attestation, ctx, res, filename);
     }
@@ -1025,7 +1050,7 @@ at_fingerprint (gpgme_data_t a, gpgme_key_t key)
 
 
 /* Print common attributes of the signature summary SUM.  Returns
-   trues if a severe warning has been encountered. */
+   true if a severe warning has been encountered. */
 static int 
 at_sig_summary (gpgme_data_t a,  
                 unsigned long sum, gpgme_signature_t sig, gpgme_key_t key)
@@ -1469,7 +1494,14 @@ keyid_from_key (gpgme_key_t k)
 const char*
 op_strerror (int err)
 {
-    return gpgme_strerror (err);
+  return gpgme_strerror (err);
+}
+
+
+const char*
+op_strsource (int err)
+{
+  return gpgme_strsource (err);
 }
 
 
index b1d3508..0b5398a 100644 (file)
@@ -64,7 +64,8 @@ int op_decrypt_stream (LPSTREAM instream, LPSTREAM outstream, int ttl,
 int op_decrypt_stream_to_buffer (LPSTREAM instream, char **outbuf, int ttl,
                                  const char *filename,
                                  gpgme_data_t attestation);
-int op_decrypt_stream_to_gpgme (LPSTREAM instream, gpgme_data_t out, int ttl,
+int op_decrypt_stream_to_gpgme (gpgme_protocol_t protocol,
+                                LPSTREAM instream, gpgme_data_t out, int ttl,
                                 const char *filename, gpgme_data_t attestation,
                                 int preview_mode);
 
@@ -75,7 +76,8 @@ int op_verify_detached_sig (LPSTREAM data, const char *sig,
 int op_verify_detached_sig_mem (const char *data_string,
                                 const char *sig_string, const char *filename,
                                 gpgme_data_t attestation);
-int op_verify_detached_sig_gpgme (gpgme_data_t data, gpgme_data_t sig,
+int op_verify_detached_sig_gpgme (gpgme_protocol_t protocol, 
+                                  gpgme_data_t data, gpgme_data_t sig,
                                   const char *filename,
                                   gpgme_data_t attestation);
 
@@ -88,7 +90,8 @@ gpgme_key_t op_get_one_key (char *pattern);
 const char *userid_from_key (gpgme_key_t k);
 const char *keyid_from_key (gpgme_key_t k);
 
-const char* op_strerror (int err);
+const char *op_strerror (int err);
+const char *op_strsource (int err);
 
 
 #ifdef __cplusplus
index a78bb78..d7c6f31 100644 (file)
@@ -28,8 +28,8 @@
 #include "mymapi.h"
 #include "mymapitags.h"
 #include "myexchext.h"
+#include "common.h"
 #include "display.h"
-#include "intern.h"
 #include "gpgmsg.hh"
 #include "msgcache.h"
 #include "engine.h"
@@ -39,6 +39,7 @@
 #include "olflange-def.h"
 #include "olflange.h"
 #include "ol-ext-callback.h"
+#include "message.h"
 #include "ext-commands.h"
 
 
@@ -81,6 +82,8 @@ GpgolExtCommands::GpgolExtCommands (GpgolExt* pParentInterface)
   m_lContext = 0; 
   m_nCmdEncrypt = 0;  
   m_nCmdSign = 0; 
+  m_nCmdShowInfo = 0;  
+  m_nCmdCheckSig = 0;
   m_nToolbarButtonID1 = 0; 
   m_nToolbarButtonID2 = 0; 
   m_nToolbarBitmap1 = 0;
@@ -206,13 +209,13 @@ GpgolExtCommands::InstallCommands (
   */
   if (m_lContext == EECONTEXT_SENDNOTEMESSAGE)
     {
-      LPMDB pMDB = NULL;
-      LPMESSAGE pMessage = NULL;
+      LPMDB mdb = NULL;
+      LPMESSAGE message = NULL;
       
       /*  Note that for read and send the object returned by the
           outlook extension callback is of class 43 (MailItem) so we
           only need to ask for Body then. */
-      hr = pEECB->GetObject (&pMDB, (LPMAPIPROP *)&pMessage);
+      hr = pEECB->GetObject (&mdb, (LPMAPIPROP *)&message);
       if (FAILED(hr))
         log_debug ("%s:%s: getObject failed: hr=%#lx\n", SRCNAME,__func__,hr);
       else if (!opt.compat.no_msgcache)
@@ -289,8 +292,8 @@ GpgolExtCommands::InstallCommands (
           xfree (key);
         }
       
-      ul_release (pMessage);
-      ul_release (pMDB);
+      ul_release (message);
+      ul_release (mdb);
     }
 
 
@@ -299,8 +302,16 @@ GpgolExtCommands::InstallCommands (
       if (opt.compat.auto_decrypt)
         watcher_set_callback_ctx ((void *)pEECB);
 
-      toolbar_add_menu (pEECB, pnCommandIDBase, "", NULL,
-                        _("&Decrypt and verify message"), &m_nCmdEncrypt,
+      if (m_pExchExt->getMsgtype (pEECB) == MSGTYPE_UNKNOWN)
+        toolbar_add_menu (pEECB, pnCommandIDBase, "", NULL,
+                          _("&Decrypt and verify message"), &m_nCmdEncrypt,
+                          NULL);
+      else
+        toolbar_add_menu (pEECB, pnCommandIDBase, "", NULL,
+                          _("&Display S/MIME information"), &m_nCmdShowInfo,
+                          NULL);
+      toolbar_add_menu (pEECB, pnCommandIDBase,
+                        _("Check &signature"), &m_nCmdCheckSig,
                         NULL);
       
       hwnd_toolbar = toolbar_from_tbe (pTBEArray, nTBECnt, &tb_idx);
@@ -438,15 +449,19 @@ GpgolExtCommands::DoCommand (
     }
   
 
-  if ((nCommandID != m_nCmdEncrypt) 
-      && (nCommandID != m_nCmdSign))
-    return S_FALSE; 
+
+  if (nCommandID != m_nCmdEncrypt
+      && nCommandID != m_nCmdSign
+      && nCommandID != m_nCmdShowInfo
+      && nCommandID != m_nCmdCheckSig)
+    return S_FALSE;
+  
 
   if (m_lContext == EECONTEXT_READNOTEMESSAGE) 
     {
       HWND hWnd = NULL;
-      LPMESSAGE pMessage = NULL;
-      LPMDB pMDB = NULL;
+      LPMESSAGE message = NULL;
+      LPMDB mdb = NULL;
 
       if (FAILED (pEECB->GetWindow (&hWnd)))
         hWnd = NULL;
@@ -454,19 +469,30 @@ GpgolExtCommands::DoCommand (
 //         log_window_hierarchy (hWnd, "%s:%s:%d: Windows hierarchy:",
 //                               SRCNAME, __func__, __LINE__);
 
-      hr = pEECB->GetObject (&pMDB, (LPMAPIPROP *)&pMessage);
+      hr = pEECB->GetObject (&mdb, (LPMAPIPROP *)&message);
       if (SUCCEEDED (hr))
         {
           if (nCommandID == m_nCmdEncrypt)
             {
-              GpgMsg *m = CreateGpgMsg (pMessage);
+              GpgMsg *m = CreateGpgMsg (message);
               m->setExchangeCallback ((void*)pEECB);
               m->decrypt (hWnd, 0);
               delete m;
            }
+          else if (nCommandID == m_nCmdShowInfo)
+            {
+              MessageBox (NULL, 
+                          _("Here you should see S/MIME related info"),
+                          "GpgOL", MB_ICONINFORMATION|MB_OK);
+            }
+          else if (nCommandID == m_nCmdCheckSig)
+            {
+              message_verify (message, m_pExchExt->getMsgtype (pEECB), 1);
+            }
+
        }
-      ul_release (pMessage);
-      ul_release (pMDB);
+      ul_release (message);
+      ul_release (mdb);
     }
   else if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
     {
@@ -507,43 +533,63 @@ GpgolExtCommands::Help (
        LPEXCHEXTCALLBACK pEECB, // The pointer to Exchange Callback Interface.
        UINT nCommandID)         // The command id.
 {
-    if (m_lContext == EECONTEXT_READNOTEMESSAGE) {
-       if (nCommandID == m_nCmdEncrypt) {
-           MessageBox (m_hWnd,
-                        _("Decrypt and verify the message."),
-                        "GpgOL", MB_OK);
-           return S_OK;
+  if (m_lContext == EECONTEXT_READNOTEMESSAGE) 
+    {
+      if (nCommandID == m_nCmdEncrypt) 
+        {
+          MessageBox (m_hWnd,
+                      _("Decrypt and verify the message."),
+                      "GpgOL", MB_OK);
+          return S_OK;
+       }
+      else if (nCommandID == m_nCmdShowInfo) 
+        {
+          MessageBox (m_hWnd,
+                      _("Show information about the S/MIME message status"),
+                      "GpgOL", MB_OK);
+          return S_OK;
+       }
+      else if (nCommandID == m_nCmdCheckSig) 
+        {
+          MessageBox (m_hWnd,
+                      _("Check the signature now and display the result"),
+                      "GpgOL", MB_OK);
+          return S_OK;
        }
     }
-    if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) {
-       if (nCommandID == m_nCmdEncrypt) {
-           MessageBox(m_hWnd,
-                       _("Select this option to encrypt the message."),
-                       "GpgOL", MB_OK);        
-           return S_OK;
+  else if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
+    {
+      if (nCommandID == m_nCmdEncrypt)
+        {
+          MessageBox (m_hWnd,
+                      _("Select this option to encrypt the message."),
+                      "GpgOL", MB_OK); 
+          return S_OK;
        } 
-       else if (nCommandID == m_nCmdSign) {
-           MessageBox(m_hWnd,
-                       _("Select this option to sign the message."),
-                       "GpgOL", MB_OK);        
-           return S_OK;
+      else if (nCommandID == m_nCmdSign) 
+        {
+          MessageBox (m_hWnd,
+                      _("Select this option to sign the message."),
+                      "GpgOL", MB_OK); 
+          return S_OK;
        } 
     }
-
-    if (m_lContext == EECONTEXT_VIEWER) {
-       if (nCommandID == m_nCmdEncrypt) {
-               MessageBox(m_hWnd, 
-                           _("Open GPG Key Manager"),
-                           "GpgOL", MB_OK);
-               return S_OK;
+  else if (m_lContext == EECONTEXT_VIEWER) 
+    {
+      if (nCommandID == m_nCmdEncrypt) 
+        {
+          MessageBox (m_hWnd, 
+                      _("Open GPG Key Manager"),
+                      "GpgOL", MB_OK);
+          return S_OK;
        } 
     }
-
-    return S_FALSE;
+  
+  return S_FALSE;
 }
 
 
-/* Called by Exhange to get the status bar text or the tooltip of a
+/* Called by Exchange to get the status bar text or the tooltip of a
    menu item.  Returns S_OK when it is a menu item of this plugin and
    the text was set; otherwise S_FALSE. */
 STDMETHODIMP 
@@ -557,49 +603,77 @@ GpgolExtCommands::QueryHelpText(
          UINT nCharCnt)    // The count of characters available in psz buffer.
 {
        
-    if (m_lContext == EECONTEXT_READNOTEMESSAGE) {
-       if (nCommandID == m_nCmdEncrypt) {
-           if (lFlags == EECQHT_STATUS)
-               lstrcpyn (pszText, ".", nCharCnt);
-           if (lFlags == EECQHT_TOOLTIP)
-               lstrcpyn (pszText,
-                          _("Decrypt message and verify signature"),
-                          nCharCnt);
-           return S_OK;
+  if (m_lContext == EECONTEXT_READNOTEMESSAGE) 
+    {
+      if (nCommandID == m_nCmdEncrypt)
+        {
+          if (lFlags == EECQHT_STATUS)
+            lstrcpyn (pszText, ".", nCharCnt);
+          if (lFlags == EECQHT_TOOLTIP)
+            lstrcpyn (pszText,
+                      _("Decrypt message and verify signature"),
+                      nCharCnt);
+          return S_OK;
+       }
+      else if (nCommandID == m_nCmdShowInfo)
+        {
+          if (lFlags == EECQHT_STATUS)
+            lstrcpyn (pszText, ".", nCharCnt);
+          if (lFlags == EECQHT_TOOLTIP)
+            lstrcpyn (pszText,
+                      _("Show S/MIME status info"),
+                      nCharCnt);
+          return S_OK;
+       }
+      else if (nCommandID == m_nCmdCheckSig)
+        {
+          if (lFlags == EECQHT_STATUS)
+            lstrcpyn (pszText, ".", nCharCnt);
+          if (lFlags == EECQHT_TOOLTIP)
+            lstrcpyn (pszText,
+                      _("Check the signature now and display the result"),
+                      nCharCnt);
+          return S_OK;
        }
     }
-    if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) {
-       if (nCommandID == m_nCmdEncrypt) {
-           if (lFlags == EECQHT_STATUS)
-               lstrcpyn (pszText, ".", nCharCnt);
-           if (lFlags == EECQHT_TOOLTIP)
-               lstrcpyn (pszText,
-                          _("Encrypt message with GPG"),
-                          nCharCnt);
-           return S_OK;
+  else if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
+    {
+      if (nCommandID == m_nCmdEncrypt) 
+        {
+          if (lFlags == EECQHT_STATUS)
+            lstrcpyn (pszText, ".", nCharCnt);
+          if (lFlags == EECQHT_TOOLTIP)
+            lstrcpyn (pszText,
+                      _("Encrypt message with GPG"),
+                      nCharCnt);
+          return S_OK;
        }
-       if (nCommandID == m_nCmdSign) {
-           if (lFlags == EECQHT_STATUS)
-               lstrcpyn (pszText, ".", nCharCnt);
-           if (lFlags == EECQHT_TOOLTIP)
-               lstrcpyn (pszText,
-                          _("Sign message with GPG"),
-                          nCharCnt);
-           return S_OK;
+      else if (nCommandID == m_nCmdSign) 
+        {
+          if (lFlags == EECQHT_STATUS)
+            lstrcpyn (pszText, ".", nCharCnt);
+          if (lFlags == EECQHT_TOOLTIP)
+            lstrcpyn (pszText,
+                      _("Sign message with GPG"),
+                      nCharCnt);
+          return S_OK;
        }
     }
-    if (m_lContext == EECONTEXT_VIEWER) {
-       if (nCommandID == m_nCmdEncrypt) {
-           if (lFlags == EECQHT_STATUS)
-               lstrcpyn (pszText, ".", nCharCnt);
-           if (lFlags == EECQHT_TOOLTIP)
+  else if (m_lContext == EECONTEXT_VIEWER) 
+    {
+      if (nCommandID == m_nCmdEncrypt) 
+        {
+          if (lFlags == EECQHT_STATUS)
+            lstrcpyn (pszText, ".", nCharCnt);
+          if (lFlags == EECQHT_TOOLTIP)
                lstrcpyn (pszText,
                           _("Open GPG Key Manager"),
                           nCharCnt);
-           return S_OK;
+          return S_OK;
        }       
     }
-    return S_FALSE;
+
+  return S_FALSE;
 }
 
 
index 3e70a28..1a4ec5c 100644 (file)
@@ -39,6 +39,8 @@ private:
   
   UINT  m_nCmdEncrypt;
   UINT  m_nCmdSign;
+  UINT  m_nCmdShowInfo;
+  UINT  m_nCmdCheckSig;
 
   UINT  m_nToolbarButtonID1;
   UINT  m_nToolbarButtonID2;     
index 7621068..e661980 100644 (file)
 
 #include "mymapi.h"
 #include "mymapitags.h"
-
-#include "intern.h"
+#include "myexchext.h"
+#include "common.h"
 #include "gpgmsg.hh"
 #include "util.h"
 #include "msgcache.h"
 #include "pgpmime.h"
 #include "engine.h"
+#include "ol-ext-callback.h"
 #include "display.h"
 #include "rfc822parse.h"
 
@@ -601,7 +602,9 @@ get_msg_content_type_cb (void *dummy_arg,
 
 
 /* Find Content-Type of the current message.  The result will be put
-   into instance variables.  */
+   into instance variables.  FIXME: This function is basically
+   duplicated in mapihelp.cpp - either remove it here or mak use of
+   the other implementation. */
 void
 GpgMsgImpl::get_msg_content_type (void)
 {
@@ -1184,7 +1187,7 @@ GpgMsgImpl::decrypt (HWND hwnd, bool info_only)
       if (!opt.compat.old_reply_hack
           && (s = msgcache_get_from_mapi (message, &refhandle)))
         {
-          update_display (hwnd, this, exchange_cb, is_html_body (s), s);
+          update_display (hwnd, exchange_cb, is_html_body (s), s);
           msgcache_unref (refhandle);
           log_debug ("%s:%s: leave (already decrypted)\n", SRCNAME, __func__);
         }
@@ -1213,7 +1216,7 @@ GpgMsgImpl::decrypt (HWND hwnd, bool info_only)
             (_("[This is a PGP/MIME message]\r\n\r\n"
                "[Use the \"Decrypt\" button in the message window "
                "to show its content.]"));        
-          update_display (hwnd, this, NULL, 0, tmp);
+          update_display (hwnd, NULL, 0, tmp);
           xfree (tmp);
         }
       
@@ -1291,7 +1294,7 @@ GpgMsgImpl::decrypt (HWND hwnd, bool info_only)
       if (!body || !*body)
         {
           char *tmp = native_to_utf8 (_("[This is a PGP/MIME message]"));
-          update_display (hwnd, this, exchange_cb, 0, tmp);
+          update_display (hwnd, exchange_cb, 0, tmp);
           xfree (tmp);
         }
       
@@ -1491,7 +1494,7 @@ GpgMsgImpl::decrypt (HWND hwnd, bool info_only)
       msgcache_put (plaintext, 0, message);
 
       if (preview)
-        update_display (hwnd, this, exchange_cb, is_html, plaintext);
+        update_display (hwnd, exchange_cb, is_html, plaintext);
       else if (opt.save_decrypted_attach)
         {
           /* User wants us to replace the encrypted message with the
@@ -1500,10 +1503,10 @@ GpgMsgImpl::decrypt (HWND hwnd, bool info_only)
           if (FAILED (hr))
             log_debug ("%s:%s: SaveChanges failed: hr=%#lx",
                        SRCNAME, __func__, hr);
-          update_display (hwnd, this, exchange_cb, is_html, plaintext);
+          update_display (hwnd, exchange_cb, is_html, plaintext);
           
         }
-      else if (update_display (hwnd, this, exchange_cb, is_html, plaintext))
+      else if (update_display (hwnd, exchange_cb, is_html, plaintext))
         {
           const char *s = 
             _("The message text cannot be displayed.\n"
index a8a1f47..2ea715f 100644 (file)
@@ -21,9 +21,7 @@
 #ifndef GPGMSG_HH
 #define GPGMSG_HH
 
-#include <gpgme.h>
-
-#include "intern.h"
+#include "common.h"
 
 /* To manage a message we use our own class to keep track about all
    the information we known on the content of a message.  This is
index 5ed8920..b3eb2a6 100644 (file)
 #include <config.h>
 
 #include <windows.h>
-
-#include <gpgme.h>
+#include <wincrypt.h>
 
 #include "mymapi.h"
 #include "mymapitags.h"
 
-
-#include "intern.h"
+#include "common.h"
 #include "passcache.h"
 #include "msgcache.h"
 #include "mymapi.h"
@@ -45,6 +43,9 @@ static FILE *logfp;
    functions.  This lock is controlled by this Mutex. */
 static HANDLE log_mutex;
 
+/* The session key used to temporary encrypt attachments.  It is
+   initialized at startup.  */
+static char *the_session_key;
 
 /* Local function prototypes. */
 static char *get_locale_dir (void);
@@ -81,6 +82,37 @@ initialize_main (void)
   return log_mutex? 0 : -1;
 }
 
+/* Return nbytes of cryptographic strong random.  Caller needs to free
+   the returned buffer.  */
+static char *
+get_crypt_random (size_t nbytes) 
+{
+  HCRYPTPROV prov;
+  char *buffer;
+
+  if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL, 
+                            (CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
+    return NULL;
+  
+  buffer = xmalloc (nbytes);
+  if (!CryptGenRandom (prov, nbytes, buffer))
+    {
+      xfree (buffer);
+      buffer = NULL;
+    }
+  CryptReleaseContext (prov, 0);
+  return buffer;
+}
+
+
+static int
+initialize_session_key (void)
+{
+  the_session_key = get_crypt_random (16);
+  return !the_session_key;
+}
+
+
 static void
 i18n_init (void)
 {
@@ -113,7 +145,7 @@ DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
     {
       set_global_hinstance (hinst);
       /* The next call initializes subsystems of gpgme and should be
-         done as early as possible.  The actual return value is (the
+         done as early as possible.  The actual return value (the
          version string) is not used here.  It may be called at any
          time later for this. */
       gpgme_check_version (NULL);
@@ -122,6 +154,8 @@ DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
       if (initialize_main ())
         return FALSE;
       i18n_init ();
+      if (initialize_session_key ())
+        return FALSE;
       if (initialize_passcache ())
         return FALSE;
       if (initialize_msgcache ())
@@ -137,6 +171,25 @@ DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
 }
 
 
+
+/* Return the static session key we are using for temporary encrypting
+   attachments.  The session key is guaranteed to be available.  */
+const void *
+get_128bit_session_key (void)
+{
+  return the_session_key;
+}
+
+
+/* Return a new allocated IV of size NBYTES.  Caller must free it.  On
+   error NULL is returned. */
+void *
+create_initialization_vector (size_t nbytes)
+{
+  return get_crypt_random (nbytes);
+}
+
+
 /* Acquire the mutex for logging.  Returns 0 on success. */
 static int 
 lock_log (void)
@@ -348,6 +401,8 @@ set_log_file (const char *name)
     }
 }
 
+
+
 void
 set_default_key (const char *name)
 {
index 9cf1616..ec59a2f 100644 (file)
@@ -27,7 +27,9 @@
 
 #include "mymapi.h"
 #include "mymapitags.h"
-#include "intern.h"
+#include "common.h"
+#include "rfc822parse.h"
+#include "serpent.h"
 #include "mapihelp.h"
 
 
@@ -88,6 +90,94 @@ log_mapi_property (LPMESSAGE message, ULONG prop, const char *propname)
 }
 
 
+/* Return the property tag for GpgOL Attach Type. */
+int 
+get_gpgolattachtype_tag (LPMESSAGE message, ULONG *r_tag)
+{
+  HRESULT hr;
+  LPSPropTagArray proparr = NULL;
+  MAPINAMEID mnid, *pmnid;     
+  /* {31805ab8-3e92-11dc-879c-00061b031004}: GpgOL custom properties.  */
+  GUID guid = {0x31805ab8, 0x3e92, 0x11dc, {0x87, 0x9c, 0x00, 0x06,
+                                            0x1b, 0x03, 0x10, 0x04}};
+
+  memset (&mnid, 0, sizeof mnid);
+  mnid.lpguid = &guid;
+  mnid.ulKind = MNID_STRING;
+  mnid.Kind.lpwstrName = L"GpgOL Attach Type";
+  pmnid = &mnid;
+  hr = message->GetIDsFromNames (1, &pmnid, MAPI_CREATE, &proparr);
+  if (FAILED (hr)) 
+    {
+      log_error ("%s:%s: can't map %s property: hr=%#lx\n",
+                 SRCNAME, __func__, "GpgOL Attach Type", hr); 
+      return -1;
+    }
+    
+  *r_tag = ((proparr->aulPropTag[0] & 0xFFFF0000) | PT_LONG);
+  return 0;
+}
+
+
+/* Return the property tag for GpgOL Sig Status. */
+int 
+get_gpgolsigstatus_tag (LPMESSAGE message, ULONG *r_tag)
+{
+  HRESULT hr;
+  LPSPropTagArray proparr = NULL;
+  MAPINAMEID mnid, *pmnid;     
+  /* {31805ab8-3e92-11dc-879c-00061b031004}: GpgOL custom properties.  */
+  GUID guid = {0x31805ab8, 0x3e92, 0x11dc, {0x87, 0x9c, 0x00, 0x06,
+                                            0x1b, 0x03, 0x10, 0x04}};
+
+  memset (&mnid, 0, sizeof mnid);
+  mnid.lpguid = &guid;
+  mnid.ulKind = MNID_STRING;
+  mnid.Kind.lpwstrName = L"GpgOL Sig Status";
+  pmnid = &mnid;
+  hr = message->GetIDsFromNames (1, &pmnid, MAPI_CREATE, &proparr);
+  if (FAILED (hr)) 
+    {
+      log_error ("%s:%s: can't map %s property: hr=%#lx\n",
+                 SRCNAME, __func__, "GpgOL Sig Status", hr); 
+      return -1;
+    }
+    
+  *r_tag = ((proparr->aulPropTag[0] & 0xFFFF0000) | PT_STRING8);
+  return 0;
+}
+
+
+/* Return the property tag for GpgOL Protect IV. */
+int 
+get_gpgolprotectiv_tag (LPMESSAGE message, ULONG *r_tag)
+{
+  HRESULT hr;
+  LPSPropTagArray proparr = NULL;
+  MAPINAMEID mnid, *pmnid;     
+  /* {31805ab8-3e92-11dc-879c-00061b031004}: GpgOL custom properties.  */
+  GUID guid = {0x31805ab8, 0x3e92, 0x11dc, {0x87, 0x9c, 0x00, 0x06,
+                                            0x1b, 0x03, 0x10, 0x04}};
+
+  memset (&mnid, 0, sizeof mnid);
+  mnid.lpguid = &guid;
+  mnid.ulKind = MNID_STRING;
+  mnid.Kind.lpwstrName = L"GpgOL Protect IV";
+  pmnid = &mnid;
+  hr = message->GetIDsFromNames (1, &pmnid, MAPI_CREATE, &proparr);
+  if (FAILED (hr)) 
+    {
+      log_error ("%s:%s: can't map %s property: hr=%#lx\n",
+                 SRCNAME, __func__, "GpgOL Protect IV", hr); 
+      return -1;
+    }
+    
+  *r_tag = ((proparr->aulPropTag[0] & 0xFFFF0000) | PT_BINARY);
+  return 0;
+}
+
+
+
 /* This function checks whether MESSAGE requires processing by us and
    adjusts the message class to our own.  Return true if the message
    was changed. */
@@ -114,15 +204,80 @@ mapi_change_message_class (LPMESSAGE message)
   if ( PROP_TYPE (propval->ulPropTag) == PT_STRING8 )
     {
       const char *s = propval->Value.lpszA;
-      if (!strncmp (s, "IPM.Note.SMIME", 14) && (!s[14] || s[14] =='.'))
+
+      if (!strcmp (s, "IPM.Note"))
+        {
+          /* Most message today are of this type.  However a PGP/MIME
+             encrypted message although has this class here.  We need
+             to see whether we can detect such a mail right here and
+             change the message class accordingly. */
+          char *ct, *proto;
+
+          ct = mapi_get_message_content_type (message, &proto, NULL);
+          if (!ct)
+            log_debug ("%s:%s: message has no content type", 
+                       SRCNAME, __func__);
+          else
+            {
+              log_debug ("%s:%s: content type is '%s'", 
+                         SRCNAME, __func__, ct);
+              if (proto)
+                {
+                  log_debug ("%s:%s:     protocol is '%s'", 
+                             SRCNAME, __func__, proto);
+              
+                  if (!strcmp (ct, "multipart/encrypted")
+                      && !strcmp (proto, "application/pgp-encrypted"))
+                    newvalue = xstrdup ("IPM.Note.GpgOL.MultipartEncrypted");
+                  xfree (proto);
+                }
+              xfree (ct);
+            }
+        }
+      else if (!strcmp (s, "IPM.Note.SMIME"))
+        {
+          /* This is an S/MIME opaque encrypted or signed message.
+             Check what it really is.  */
+          char *ct, *smtype;
+
+          ct = mapi_get_message_content_type (message, NULL, &smtype);
+          if (!ct)
+            log_debug ("%s:%s: message has no content type", 
+                       SRCNAME, __func__);
+          else
+            {
+              log_debug ("%s:%s: content type is '%s'", 
+                         SRCNAME, __func__, ct);
+              if (smtype)
+                {
+                  log_debug ("%s:%s:   smime-type is '%s'", 
+                             SRCNAME, __func__, smtype);
+              
+                  if (!strcmp (ct, "application/pkcs7-mime")
+                      || !strcmp (ct, "application/x-pkcs7-mime"))
+                    {
+                      if (!strcmp (smtype, "signed-data"))
+                        newvalue = xstrdup ("IPM.Note.GpgOL.OpaqueSigned");
+                      else if (!strcmp (smtype, "enveloped-data"))
+                        newvalue = xstrdup ("IPM.Note.GpgOL.OpaqueEncrypted");
+                    }
+                  xfree (smtype);
+                }
+              xfree (ct);
+            }
+          if (!newvalue)
+            newvalue = xstrdup ("IPM.Note.GpgOL");
+        }
+      else if (!strncmp (s, "IPM.Note.SMIME", 14) && (!s[14] || s[14] =='.'))
         {
-          /* This is either "IPM.Note.SMIME" or "IPM.Note.SMIME.foo".
-             Note that we ncan't just insert a new aprt and keep the
-             SMIME; we need to change the SMIME part of the class name
-             so that Outlook does not proxcess it as an SMIME
+          /* This is "IPM.Note.SMIME.foo" (where ".foo" is optional
+             but the previous condition has already taken care of
+             this.  Note that we can't just insert a new part and keep
+             the SMIME; we need to change the SMIME part of the class
+             name so that Outlook does not proxcess it as an SMIME
              message. */
           newvalue = (char*)xmalloc (strlen (s) + 1);
-          strcpy (stpcpy (newvalue, "IPM.Note.GpgSM"), s+14);
+          strcpy (stpcpy (newvalue, "IPM.Note.GpgOL"), s+14);
         }
     }
   MAPIFreeBuffer (propval);
@@ -152,96 +307,921 @@ mapi_change_message_class (LPMESSAGE message)
 }
 
 
-/* Return the message class as a scalar.  This function knows only
-   about out own message classes.  Returns MSGCLS_UNKNOWN for any
-   MSGCLASS we have no special support for.  */
-msgclass_t
-mapi_get_message_class (LPMESSAGE message)
+/* Return the message type.  This function knows only about our own
+   message types.  Returns MSGTYPE_UNKNOWN for any MESSAGE we have
+   no special support for.  */
+msgtype_t
+mapi_get_message_type (LPMESSAGE message)
 {
   HRESULT hr;
   LPSPropValue propval = NULL;
-  msgclass_t msgcls = MSGCLS_UNKNOWN;
+  msgtype_t msgtype = MSGTYPE_UNKNOWN;
 
   if (!message)
-    return msgcls
+    return msgtype
 
   hr = HrGetOneProp ((LPMAPIPROP)message, PR_MESSAGE_CLASS_A, &propval);
   if (FAILED (hr))
     {
       log_error ("%s:%s: HrGetOneProp() failed: hr=%#lx\n",
                  SRCNAME, __func__, hr);
-      return msgcls;
+      return msgtype;
     }
     
   if ( PROP_TYPE (propval->ulPropTag) == PT_STRING8 )
     {
       const char *s = propval->Value.lpszA;
-      if (!strncmp (s, "IPM.Note.GpgSM", 14) && (!s[14] || s[14] =='.'))
+      if (!strncmp (s, "IPM.Note.GpgOL", 14) && (!s[14] || s[14] =='.'))
         {
           s += 14;
           if (!*s)
-            msgcls = MSGCLS_GPGSM;
+            msgtype = MSGTYPE_GPGOL;
           else if (!strcmp (s, ".MultipartSigned"))
-            msgcls = MSGCLS_GPGSM_MULTIPART_SIGNED;
+            msgtype = MSGTYPE_GPGOL_MULTIPART_SIGNED;
+          else if (!strcmp (s, ".MultipartEncrypted"))
+            msgtype = MSGTYPE_GPGOL_MULTIPART_ENCRYPTED;
+          else if (!strcmp (s, ".OpaqueSigned"))
+            msgtype = MSGTYPE_GPGOL_OPAQUE_SIGNED;
+          else if (!strcmp (s, ".OpaqueEncrypted"))
+            msgtype = MSGTYPE_GPGOL_OPAQUE_ENCRYPTED;
           else
             log_debug ("%s:%s: message class `%s' not supported",
                        SRCNAME, __func__, s-14);
         }
     }
   MAPIFreeBuffer (propval);
-  return msgcls;
+  return msgtype;
 }
 
 
 /* This function is pretty useless because IConverterSession won't
-   take attachments in to account.  Need to write our own version.  */
-// int
-// mapi_to_mime (LPMESSAGE message, const char *filename)
-// {
-//   HRESULT hr;
-//   LPCONVERTERSESSION session;
-//   LPSTREAM stream;
-
-//   hr = CoCreateInstance (CLSID_IConverterSession, NULL, CLSCTX_INPROC_SERVER,
-//                          IID_IConverterSession, (void **) &session);
-//   if (FAILED (hr))
-//     {
-//       log_error ("%s:%s: can't create new IConverterSession object: hr=%#lx",
-//                  SRCNAME, __func__, hr);
-//       return -1;
-//     }
-
-
-//   hr = OpenStreamOnFile (MAPIAllocateBuffer, MAPIFreeBuffer,
-//                          (STGM_CREATE | STGM_READWRITE),
-//                          (char*)filename, NULL, &stream); 
-//   if (FAILED (hr)) 
-//     {
-//       log_error ("%s:%s: can't create file `%s': hr=%#lx\n",
-//                  SRCNAME, __func__, filename, hr); 
-//       hr = -1;
-//     }
-//   else
-//     {
-//       hr = session->MAPIToMIMEStm (message, stream, 0);
-//       if (FAILED (hr))
-//         {
-//           log_error ("%s:%s: MAPIToMIMEStm failed: hr=%#lx",
-//                      SRCNAME, __func__, hr);
-//           stream->Revert ();
-//           hr = -1;
-//         }
-//       else
-//         {
-//           stream->Commit (0);
-//           hr = 0;
-//         }
-
-//       stream->Release ();
-//     }
-
-//   session->Release ();
-//   return hr;
-// }
+   take attachments into account.  Need to write our own version.  */
+int
+mapi_to_mime (LPMESSAGE message, const char *filename)
+{
+  HRESULT hr;
+  LPCONVERTERSESSION session;
+  LPSTREAM stream;
+
+  hr = CoCreateInstance (CLSID_IConverterSession, NULL, CLSCTX_INPROC_SERVER,
+                         IID_IConverterSession, (void **) &session);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: can't create new IConverterSession object: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      return -1;
+    }
+
+
+  hr = OpenStreamOnFile (MAPIAllocateBuffer, MAPIFreeBuffer,
+                         (STGM_CREATE | STGM_READWRITE),
+                         (char*)filename, NULL, &stream); 
+  if (FAILED (hr)) 
+    {
+      log_error ("%s:%s: can't create file `%s': hr=%#lx\n",
+                 SRCNAME, __func__, filename, hr); 
+      hr = -1;
+    }
+  else
+    {
+      hr = session->MAPIToMIMEStm (message, stream, CCSF_SMTP);
+      if (FAILED (hr))
+        {
+          log_error ("%s:%s: MAPIToMIMEStm failed: hr=%#lx",
+                     SRCNAME, __func__, hr);
+          stream->Revert ();
+          hr = -1;
+        }
+      else
+        {
+          stream->Commit (0);
+          hr = 0;
+        }
+
+      stream->Release ();
+    }
+
+  session->Release ();
+  return hr;
+}
+
+
+/* Return a binary propery in a malloced buffer with its length stored
+   at R_NBYTES.  Returns NULL on error.  */
+char *
+mapi_get_binary_prop (LPMESSAGE message, ULONG proptype, size_t *r_nbytes)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  char *data;
+
+  *r_nbytes = 0;
+  hr = HrGetOneProp ((LPMAPIPROP)message, proptype, &propval);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: error getting property %#lx: hr=%#lx",
+                 SRCNAME, __func__, proptype, hr);
+      return NULL; 
+    }
+  switch ( PROP_TYPE (propval->ulPropTag) )
+    {
+    case PT_BINARY:
+      /* This is a binary object but we know that it must be plain
+         ASCII due to the armored format.  */
+      data = (char*)xmalloc (propval->Value.bin.cb + 1);
+      memcpy (data, propval->Value.bin.lpb, propval->Value.bin.cb);
+      data[propval->Value.bin.cb] = 0;
+      *r_nbytes = propval->Value.bin.cb;
+      break;
+      
+    default:
+      log_debug ("%s:%s: requested property %#lx has unknown tag %#lx\n",
+                 SRCNAME, __func__, proptype, propval->ulPropTag);
+      data = NULL;
+      break;
+    }
+  MAPIFreeBuffer (propval);
+  return data;
+}
+
+
+/* Return the attachment method for attachment OBJ.  In case of error
+   we return 0 which happens not to be defined.  */
+static int
+get_attach_method (LPATTACH obj)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  int method ;
+
+  hr = HrGetOneProp ((LPMAPIPROP)obj, PR_ATTACH_METHOD, &propval);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: error getting attachment method: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      return 0; 
+    }
+  /* We don't bother checking whether we really get a PT_LONG ulong
+     back; if not the system is seriously damaged and we can't do
+     further harm by returning a possible random value.  */
+  method = propval->Value.l;
+  MAPIFreeBuffer (propval);
+  return method;
+}
+
+
+
+/* Return the filename from the attachment as a malloced string.  The
+   encoding we return will be UTF-8, however the MAPI docs declare
+   that MAPI does only handle plain ANSI and thus we don't really care
+   later on.  In fact we would need to convert the filename back to
+   wchar and use the Unicode versions of the file API.  Returns NULL
+   on error or if no filename is available. */
+static char *
+get_attach_filename (LPATTACH obj)
+{
+  HRESULT hr;
+  LPSPropValue propval;
+  char *name = NULL;
+
+  hr = HrGetOneProp ((LPMAPIPROP)obj, PR_ATTACH_LONG_FILENAME, &propval);
+  if (FAILED(hr)) 
+    hr = HrGetOneProp ((LPMAPIPROP)obj, PR_ATTACH_FILENAME, &propval);
+  if (FAILED(hr))
+    {
+      log_debug ("%s:%s: no filename property found", SRCNAME, __func__);
+      return NULL;
+    }
+
+  switch ( PROP_TYPE (propval->ulPropTag) )
+    {
+    case PT_UNICODE:
+      name = wchar_to_utf8 (propval->Value.lpszW);
+      if (!name)
+        log_debug ("%s:%s: error converting to utf8\n", SRCNAME, __func__);
+      break;
+      
+    case PT_STRING8:
+      name = xstrdup (propval->Value.lpszA);
+      break;
+      
+    default:
+      log_debug ("%s:%s: proptag=%#lx not supported\n",
+                 SRCNAME, __func__, propval->ulPropTag);
+      name = NULL;
+      break;
+    }
+  MAPIFreeBuffer (propval);
+  return name;
+}
+
+
+/* Return the content-type of the attachment OBJ or NULL if it does
+   not exists.  Caller must free. */
+static char *
+get_attach_mime_tag (LPATTACH obj)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  char *name;
+
+  hr = HrGetOneProp ((LPMAPIPROP)obj, PR_ATTACH_MIME_TAG_A, &propval);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: error getting attachment's MIME tag: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      return NULL; 
+    }
+  switch ( PROP_TYPE (propval->ulPropTag) )
+    {
+    case PT_UNICODE:
+      name = wchar_to_utf8 (propval->Value.lpszW);
+      if (!name)
+        log_debug ("%s:%s: error converting to utf8\n", SRCNAME, __func__);
+      break;
+      
+    case PT_STRING8:
+      name = xstrdup (propval->Value.lpszA);
+      break;
+      
+    default:
+      log_debug ("%s:%s: proptag=%#lx not supported\n",
+                 SRCNAME, __func__, propval->ulPropTag);
+      name = NULL;
+      break;
+    }
+  MAPIFreeBuffer (propval);
+  return name;
+}
+
+
+/* Return the GpgOL Attach Type for attachment OBJ.  Tag needs to be
+   the tag of that property. */
+static attachtype_t
+get_gpgolattachtype (LPATTACH obj, ULONG tag)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  attachtype_t retval;
+
+  hr = HrGetOneProp ((LPMAPIPROP)obj, tag, &propval);
+  if (FAILED (hr))
+    {
+      if (hr != MAPI_E_NOT_FOUND)
+        log_error ("%s:%s: error getting GpgOL Attach Type: hr=%#lx",
+                   SRCNAME, __func__, hr);
+      return ATTACHTYPE_UNKNOWN; 
+    }
+  retval = (attachtype_t)propval->Value.l;
+  MAPIFreeBuffer (propval);
+  return retval;
+}
+
+
+/* Gather information about attachments and return a new table of
+   attachments.  Caller must release the returned table.s The routine
+   will return NULL in case of an error or if no attachments are
+   available.  With FAST set only some information gets collected. */
+mapi_attach_item_t *
+mapi_create_attach_table (LPMESSAGE message, int fast)
+{    
+  HRESULT hr;
+  SizedSPropTagArray (1L, propAttNum) = { 1L, {PR_ATTACH_NUM} };
+  LPMAPITABLE mapitable;
+  LPSRowSet   mapirows;
+  mapi_attach_item_t *table; 
+  unsigned int pos, n_attach;
+  ULONG moss_tag;
+
+  if (get_gpgolattachtype_tag (message, &moss_tag) )
+    return NULL;
+
+  /* Open the attachment table.  */
+  hr = message->GetAttachmentTable (0, &mapitable);
+  if (FAILED (hr))
+    {
+      log_debug ("%s:%s: GetAttachmentTable failed: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      return NULL;
+    }
+      
+  hr = HrQueryAllRows (mapitable, (LPSPropTagArray)&propAttNum,
+                       NULL, NULL, 0, &mapirows);
+  if (FAILED (hr))
+    {
+      log_debug ("%s:%s: HrQueryAllRows failed: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      mapitable->Release ();
+      return NULL;
+    }
+  n_attach = mapirows->cRows > 0? mapirows->cRows : 0;
+
+  log_debug ("%s:%s: message has %u attachments\n",
+             SRCNAME, __func__, n_attach);
+  if (!n_attach)
+    {
+      FreeProws (mapirows);
+      mapitable->Release ();
+      return NULL;
+    }
+
+  /* Allocate our own table.  */
+  table = (mapi_attach_item_t *)xcalloc (n_attach+1, sizeof *table);
+  for (pos=0; pos < n_attach; pos++) 
+    {
+      LPATTACH att;
+
+      hr = message->OpenAttach (pos, NULL, MAPI_BEST_ACCESS, &att);    
+      if (FAILED (hr))
+        {
+          log_error ("%s:%s: can't open attachment %d: hr=%#lx",
+                     SRCNAME, __func__, pos, hr);
+          table[pos].mapipos = -1;
+          continue;
+        }
+
+      table[pos].mapipos = pos;
+      table[pos].method = get_attach_method (att);
+      table[pos].filename = fast? NULL : get_attach_filename (att);
+      table[pos].content_type = fast? NULL : get_attach_mime_tag (att);
+      if (table[pos].content_type)
+        {
+          char *p = strchr (table[pos].content_type, ';');
+          if (p)
+            {
+              *p++ = 0;
+              trim_trailing_spaces (table[pos].content_type);
+              while (strchr (" \t\r\n", *p))
+                p++;
+              trim_trailing_spaces (p);
+              table[pos].content_type_parms = p;
+            }
+        }
+      table[pos].attach_type = get_gpgolattachtype (att, moss_tag);
+      att->Release ();
+    }
+  table[pos].end_of_table = 1;
+  FreeProws (mapirows);
+  mapitable->Release ();
+
+  if (fast)
+    {
+      log_debug ("%s:%s: attachment info: not shown due to fast flag\n",
+                 SRCNAME, __func__);
+    }
+  else
+    {
+      log_debug ("%s:%s: attachment info:\n", SRCNAME, __func__);
+      for (pos=0; !table[pos].end_of_table; pos++)
+        {
+          log_debug ("\t%d mt=%d fname=`%s' ct=`%s' ct_parms=`%s'\n",
+                     table[pos].mapipos,
+                     table[pos].attach_type,
+                     table[pos].filename, table[pos].content_type,
+                     table[pos].content_type_parms);
+        }
+    }
+
+  return table;
+}
+
+
+/* Release a table as created by mapi_create_attach_table. */
+void
+mapi_release_attach_table (mapi_attach_item_t *table)
+{
+  unsigned int pos;
+
+  if (!table)
+    return;
+
+  for (pos=0; !table[pos].end_of_table; pos++)
+    {
+      xfree (table[pos].filename);
+      xfree (table[pos].content_type);
+    }
+  xfree (table);
+}
+
+
+/* Return an attachment as a new IStream object.  Returns NULL on
+   failure. */
+LPSTREAM
+mapi_get_attach_as_stream (LPMESSAGE message, mapi_attach_item_t *item)
+{
+  HRESULT hr;
+  LPATTACH att;
+  LPSTREAM stream;
+
+  if (!item || item->end_of_table || item->mapipos == -1)
+    return NULL;
+
+  hr = message->OpenAttach (item->mapipos, NULL, MAPI_BEST_ACCESS, &att);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: can't open attachment at %d: hr=%#lx",
+                 SRCNAME, __func__, item->mapipos, hr);
+      return NULL;
+    }
+  if (item->method != ATTACH_BY_VALUE)
+    {
+      log_error ("%s:%s: attachment: method not supported", SRCNAME, __func__);
+      att->Release ();
+      return NULL;
+    }
+
+  hr = att->OpenProperty (PR_ATTACH_DATA_BIN, &IID_IStream, 
+                          0, 0, (LPUNKNOWN*) &stream);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: can't open data stream of attachment: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      att->Release ();
+      return NULL;
+    }
+
+  att->Release ();
+
+  return stream;
+}
+
+
+/* Return a malloced buffer with the content of the attachment. If
+   R_NBYTES is not NULL the number of bytes will get stored there.
+   ATT must have an attachment method of ATATCH_BY_VALUE.  Returns
+   NULL on error.  If UNPROTECT is set and the appropriate crypto
+   attribute is available, the function returns the unprotected
+   version of the atatchment. */
+static char *
+attach_to_buffer (LPATTACH att, size_t *r_nbytes, int unprotect, 
+                  int *r_was_protected)
+{
+  HRESULT hr;
+  LPSTREAM stream;
+  STATSTG statInfo;
+  ULONG nread;
+  char *buffer;
+  symenc_t symenc = NULL;
+
+  if (r_was_protected)
+    *r_was_protected = 0;
+
+  if (unprotect)
+    {
+      ULONG tag;
+      char *iv;
+      size_t ivlen;
+
+      if (!get_gpgolprotectiv_tag ((LPMESSAGE)att, &tag) 
+          && (iv = mapi_get_binary_prop ((LPMESSAGE)att, tag, &ivlen)))
+        {
+          symenc = symenc_open (get_128bit_session_key (), 16, iv, ivlen);
+          xfree (iv);
+          if (!symenc)
+            log_error ("%s:%s: can't open encryption context", 
+                       SRCNAME, __func__);
+        }
+    }
+  
+
+  hr = att->OpenProperty (PR_ATTACH_DATA_BIN, &IID_IStream, 
+                          0, 0, (LPUNKNOWN*) &stream);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: can't open data stream of attachment: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      return NULL;
+    }
+
+  hr = stream->Stat (&statInfo, STATFLAG_NONAME);
+  if ( hr != S_OK )
+    {
+      log_error ("%s:%s: Stat failed: hr=%#lx", SRCNAME, __func__, hr);
+      stream->Release ();
+      return NULL;
+    }
+      
+  /* Allocate one byte more so that we can terminate the string.  */
+  buffer = (char*)xmalloc ((size_t)statInfo.cbSize.QuadPart + 1);
+
+  hr = stream->Read (buffer, (size_t)statInfo.cbSize.QuadPart, &nread);
+  if ( hr != S_OK )
+    {
+      log_error ("%s:%s: Read failed: hr=%#lx", SRCNAME, __func__, hr);
+      xfree (buffer);
+      stream->Release ();
+      return NULL;
+    }
+  if (nread != statInfo.cbSize.QuadPart)
+    {
+      log_error ("%s:%s: not enough bytes returned\n", SRCNAME, __func__);
+      xfree (buffer);
+      buffer = NULL;
+    }
+  stream->Release ();
+
+  if (buffer && symenc)
+    {
+      symenc_cfb_decrypt (symenc, buffer, buffer, nread);
+      if (nread < 16 || memcmp (buffer, "GpgOL attachment", 16))
+        {
+          xfree (buffer);
+          buffer = native_to_utf8 
+            (_("[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]"));
+          nread = strlen (buffer);
+        }
+      else
+        {
+          memmove (buffer, buffer+16, nread-16);
+          nread -= 16;
+          if (r_was_protected)
+            *r_was_protected = 1;
+        }
+    }
+
+  /* Make sure that the buffer is a C string.  */
+  if (buffer)
+    buffer[nread] = 0;
+
+  symenc_close (symenc);
+  if (r_nbytes)
+    *r_nbytes = nread;
+  return buffer;
+}
+
+
+
+/* Return an attachment as a malloced buffer; The size of the buffer
+   will be stored at R_NBYTES.  Returns NULL on failure. */
+char *
+mapi_get_attach (LPMESSAGE message, mapi_attach_item_t *item, size_t *r_nbytes)
+{
+  HRESULT hr;
+  LPATTACH att;
+  char *buffer;
+
+  if (!item || item->end_of_table || item->mapipos == -1)
+    return NULL;
+
+  hr = message->OpenAttach (item->mapipos, NULL, MAPI_BEST_ACCESS, &att);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: can't open attachment at %d: hr=%#lx",
+                 SRCNAME, __func__, item->mapipos, hr);
+      return NULL;
+    }
+  if (item->method != ATTACH_BY_VALUE)
+    {
+      log_error ("%s:%s: attachment: method not supported", SRCNAME, __func__);
+      att->Release ();
+      return NULL;
+    }
+
+  buffer = attach_to_buffer (att, r_nbytes, 0, NULL);
+  att->Release ();
+
+  return buffer;
+}
+
+
+/* Mark this attachment as the orginal MOSS message.  We set a custom
+   property as weel ast the hidden hidden flag on ot..  */
+int 
+mapi_mark_moss_attach (LPMESSAGE message, mapi_attach_item_t *item)
+{
+  int retval = -1;
+  HRESULT hr;
+  LPATTACH att;
+  SPropValue prop;
+
+  if (!item || item->end_of_table || item->mapipos == -1)
+    return -1;
+
+  hr = message->OpenAttach (item->mapipos, NULL, MAPI_BEST_ACCESS, &att);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: can't open attachment at %d: hr=%#lx",
+                 SRCNAME, __func__, item->mapipos, hr);
+      return -1;
+    }
+
+  if (FAILED (hr)) 
+    {
+      log_error ("%s:%s: can't map %s property: hr=%#lx\n",
+                 SRCNAME, __func__, "GpgOL Attach Type", hr); 
+      goto leave;
+    }
+    
+  if (get_gpgolattachtype_tag (message, &prop.ulPropTag) )
+    goto leave;
+  prop.Value.l = ATTACHTYPE_MOSS;
+  hr = HrSetOneProp (att, &prop);      
+  if (hr)
+    {
+      log_error ("%s:%s: can't set %s property: hr=%#lx\n",
+                 SRCNAME, __func__, "GpgOL Attach Type", hr); 
+      return false;
+    }
+
+  prop.ulPropTag = PR_ATTACHMENT_HIDDEN;
+  prop.Value.b = TRUE;
+  hr = HrSetOneProp (att, &prop);
+  if (hr)
+    {
+      log_error ("%s:%s: can't set hidden attach flag: hr=%#lx\n",
+                 SRCNAME, __func__, hr); 
+      goto leave;
+    }
+  
+
+  hr = att->SaveChanges (KEEP_OPEN_READWRITE);
+  if (hr)
+    {
+      log_error ("%s:%s: SaveChanges(attachment) failed: hr=%#lx\n",
+                 SRCNAME, __func__, hr); 
+      goto leave;
+    }
+  
+  retval = 0;
+    
+ leave:
+  att->Release ();
+  return retval;
+}
+
+
+
+/* Returns True if MESSAGE has a GpgOL Sig Status property.  */
+int
+mapi_has_sig_status (LPMESSAGE msg)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  ULONG tag;
+  int yes;
+
+  if (get_gpgolsigstatus_tag (msg, &tag) )
+    return 0; /* Error:  Assume No.  */
+  hr = HrGetOneProp ((LPMAPIPROP)msg, tag, &propval);
+  if (FAILED (hr))
+    return 0; /* No.  */  
+  if (PROP_TYPE (propval->ulPropTag) == PT_STRING8)
+    yes = !(propval->Value.lpszA && !strcmp (propval->Value.lpszA, "?"));
+  else
+    yes = 0;
+
+  MAPIFreeBuffer (propval);
+  return yes;
+}
+
+
+/* Set the signature status property to STATUS_STRING.  To set the
+   status to not checked, set it to "?".  Note that this function does
+   not call SaveChanges.  */
+int 
+mapi_set_sig_status (LPMESSAGE message, const char *status_string)
+{
+  HRESULT hr;
+  SPropValue prop;
+
+  if (get_gpgolsigstatus_tag (message, &prop.ulPropTag) )
+    return -1;
+  prop.Value.lpszA = xstrdup (status_string);
+  hr = HrSetOneProp (message, &prop);  
+  xfree (prop.Value.lpszA);
+  if (hr)
+    {
+      log_error ("%s:%s: can't set %s property: hr=%#lx\n",
+                 SRCNAME, __func__, "GpgOL Sig Status", hr); 
+      return -1;
+    }
+
+  return 0;
+}
+
+
+/* Helper for mapi_get_msg_content_type() */
+static int
+get_message_content_type_cb (void *dummy_arg,
+                             rfc822parse_event_t event, rfc822parse_t msg)
+{
+  if (event == RFC822PARSE_T2BODY)
+    return 42; /* Hack to stop the parsing after having read the
+                  outher headers. */
+  return 0;
+}
+
+
+/* Return Content-Type of the current message.  This one is taken
+   directly from the rfc822 header.  If R_PROTOCOL is not NULL a
+   string with the protocol parameter will be stored at this address,
+   if no protocol is given NULL will be stored.  If R_SMTYPE is not
+   NULL a string with the smime-type parameter will be stored there.
+   Caller must release all returned strings.  */
+char *
+mapi_get_message_content_type (LPMESSAGE message,
+                               char **r_protocol, char **r_smtype)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  rfc822parse_t msg;
+  const char *header_lines, *s;
+  rfc822parse_field_t ctx;
+  size_t length;
+  char *retstr = NULL;
+  
+  if (r_protocol)
+    *r_protocol = NULL;
+  if (r_smtype)
+    *r_smtype = NULL;
+
+  hr = HrGetOneProp ((LPMAPIPROP)message,
+                     PR_TRANSPORT_MESSAGE_HEADERS_A, &propval);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: error getting the headers lines: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      return NULL; 
+    }
+  if (PROP_TYPE (propval->ulPropTag) != PT_STRING8)
+    {
+      /* As per rfc822, header lines must be plain ascii, so no need
+         to cope withy unicode etc. */
+      log_error ("%s:%s: proptag=%#lx not supported\n",
+                 SRCNAME, __func__, propval->ulPropTag);
+      MAPIFreeBuffer (propval);
+      return NULL;
+    }
+  header_lines = propval->Value.lpszA;
+
+  /* Read the headers into an rfc822 object. */
+  msg = rfc822parse_open (get_message_content_type_cb, NULL);
+  if (!msg)
+    {
+      log_error ("%s:%s: rfc822parse_open failed\n", SRCNAME, __func__);
+      MAPIFreeBuffer (propval);
+      return NULL;
+    }
+  
+  while ((s = strchr (header_lines, '\n')))
+    {
+      length = (s - header_lines);
+      if (length && s[-1] == '\r')
+        length--;
+      rfc822parse_insert (msg, (const unsigned char*)header_lines, length);
+      header_lines = s+1;
+    }
+  
+  /* Parse the content-type field. */
+  ctx = rfc822parse_parse_field (msg, "Content-Type", -1);
+  if (ctx)
+    {
+      const char *s1, *s2;
+      s1 = rfc822parse_query_media_type (ctx, &s2);
+      if (s1)
+        {
+          retstr = (char*)xmalloc (strlen (s1) + 1 + strlen (s2) + 1);
+          strcpy (stpcpy (stpcpy (retstr, s1), "/"), s2);
+
+          if (r_protocol)
+            {
+              s = rfc822parse_query_parameter (ctx, "protocol", 0);
+              if (s)
+                *r_protocol = xstrdup (s);
+            }
+          if (r_smtype)
+            {
+              s = rfc822parse_query_parameter (ctx, "smime-type", 0);
+              if (s)
+                *r_smtype = xstrdup (s);
+            }
+        }
+      rfc822parse_release_field (ctx);
+    }
+
+  rfc822parse_close (msg);
+  MAPIFreeBuffer (propval);
+  return retstr;
+}
+
+
+/* Helper for mapi_get_gpgol_body_attachment.  */
+static int
+has_gpgol_body_name (LPATTACH obj)
+{
+  HRESULT hr;
+  LPSPropValue propval;
+  int yes = 0;
+
+  hr = HrGetOneProp ((LPMAPIPROP)obj, PR_ATTACH_FILENAME, &propval);
+  if (FAILED(hr))
+    return 0;
+
+  if ( PROP_TYPE (propval->ulPropTag) == PT_UNICODE)
+    {
+      if (!wcscmp (propval->Value.lpszW, L"gpgol000.txt"))
+        yes = 1;
+      else if (!wcscmp (propval->Value.lpszW, L"gpgol000.htm"))
+        yes = 2;
+    }
+  else if ( PROP_TYPE (propval->ulPropTag) == PT_STRING8)
+    {
+      if (!strcmp (propval->Value.lpszA, "gpgol000.txt"))
+        yes = 1;
+      else if (!strcmp (propval->Value.lpszA, "gpgol000.htm"))
+        yes = 2;
+    }
+  MAPIFreeBuffer (propval);
+  return yes;
+}
+
+
+/* Return the content of the body attachment of MESSAGE.  The body
+   attachment is a hidden attachment created by us for later display.
+   If R_NBYTES is not NULL the number of bytes in the returned buffer
+   is stored there.  If R_ISHTML is not NULL a flag indicating whether
+   the HTML is html formatted is stored there.  If R_PROTECTED is not
+   NULL a flag indicating whethernthe message was protected is store
+   there.  If no body attachment can be found or on any other error
+   NULL is returned.  Caller must free the returned string. */
+char *
+mapi_get_gpgol_body_attachment (LPMESSAGE message, size_t *r_nbytes, 
+                                int *r_ishtml, int *r_protected)
+{    
+  HRESULT hr;
+  SizedSPropTagArray (1L, propAttNum) = { 1L, {PR_ATTACH_NUM} };
+  LPMAPITABLE mapitable;
+  LPSRowSet   mapirows;
+  unsigned int pos, n_attach;
+  ULONG moss_tag;
+  char *body = NULL;
+  int bodytype;
+
+  if (r_ishtml)
+    *r_ishtml = 0;
+  if (r_protected)
+    *r_protected = 0;
+
+  if (get_gpgolattachtype_tag (message, &moss_tag) )
+    return NULL;
+
+  hr = message->GetAttachmentTable (0, &mapitable);
+  if (FAILED (hr))
+    {
+      log_debug ("%s:%s: GetAttachmentTable failed: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      return NULL;
+    }
+      
+  hr = HrQueryAllRows (mapitable, (LPSPropTagArray)&propAttNum,
+                       NULL, NULL, 0, &mapirows);
+  if (FAILED (hr))
+    {
+      log_debug ("%s:%s: HrQueryAllRows failed: hr=%#lx",
+                 SRCNAME, __func__, hr);
+      mapitable->Release ();
+      return NULL;
+    }
+  n_attach = mapirows->cRows > 0? mapirows->cRows : 0;
+  if (!n_attach)
+    {
+      FreeProws (mapirows);
+      mapitable->Release ();
+      log_debug ("%s:%s: No attachments at all", SRCNAME, __func__);
+      return NULL;
+    }
+
+  for (pos=0; pos < n_attach; pos++) 
+    {
+      LPATTACH att;
+
+      hr = message->OpenAttach (pos, NULL, MAPI_BEST_ACCESS, &att);    
+      if (FAILED (hr))
+        {
+          log_error ("%s:%s: can't open attachment %d: hr=%#lx",
+                     SRCNAME, __func__, pos, hr);
+          continue;
+        }
+      if ( (bodytype=has_gpgol_body_name (att))
+           && get_gpgolattachtype (att, moss_tag) == ATTACHTYPE_FROMMOSS)
+        {
+          if (get_attach_method (att) == ATTACH_BY_VALUE)
+            body = attach_to_buffer (att, r_nbytes, 1, r_protected);
+          att->Release ();
+          if (r_ishtml)
+            *r_ishtml = (bodytype == 2);
+          break;
+        }
+      att->Release ();
+    }
+  FreeProws (mapirows);
+  mapitable->Release ();
+  if (!body)
+    log_error ("%s:%s: no suitable body attachment found", SRCNAME, __func__);
+  
+  return body;
+}
 
 
index 25ba9ab..a9444c5 100644 (file)
 #ifndef MAPIHELP_H
 #define MAPIHELP_H
 
-/* The list of message classes we support.  */
+#ifdef __cplusplus
+extern "C" {
+#if 0
+}
+#endif
+#endif
+
+/* The list of message types we support in GpgOL.  */
 typedef enum 
   {
-    MSGCLS_UNKNOWN = 0,
-    MSGCLS_GPGSM,
-    MSGCLS_GPGSM_MULTIPART_SIGNED
+    MSGTYPE_UNKNOWN = 0,
+    MSGTYPE_GPGOL,
+    MSGTYPE_GPGOL_MULTIPART_SIGNED,
+    MSGTYPE_GPGOL_MULTIPART_ENCRYPTED,
+    MSGTYPE_GPGOL_OPAQUE_SIGNED,
+    MSGTYPE_GPGOL_OPAQUE_ENCRYPTED
+  }
+msgtype_t;
+
+typedef enum
+  {
+    ATTACHTYPE_UNKNOWN = 0,
+    ATTACHTYPE_MOSS = 1,     /* The original MOSS message (ie. a
+                                S/MIME or PGP/MIME message. */
+    ATTACHTYPE_FROMMOSS = 2  /* Attachment created from MOSS.  */
   }
-msgclass_t;
+attachtype_t;
+
+/* An object to collect information about one MAPI attachment.  */
+struct mapi_attach_item_s
+{
+  int end_of_table;     /* True if this is the last plus one entry of
+                           the table. */
+  int mapipos;          /* The position which needs to be passed to
+                           MAPI to open the attachment.  -1 means that
+                           there is no valid atatchment.  */
+   
+  int method;           /* MAPI attachment method. */
+  char *filename;       /* Malloced filename of this attachment or NULL. */
+
+  /* Malloced string with the MIME attrib or NULL.  Parameters are
+     stripped off thus a compare against "type/subtype" is
+     sufficient. */
+  char *content_type; 
+
+  /* If not NULL the parameters of the content_type. */
+  const char *content_type_parms; 
+
+  /* The attachment type from Property GpgOL Atatch Type.  */
+  attachtype_t attach_type;
+
+};
+typedef struct mapi_attach_item_s mapi_attach_item_t;
+
 
 
 void log_mapi_property (LPMESSAGE message, ULONG prop, const char *propname);
+int get_gpgolattachtype_tag (LPMESSAGE message, ULONG *r_tag);
+int get_gpgolsigstatus_tag (LPMESSAGE message, ULONG *r_tag);
+int get_gpgolprotectiv_tag (LPMESSAGE message, ULONG *r_tag);
+
 int mapi_change_message_class (LPMESSAGE message);
-msgclass_t mapi_get_message_class (LPMESSAGE message);
+msgtype_t mapi_get_message_type (LPMESSAGE message);
 int mapi_to_mime (LPMESSAGE message, const char *filename);
 
+char *mapi_get_binary_prop (LPMESSAGE message,ULONG proptype,size_t *r_nbytes);
+
+mapi_attach_item_t *mapi_create_attach_table (LPMESSAGE message, int fast);
+void mapi_release_attach_table (mapi_attach_item_t *table);
+LPSTREAM mapi_get_attach_as_stream (LPMESSAGE message, 
+                                    mapi_attach_item_t *item);
+char *mapi_get_attach (LPMESSAGE message, 
+                       mapi_attach_item_t *item, size_t *r_nbytes);
+int mapi_mark_moss_attach (LPMESSAGE message, mapi_attach_item_t *item);
+int mapi_has_sig_status (LPMESSAGE msg);
+int mapi_set_sig_status (LPMESSAGE message, const char *status_string);
+
+char *mapi_get_message_content_type (LPMESSAGE message, 
+                                     char **r_protocol, char **r_smtype);
+
+char *mapi_get_gpgol_body_attachment (LPMESSAGE message, size_t *r_nbytes,
+                                      int *r_ishtml, int *r_protected);
 
 
+#ifdef __cplusplus
+}
+#endif
 #endif /*MAPIHELP_H*/
index 062382f..ec29bdc 100644 (file)
 #include <config.h>
 #endif
 #include <windows.h>
+#include <time.h>  /* FIXME; just for testing.  */
 
 #include "mymapi.h"
 #include "mymapitags.h"
 #include "myexchext.h"
 #include "display.h"
-#include "intern.h"
+#include "common.h"
 #include "gpgmsg.hh"
 #include "msgcache.h"
-#include "engine.h"
 #include "mapihelp.h"
 
 #include "olflange-ids.h"
 #include "olflange-def.h"
 #include "olflange.h"
 #include "ol-ext-callback.h"
+#include "mimeparser.h"
+#include "message.h"
 #include "message-events.h"
 
 
@@ -104,28 +106,52 @@ GpgolMessageEvents::QueryInterface (REFIID riid, LPVOID FAR *ppvObj)
 STDMETHODIMP 
 GpgolMessageEvents::OnRead (LPEXCHEXTCALLBACK pEECB) 
 {
-  LPMDB pMDB = NULL;
-  LPMESSAGE pMessage = NULL;
-  msgclass_t msgcls;
+  LPMDB mdb = NULL;
+  LPMESSAGE message = NULL;
   
   log_debug ("%s:%s: received\n", SRCNAME, __func__);
-  pEECB->GetObject (&pMDB, (LPMAPIPROP *)&pMessage);
-  log_mapi_property (pMessage, PR_CONVERSATION_INDEX,"PR_CONVERSATION_INDEX");
-  msgcls = mapi_get_message_class (pMessage);
-  switch (msgcls)
+  pEECB->GetObject (&mdb, (LPMAPIPROP *)&message);
+  log_mapi_property (message, PR_CONVERSATION_INDEX,"PR_CONVERSATION_INDEX");
+  switch (m_pExchExt->getMsgtype (pEECB))
     {
-    case MSGCLS_UNKNOWN: 
+    case MSGTYPE_UNKNOWN: 
+      break;
+    case MSGTYPE_GPGOL:
+      log_debug ("%s:%s: ignoring unknown message of original SMIME class\n",
+                 SRCNAME, __func__);
       break;
-    case MSGCLS_GPGSM:
-    case MSGCLS_GPGSM_MULTIPART_SIGNED:
-      log_debug ("%s:%s: need to handle msgcls %d\n", 
-                 SRCNAME, __func__, msgcls);
+    case MSGTYPE_GPGOL_MULTIPART_SIGNED:
+      log_debug ("%s:%s: processing multipart signed message\n", 
+                 SRCNAME, __func__);
       m_is_smime = TRUE;
+      message_verify (message, m_pExchExt->getMsgtype (pEECB), 0);
+      break;
+    case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED:
+      log_debug ("%s:%s: processing multipart encrypted message\n",
+                 SRCNAME, __func__);
+      m_is_smime = TRUE;
+      message_decrypt (message, m_pExchExt->getMsgtype (pEECB), 0);
+      /* Hmmm, we might want to abort it and run our own inspector
+         instead.  */
+      break;
+    case MSGTYPE_GPGOL_OPAQUE_SIGNED:
+      log_debug ("%s:%s: processing opaque signed message\n", 
+                 SRCNAME, __func__);
+      m_is_smime = TRUE;
+      message_verify (message, m_pExchExt->getMsgtype (pEECB), 0);
+      break;
+    case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED:
+      log_debug ("%s:%s: processing opaque encrypted message\n",
+                 SRCNAME, __func__);
+      m_is_smime = TRUE;
+      message_decrypt (message, m_pExchExt->getMsgtype (pEECB), 0);
+      /* Hmmm, we might want to abort it and run our own inspector
+         instead.  */
       break;
     }
   
-  ul_release (pMessage);
-  ul_release (pMDB);
+  ul_release (message);
+  ul_release (mdb);
 
   return S_FALSE;
 }
@@ -139,21 +165,22 @@ GpgolMessageEvents::OnReadComplete (LPEXCHEXTCALLBACK pEECB, ULONG lFlags)
 {
   log_debug ("%s:%s: received\n", SRCNAME, __func__);
 
+
   /* The preview_info stuff does not work because for some reasons we
      can't update the window.  Thus disabled for now. */
   if (!m_is_smime && opt.preview_decrypt /*|| !opt.compat.no_preview_info*/)
     {
       HRESULT hr;
       HWND hWnd = NULL;
-      LPMESSAGE pMessage = NULL;
-      LPMDB pMDB = NULL;
+      LPMESSAGE message = NULL;
+      LPMDB mdb = NULL;
 
       if (FAILED (pEECB->GetWindow (&hWnd)))
         hWnd = NULL;
-      hr = pEECB->GetObject (&pMDB, (LPMAPIPROP *)&pMessage);
+      hr = pEECB->GetObject (&mdb, (LPMAPIPROP *)&message);
       if (SUCCEEDED (hr))
         {
-          GpgMsg *m = CreateGpgMsg (pMessage);
+          GpgMsg *m = CreateGpgMsg (message);
           m->setExchangeCallback ((void*)pEECB);
           m->setPreview (1);
           /* If preview decryption has been requested, do so.  If not,
@@ -162,12 +189,37 @@ GpgolMessageEvents::OnReadComplete (LPEXCHEXTCALLBACK pEECB, ULONG lFlags)
           m->decrypt (hWnd, !opt.preview_decrypt);
           delete m;
        }
-      ul_release (pMessage);
-      ul_release (pMDB);
+      ul_release (message);
+      ul_release (mdb);
     }
+  else if (m_is_smime)
+    {
+      HRESULT hr;
+      HWND hwnd = NULL;
+      LPMESSAGE message = NULL;
+      LPMDB mdb = NULL;
 
+      if (FAILED (pEECB->GetWindow (&hwnd)))
+        hwnd = NULL;
+      hr = pEECB->GetObject (&mdb, (LPMAPIPROP *)&message);
+      if (SUCCEEDED (hr))
+        {
+          int ishtml, wasprotected;
+          char *body;
+
+          /* If the message was protected we don't allow a fallback to
+             the OOM display methods.  FIXME:  This is currently disabled. */
+          body = mapi_get_gpgol_body_attachment (message, NULL,
+                                                 &ishtml, &wasprotected);
+          if (body)
+            update_display (hwnd, /*wasprotected?NULL:*/pEECB, ishtml, body);
+        }
+      ul_release (message);
+      ul_release (mdb);
+    }
+  
 
-#if 0
+#if 1
     {
       HWND hWnd = NULL;
 
index 06b583b..1402e36 100644 (file)
@@ -70,9 +70,9 @@ class GpgolMessageEvents : public IExchExtMessageEvents
   STDMETHODIMP_ (VOID)OnSubmitComplete (LPEXCHEXTCALLBACK pEECB, ULONG lFlags);
 
   inline void SetContext (ULONG lContext)
-  { 
-    m_lContext = lContext;
-  };
+    
+      m_lContext = lContext;
+    };
 };
 
 
index a4ef16e..457d060 100644 (file)
@@ -8,6 +8,7 @@
  * 2005-08-12  Initial version.
  * 2005-09-18  Add IExchExtAttachedFileEvents.
  * 2007-07-18  Add IExchExtUserEvents and IExchExtSessionEvents.
+ * 2007-07-20  Add IOutlookExtItemEvents.
  */
 
 #ifndef EXCHEXT_H
@@ -97,6 +98,7 @@ DEFINE_OLEGUID(IID_IExchExtAdvancedCriteria,  0x00020d18, 0, 0);
 DEFINE_OLEGUID(IID_IExchExtModeless,          0x00020d19, 0, 0);
 DEFINE_OLEGUID(IID_IExchExtModelessCallback,  0x00020d1a, 0, 0);
 DEFINE_OLEGUID(IID_IOutlookExtCallback,       0x0006720d, 0, 0);
+DEFINE_OLEGUID(IID_IOutlookExtItemEvents,     0x0006723A, 0, 0);
 
 
 /* Type definitions. */
@@ -140,11 +142,15 @@ typedef IExchExtPropertySheets *LPEXCHEXTPROPERTYSHEETS;
 typedef struct IExchExtCallback IExchExtCallback;
 typedef IExchExtCallback *LPEXCHEXTCALLBACK;
 
+typedef struct IExchExtAttachedFileEvents IExchExtAttachedFileEvents;
+typedef IExchExtAttachedFileEvents *LPEXCHEXTATTACHEDFILEEVENTS;
+
 typedef struct IOutlookExtCallback IOutlookExtCallback;
 typedef IOutlookExtCallback *LPOUTLOOKEXTCALLBACK;
 
-typedef struct IExchExtAttachedFileEvents IExchExtAttachedFileEvents;
-typedef IExchExtAttachedFileEvents *LPEXCHEXTATTACHEDFILEEVENTS;
+typedef struct IOutlookExtItemEvents IOutlookExtItemEvents;
+typedef IOutlookExtItemEvents *LPOUTLOOKEXTITEMEVENTS;
+
 
 /* The next classes are not yet defined. but if so they should go here. */
 typedef struct IExchExtModeless IExchExtModeless; 
@@ -364,6 +370,28 @@ DECLARE_INTERFACE_(IExchExtCallback, IUnknown)
 
 
 
+EXTERN_C const IID IID_IExchExtAttachedFileEvents;
+#undef INTERFACE
+#define INTERFACE  IExchExtAttachedFileEvents
+DECLARE_INTERFACE_(IExchExtAttachedFileEvents, IUnknown)
+{
+  /*** IUnknown methods ***/
+  STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * lppvObj) PURE;
+  STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+  STDMETHOD_(ULONG,Release) (THIS) PURE;
+  
+  /*** IExchExtAttachedFileEvents methods ***/
+  STDMETHOD(OnReadPattFromSzFile)(THIS_ LPATTACH lpatt, LPTSTR lpszFile,
+                                 ULONG ulFlags) PURE;
+  STDMETHOD(OnWritePattToSzFile)(THIS_ LPATTACH lpatt, LPTSTR lpszFile,
+                                ULONG ulFlags) PURE;
+  STDMETHOD(QueryDisallowOpenPatt)(THIS_ LPATTACH lpatt) PURE;
+  STDMETHOD(OnOpenPatt)(THIS_ LPATTACH lpatt) PURE;
+  STDMETHOD(OnOpenSzFile)(THIS_ LPTSTR lpszFile, ULONG ulFlags) PURE;
+};
+
+
+
 EXTERN_C const IID IID_IOutlookExtCallback;
 #undef INTERFACE
 #define INTERFACE IOutlookExtCallback
@@ -381,24 +409,21 @@ DECLARE_INTERFACE_(IOutlookExtCallback, IUnknown)
 
 
 
-EXTERN_C const IID IID_IExchExtAttachedFileEvents;
+EXTERN_C const IID IID_IOutlookExtItemEvents;
 #undef INTERFACE
-#define INTERFACE  IExchExtAttachedFileEvents
-DECLARE_INTERFACE_(IExchExtAttachedFileEvents, IUnknown)
+#define INTERFACE  IOutlookExtItemEvents
+DECLARE_INTERFACE_(IOutlookExtItemEvents, IUnknown)
 {
   /*** IUnknown methods ***/
   STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * lppvObj) PURE;
   STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
   STDMETHOD_(ULONG,Release) (THIS) PURE;
-  
-  /*** IExchExtAttachedFileEvents methods ***/
-  STDMETHOD(OnReadPattFromSzFile)(THIS_ LPATTACH lpatt, LPTSTR lpszFile,
-                                 ULONG ulFlags) PURE;
-  STDMETHOD(OnWritePattToSzFile)(THIS_ LPATTACH lpatt, LPTSTR lpszFile,
-                                ULONG ulFlags) PURE;
-  STDMETHOD(QueryDisallowOpenPatt)(THIS_ LPATTACH lpatt) PURE;
-  STDMETHOD(OnOpenPatt)(THIS_ LPATTACH lpatt) PURE;
-  STDMETHOD(OnOpenSzFile)(THIS_ LPTSTR lpszFile, ULONG ulFlags) PURE;
+
+  /*** IOutlookExtItemEvents ***/
+  STDMETHOD(OnOpen)(THIS_ LPEXCHEXTCALLBACK) PURE;
+  STDMETHOD(OnOpenComplete)(THIS_ LPEXCHEXTCALLBACK, ULONG) PURE;
+  STDMETHOD(OnClose)(THIS_ LPEXCHEXTCALLBACK, ULONG) PURE;
+  STDMETHOD(OnCloseComplete)(THIS_ LPEXCHEXTCALLBACK, ULONG) PURE;
 };
 
 
index 17e9efc..3a5bb95 100644 (file)
@@ -1,4 +1,4 @@
-/* mymapi.h - MAPI definitions required for GPGol and Mingw32
+/* mymapi.h - MAPI definitions required for GpgOL and Mingw32
  * Copyright (C) 1998 Justin Bradford
  * Copyright (C) 2000 François Gouget
  * Copyright (C) 2005, 2007 g10 Code GmbH
    2007-07-19  Add IConverterSession.  Info taken from
                  http://blogs.msdn.com/stephen_griffin/archive/2007/06/22/
                  iconvertersession-do-you-converter-session.aspx
+   2007-07-23  More IConverterSession features.
+   2007-07-23  Add IMAPISession; taken from WINE.
+   2007-07-24  Add IMsgStore, IMAPIContainer and IMAPIFolder taken from specs.
+               Reorganized code.
 */
 
 #ifndef MAPI_H
@@ -49,6 +53,13 @@ typedef unsigned long           LHANDLE, *LPLHANDLE;
 
 typedef unsigned long           FLAGS;
 
+
+typedef struct _MAPIUID
+{
+    BYTE ab[sizeof(GUID)];
+} MAPIUID, *LPMAPIUID;
+
+
 struct MapiFileDesc_s
 {
   ULONG ulReserved;
@@ -113,7 +124,7 @@ typedef struct MapiMessage_s *lpMapiMessage;
 
 /* Flags for various calls */
 #define MAPI_MODIFY                   0x00000001U /* Object can be modified. */
-#define MAPI_CREATE                   0x00000002U 
+#define MAPI_CREATE                   0x00000002U
 #define MAPI_ACCESS_MODIFY            MAPI_MODIFY /* Want write access. */
 #define MAPI_ACCESS_READ              0x00000002U /* Want read access. */
 #define MAPI_ACCESS_DELETE            0x00000004U /* Want delete access. */
@@ -123,21 +134,27 @@ typedef struct MapiMessage_s *lpMapiMessage;
 #define MAPI_UNICODE                  0x80000000U /* Strings in this
                                                      call are Unicode. */
 
-#define MAPI_BEST_ACCESS              0x00000010U
+#define MAPI_DEFERRED_ERRORS          0x00000008ul
+#define MAPI_BEST_ACCESS              0x00000010ul
+
 
+#define MDB_NO_DIALOG                 0x00000001ul
+#define MDB_WRITE                     0x00000004ul
+#define MDB_TEMPORARY                 0x00000020ul
+#define MDB_NO_MAIL                   0x00000080ul
 
-#define ATTACH_BY_VALUE       1 
-#define ATTACH_BY_REFERENCE   2 
-#define ATTACH_BY_REF_RESOLVE 3 
-#define ATTACH_BY_REF_ONLY    4 
+
+#define ATTACH_BY_VALUE       1
+#define ATTACH_BY_REFERENCE   2
+#define ATTACH_BY_REF_RESOLVE 3
+#define ATTACH_BY_REF_ONLY    4
 #define ATTACH_EMBEDDED_MSG   5
-#define ATTACH_OLE            6  
+#define ATTACH_OLE            6
 
 
 #define KEEP_OPEN_READONLY            0x00000001
 #define KEEP_OPEN_READWRITE           0x00000002
 #define FORCE_SAVE                    0x00000004
-#define MAPI_DEFERRED_ERRORS          0x00000008
 
 #define SOF_UNIQUEFILENAME            0x80000000
 
@@ -145,6 +162,29 @@ typedef struct MapiMessage_s *lpMapiMessage;
 #define RTF_SYNC_BODY_CHANGED         2
 
 
+#define FORCE_SUBMIT                  0x00000001ul
+                                      
+#define MSGFLAG_READ                  0x00000001ul
+#define MSGFLAG_UNMODIFIED            0x00000002ul
+#define MSGFLAG_SUBMIT                0x00000004ul
+#define MSGFLAG_UNSENT                0x00000008ul
+#define MSGFLAG_HASATTACH             0x00000010ul
+#define MSGFLAG_FROMME                0x00000020ul
+#define MSGFLAG_ASSOCIATED            0x00000040ul
+#define MSGFLAG_RESEND                0x00000080ul
+#define MSGFLAG_RN_PENDING            0x00000100ul
+#define MSGFLAG_NRN_PENDING           0x00000200ul
+                                      
+#define SUBMITFLAG_LOCKED             0x00000001ul
+#define SUBMITFLAG_PREPROCESS         0x00000002ul
+
+#define HOOK_DELETE                   0x00000001ul
+#define HOOK_CANCEL                   0x00000002ul
+
+#define HOOK_INBOUND                  0x00000200ul
+#define HOOK_OUTBOUND                 0x00000400ul
+
+
 #ifndef MAPI_DIM
 # define MAPI_DIM 1 /* Default to one dimension for variable length arrays */
 #endif
@@ -208,7 +248,7 @@ DEFINE_OLEGUID(PS_ROUTING_ENTRYID,0x20383,0,0);
 DEFINE_OLEGUID(PS_ROUTING_SEARCH_KEY,0x20384,0,0);
 
 DEFINE_GUID(CLSID_IConverterSession, 0x4e3a7680, 0xb77a,
-            0x11d0, 0x9d, 0xa5, 0x0, 0xc0, 0x4f, 0xd6, 0x56, 0x85); 
+            0x11d0, 0x9d, 0xa5, 0x0, 0xc0, 0x4f, 0xd6, 0x56, 0x85);
 DEFINE_GUID(IID_IConverterSession, 0x4b401570, 0xb77b,
             0x11d0, 0x9d, 0xa5, 0x0, 0xc0, 0x4f, 0xd6, 0x56, 0x85);
 
@@ -490,39 +530,88 @@ typedef struct _ADRLIST
 } ADRLIST, *LPADRLIST;
 
 
+struct IAddrBook;
+typedef struct IAddrBook *LPADRBOOK;
+
+
+/* FIXME: Need to move the HCHARSET definition to some other place.  */
+typedef void *HCHARSET;
+
+
+typedef enum tagCHARSETTYPE
+  {
+    CHARSET_BODY = 0,
+    CHARSET_HEADER = 1,
+    CHARSET_WEB = 2
+  }
+CHARSETTYPE;
+
+typedef enum tagCSETAPPLYTYPE
+  {
+    CSET_APPLY_UNTAGGED = 0,
+    CSET_APPLY_ALL = 1,
+    CSET_APPLY_TAG_ALL = 2
+  }
+CSETAPPLYTYPE;
+
+
+/* Note that this is just a minimal definition.  */
+typedef struct
+{
+  ULONG ulEventType;  /* Notification type.  */
+  ULONG ulAlignPad;   /* Force alignment on a 8 byte.  */
+  union {
+    struct {
+      ULONG           n_entryid;
+      LPENTRYID       entryid;
+      ULONG           obj_type;
+      ULONG           n_parentid;
+      LPENTRYID       parentid;
+      ULONG           n_oldid;
+      LPENTRYID       oldid;
+      ULONG           n_oldparentid;
+      LPENTRYID       oldparentid;
+      LPSPropTagArray prop_tag_array;
+    } obj;
+  } info;
+} NOTIFICATION, FAR *LPNOTIFICATION;
+
 
 /* Definitions required for IConverterSession. */
 typedef enum tagMIMESAVETYPE
-  {    
-    SAVE_RFC822        = 0,
-    SAVE_RFC1521 = 1
-  } 
+  {
+    SAVE_RFC822 = 0,    /* Use uuencode for attachments.  */
+    SAVE_RFC1521 = 1    /* Regular MIME.  */
+  }
 MIMESAVETYPE;
 
 typedef enum tagENCODINGTYPE
   {
-    IET_BINARY  = 0,
-    IET_BASE64  = 1,
+    IET_BINARY   = 0,
+    IET_BASE64   = 1,
     IET_UUENCODE = 2,
-    IET_QP      = 3,
-    IET_7BIT    = 4,
-    IET_8BIT    = 5,
+    IET_QP       = 3,
+    IET_7BIT     = 4,
+    IET_8BIT     = 5,
     IET_INETCSET = 6,
-    IET_UNICODE         = 7,
-    IET_RFC1522         = 8,
-    IET_ENCODED         = 9,
-    IET_CURRENT         = 10,
-    IET_UNKNOWN         = 11,
+    IET_UNICODE  = 7,
+    IET_RFC1522  = 8,
+    IET_ENCODED  = 9,
+    IET_CURRENT  = 10,
+    IET_UNKNOWN  = 11,
     IET_BINHEX40 = 12,
-    IET_LAST    = 13
+    IET_LAST     = 13
   }
 ENCODINGTYPE;
 
-#define CCSF_SMTP        0x0002
-#define CCSF_NOHEADERS   0x0004
-#define CCSF_INCLUDE_BCC  0x0020
-#define CCSF_USE_RTF     0x0080
-#define CCSF_NO_MSGID    0x4000
+#define CCSF_SMTP            0x0002 /* The input is an SMTP message.  */
+#define CCSF_NOHEADERS       0x0004 /* Ignore headers outside the message.  */
+#define CCSF_USE_TNEF        0x0010 /* Embed TNEF in MIME.  */
+#define CCSF_INCLUDE_BCC     0x0020 /* Include BCC recipients.  */
+#define CCSF_8BITHEADERS     0x0040 /* Allow 8-bit headers. (mapi->mime) */
+#define CCSF_USE_RTF         0x0080 /* Convert HTML to RTF.  */
+#define CCSF_PLAIN_TEXT_ONLY 0x1000 /* Create only plain text (mapi->mime) */
+#define CCSF_NO_MSGID        0x4000 /* Do not include Message-Id.  */
 
 
 \f
@@ -548,45 +637,252 @@ typedef struct IMAPIProp *LPMAPIPROP;
 struct IMessage;
 typedef struct IMessage *LPMESSAGE;
 
+struct IMAPIContainer;
+typedef struct IMAPIContainer *LPMAPICONTAINER;
+
+struct IMAPIFolder;
+typedef struct IMAPIFolder *LPMAPIFOLDER;
+
 struct IMsgStore;
 typedef struct IMsgStore *LPMDB;
 
+struct IMAPISession;
+typedef struct IMAPISession *LPMAPISESSION;
+
+struct IMsgServiceAdmin;
+typedef struct IMsgServiceAdmin *LPSERVICEADMIN;
+
 struct IConverterSession;
 typedef struct IConverterSession *LPCONVERTERSESSION;
 
+struct IProfSect;
+typedef struct IProfSect *LPPROFSECT;
+
+struct ISpoolerHook;
+typedef struct ISpoolerHook *LPSPOOLERHOOK;
+
+
+/*** IUnknown methods ***/
+#define MY_IUNKNOWN_METHODS \
+  STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID*) PURE; \
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;                  \
+  STDMETHOD_(ULONG,Release)(THIS) PURE
+
+/*** IMAPIProp methods ***/
+#define MY_IMAPIPROP_METHODS \
+  STDMETHOD(GetLastError)(THIS_ HRESULT, ULONG, LPMAPIERROR FAR*);         \
+  STDMETHOD(SaveChanges)(THIS_ ULONG);                                     \
+  STDMETHOD(GetProps)(THIS_ LPSPropTagArray, ULONG, ULONG FAR*,            \
+                      LPSPropValue FAR*);                                  \
+  STDMETHOD(GetPropList)(THIS_ ULONG, LPSPropTagArray FAR *);              \
+  STDMETHOD(OpenProperty)(THIS_ ULONG, LPCIID lpiid, ULONG,                \
+                          ULONG, LPUNKNOWN FAR*);                          \
+  STDMETHOD(SetProps)(THIS_ LONG, LPSPropValue, LPSPropProblemArray FAR*); \
+  STDMETHOD(DeleteProps)(THIS_ LPSPropTagArray, LPSPropProblemArray FAR *);\
+  STDMETHOD(CopyTo)(THIS_ ULONG, LPCIID, LPSPropTagArray, ULONG,           \
+                    LPMAPIPROGRESS, LPCIID lpInterface, LPVOID,            \
+                    ULONG, LPSPropProblemArray FAR*);                      \
+  STDMETHOD(CopyProps)(THIS_ LPSPropTagArray, ULONG, LPMAPIPROGRESS,       \
+                       LPCIID, LPVOID, ULONG, LPSPropProblemArray FAR*);   \
+  STDMETHOD(GetNamesFromIDs)(THIS_ LPSPropTagArray FAR*, LPGUID,           \
+                             ULONG, ULONG FAR*, LPMAPINAMEID FAR* FAR*);   \
+  STDMETHOD(GetIDsFromNames)(THIS_ ULONG, LPMAPINAMEID FAR*, ULONG,        \
+                             LPSPropTagArray FAR*)
+
+/*** IMsgstore methods ***/
+#define MY_IMSGSTORE_METHODS \
+  STDMETHOD(Advise)(THIS_ ULONG n_entryid, LPENTRYID entryid,                \
+                    ULONG ulEventMask, LPMAPIADVISESINK lpAdviseSink,        \
+                    ULONG FAR *connection) PURE;                             \
+  STDMETHOD(Unadvise)(THIS_ ULONG connection) PURE;                          \
+  STDMETHOD(CompareEntryIDs)(THIS_  ULONG n_entryid1, LPENTRYID entryid1,    \
+                             ULONG n_entryid2, LPENTRYID entryid2,           \
+                             ULONG flags, ULONG FAR *lpulResult) PURE;       \
+  STDMETHOD(OpenEntry)(THIS_ ULONG n_entryid, LPENTRYID entryid,             \
+                       LPCIID lpInterface, ULONG flags,                      \
+                       ULONG FAR *obj_type, LPUNKNOWN FAR *lppUnk) PURE;     \
+  STDMETHOD(SetReceiveFolder)(THIS_ LPTSTR message_class, ULONG flags,       \
+                              ULONG n_entryid, LPENTRYID entryid) PURE;      \
+  STDMETHOD(GetReceiveFolder)(THIS_ LPTSTR message_class, ULONG flags,       \
+                              ULONG FAR *r_nentryid,LPENTRYID FAR *r_entryid,\
+                              LPTSTR FAR *lppszExplicitClass) PURE;          \
+  STDMETHOD(GetReceiveFolderTable)(THIS_ ULONG flags,                        \
+                                   LPMAPITABLE FAR *lppTable) PURE;          \
+  STDMETHOD(StoreLogoff)(THIS_ ULONG FAR *r_flags) PURE;                     \
+  STDMETHOD(AbortSubmit)(THIS_ ULONG nentryid, LPENTRYID entryid,            \
+                         ULONG flags) PURE;                                  \
+  STDMETHOD(GetOutgoingQueue)(THIS_ ULONG flags,LPMAPITABLE FAR *table) PURE;\
+  STDMETHOD(SetLockState)(THIS_ LPMESSAGE message, ULONG lock_state) PURE;   \
+  STDMETHOD(FinishedMsg)(THIS_ ULONG ulFlags,                                \
+                         ULONG nentryid, LPENTRYID entryid) PURE;            \
+  STDMETHOD(NotifyNewMail)(THIS_ LPNOTIFICATION notification) PURE
+
+
+/*** IMessage methods ***/
+#define MY_IMESSAGE_METHODS \
+  STDMETHOD(GetAttachmentTable)(THIS_ ULONG, LPMAPITABLE FAR*) PURE;         \
+  STDMETHOD(OpenAttach)(THIS_ ULONG, LPCIID, ULONG, LPATTACH FAR*) PURE;     \
+  STDMETHOD(CreateAttach)(THIS_ LPCIID, ULONG, ULONG FAR*,                   \
+                          LPATTACH FAR*) PURE;                               \
+  STDMETHOD(DeleteAttach)(THIS_ ULONG, ULONG, LPMAPIPROGRESS, ULONG) PURE;   \
+  STDMETHOD(GetRecipientTable)(THIS_ ULONG, LPMAPITABLE FAR*) PURE;          \
+  STDMETHOD(ModifyRecipients)(THIS_ ULONG, LPADRLIST) PURE;                  \
+  STDMETHOD(SubmitMessage)(THIS_ ULONG) PURE;                                \
+  STDMETHOD(SetReadFlag)(THIS_ ULONG) PURE
+
+/*** IMAPIContainer ***/
+#define MY_IMAPICONTAINER_METHODS \
+  STDMETHOD(GetContentsTable)(THIS_ ULONG flags,                             \
+                              LPMAPITABLE FAR *table) PURE;                  \
+  STDMETHOD(GetHierarchyTable)(THIS_ ULONG flags,                            \
+                               LPMAPITABLE FAR *table) PURE;                 \
+  STDMETHOD(OpenEntry)(THIS_ ULONG n_entryid, LPENTRYID entryid,             \
+                       LPCIID iface, ULONG flags,                            \
+                       ULONG FAR *obj_type, LPUNKNOWN FAR *lppUnk) PURE;     \
+  STDMETHOD(SetSearchCriteria)(THIS_ LPSRestriction restriction,             \
+                               LPENTRYLIST container_list,                   \
+                               ULONG  search_flags) PURE;                    \
+  STDMETHOD(GetSearchCriteria)(THIS_ ULONG flags,                            \
+                               LPSRestriction FAR *restriction,              \
+                               LPENTRYLIST FAR *container_list,              \
+                               ULONG FAR *search_state) PURE
+
+
+/*** IMAPIFolder methods ***/
+#define MY_IMAPIFOLDER_METHODS \
+  STDMETHOD(CreateMessage)(THIS_ LPCIID iface, ULONG flags,                  \
+                           LPMESSAGE FAR *message) PURE;                     \
+  STDMETHOD(CopyMessages)(THIS_ LPENTRYLIST msg_list, LPCIID iface,          \
+                          LPVOID dest_folder, ULONG ui_param,                \
+                          LPMAPIPROGRESS progress, ULONG flags) PURE;        \
+  STDMETHOD(DeleteMessages)(THIS_ LPENTRYLIST msg_list, ULONG uiparam,       \
+                            LPMAPIPROGRESS progress, ULONG flags) PURE;      \
+  STDMETHOD(CreateFolder)(THIS_ ULONG folder_type, LPTSTR folder_name,       \
+                          LPTSTR folder_comment, LPCIID iface,               \
+                          ULONG flags, LPMAPIFOLDER FAR *folder) PURE;       \
+  STDMETHOD(CopyFolder)(THIS_ ULONG n_entryid, LPENTRYID entryid,            \
+                        LPCIID iface, LPVOID dest_folder,                    \
+                        LPTSTR new_folder_name, ULONG uiparam,               \
+                        LPMAPIPROGRESS progress, ULONG flags) PURE;          \
+  STDMETHOD(DeleteFolder)(THIS_ ULONG n_entryid, LPENTRYID entryid,          \
+                          ULONG uiparam,                                     \
+                          LPMAPIPROGRESS progress, ULONG flags) PURE;        \
+  STDMETHOD(SetReadFlags)(THIS_ LPENTRYLIST msg_list, ULONG uiparam,         \
+                          LPMAPIPROGRESS progress, ULONG flags) PURE;        \
+  STDMETHOD(GetMessageStatus)(THIS_ ULONG n_entryid, LPENTRYID entryid,      \
+                              ULONG flags, ULONG FAR *message_status) PURE;  \
+  STDMETHOD(SetMessageStatus)(THIS_ ULONG n_entryid, LPENTRYID entryid,      \
+                              ULONG new_status, ULONG new_status_mask,       \
+                              ULONG FAR *r_old_status) PURE;                 \
+  STDMETHOD(SaveContentsSort)(THIS_ LPSSortOrderSet sort_criteria,           \
+                              ULONG flags) PURE;                             \
+  STDMETHOD(EmptyFolder)(THIS_ ULONG uiparam,                                \
+                         LPMAPIPROGRESS progress, ULONG flags) PURE
+
+
+/*** IMAPITable methods ***/
+#define MY_IMAPITABLE_METHODS \
+  STDMETHOD(GetLastError)(THIS_ HRESULT, ULONG, LPMAPIERROR*) PURE;          \
+  STDMETHOD(Advise)(THIS_ ULONG, LPMAPIADVISESINK, ULONG*) PURE;             \
+  STDMETHOD(Unadvise)(THIS_ ULONG ulCxn) PURE;                               \
+  STDMETHOD(GetStatus)(THIS_ ULONG*, ULONG*) PURE;                           \
+  STDMETHOD(SetColumns)(THIS_ LPSPropTagArray, ULONG) PURE;                  \
+  STDMETHOD(QueryColumns)(THIS_ ULONG, LPSPropTagArray*) PURE;               \
+  STDMETHOD(GetRowCount)(THIS_ ULONG, ULONG *) PURE;                         \
+  STDMETHOD(SeekRow)(THIS_ BOOKMARK, LONG, LONG*) PURE;                      \
+  STDMETHOD(SeekRowApprox)(THIS_ ULONG, ULONG) PURE;                         \
+  STDMETHOD(QueryPosition)(THIS_ ULONG*, ULONG*, ULONG*) PURE;               \
+  STDMETHOD(FindRow)(THIS_ LPSRestriction, BOOKMARK, ULONG) PURE;            \
+  STDMETHOD(Restrict)(THIS_ LPSRestriction, ULONG) PURE;                     \
+  STDMETHOD(CreateBookmark)(THIS_ BOOKMARK*) PURE;                           \
+  STDMETHOD(FreeBookmark)(THIS_ BOOKMARK) PURE;                              \
+  STDMETHOD(SortTable)(THIS_ LPSSortOrderSet, ULONG) PURE;                   \
+  STDMETHOD(QuerySortOrder)(THIS_ LPSSortOrderSet*) PURE;                    \
+  STDMETHOD(QueryRows)(THIS_ LONG, ULONG, LPSRowSet*) PURE;                  \
+  STDMETHOD(Abort)(THIS) PURE;                                               \
+  STDMETHOD(ExpandRow)(THIS_ ULONG, LPBYTE, ULONG, ULONG,                    \
+                       LPSRowSet*, ULONG*) PURE;                             \
+  STDMETHOD(CollapseRow)(THIS_ ULONG, LPBYTE, ULONG, ULONG*) PURE;           \
+  STDMETHOD(WaitForCompletion)(THIS_ ULONG, ULONG, ULONG*) PURE;             \
+  STDMETHOD(GetCollapseState)(THIS_ ULONG, ULONG,LPBYTE,ULONG*,LPBYTE*) PURE;\
+  STDMETHOD(SetCollapseState)(THIS_ ULONG, ULONG, LPBYTE, BOOKMARK*) PURE
+
+
+
+/*** IMAPISession methods ***/
+#define MY_IMAPISESSION_METHODS \
+  STDMETHOD(GetLastError)(THIS_ HRESULT hResult, ULONG ulFlags,               \
+                          LPMAPIERROR *lppMAPIError) PURE;                    \
+  STDMETHOD(GetMsgStoresTable)(THIS_ ULONG ulFlags,                           \
+                               LPMAPITABLE *lppTable) PURE;                   \
+  STDMETHOD(OpenMsgStore)(THIS_ ULONG_PTR ulUIParam, ULONG cbId,              \
+                          LPENTRYID lpId, LPCIID lpIFace,                     \
+                          ULONG ulFlags, LPMDB *lppMDB) PURE;                 \
+  STDMETHOD(OpenAddressBook)(THIS_ ULONG_PTR ulUIParam, LPCIID iid,           \
+                             ULONG ulFlags, LPADRBOOK *lppAdrBook) PURE;      \
+  STDMETHOD(OpenProfileSection)(THIS_ LPMAPIUID lpUID, LPCIID iid,            \
+                                ULONG ulFlags, LPPROFSECT *lppProf) PURE;     \
+  STDMETHOD(GetStatusTable)(THIS_ ULONG ulFlags, LPMAPITABLE *lppTable) PURE; \
+  STDMETHOD(OpenEntry)(THIS_ ULONG cbId, LPENTRYID lpId, LPCIID iid,          \
+                       ULONG ulFlags, ULONG *lpType, LPUNKNOWN *lppUnk) PURE; \
+  STDMETHOD(CompareEntryIDs)(THIS_ ULONG cbLID, LPENTRYID lpLID, ULONG cbRID, \
+                             LPENTRYID lpRID, ULONG ulFlags,                  \
+                             ULONG *lpRes) PURE;                              \
+  STDMETHOD(Advise)(THIS_ ULONG cbId, LPENTRYID lpId, ULONG ulMask,           \
+                    LPMAPIADVISESINK lpSink, ULONG *lpCxn) PURE;              \
+  STDMETHOD(Unadvise)(THIS_ ULONG ulConnection) PURE;                         \
+  STDMETHOD(MessageOptions)(THIS_ ULONG_PTR ulUIParam, ULONG ulFlags,         \
+                            LPSTR lpszAddr, LPMESSAGE lpMsg) PURE;            \
+  STDMETHOD(QueryDefaultMessageOpt)(THIS_ LPSTR lpszAddr, ULONG ulFlags,      \
+                                    ULONG *lpcVals,                           \
+                                    LPSPropValue *lppOpts) PURE;              \
+  STDMETHOD(EnumAdrTypes)(THIS_ ULONG ulFlags, ULONG *lpcTypes,               \
+                          LPSTR **lpppszTypes) PURE;                          \
+  STDMETHOD(QueryIdentity)(THIS_ ULONG *lpcbId, LPENTRYID *lppEntryID) PURE;  \
+  STDMETHOD(Logoff)(THIS_ ULONG_PTR ulUIParam, ULONG ulFlags,                 \
+                    ULONG ulReserved) PURE;                                   \
+  STDMETHOD(SetDefaultStore)(THIS_ ULONG ulFlags, ULONG cbId,                 \
+                             LPENTRYID lpId) PURE;                            \
+  STDMETHOD(AdminServices)(THIS_ ULONG ulFlags, LPSERVICEADMIN *lppAdmin)PURE;\
+  STDMETHOD(ShowForm)(THIS_ ULONG_PTR ulUIParam, LPMDB lpStore,               \
+                      LPMAPIFOLDER lpParent, LPCIID iid, ULONG ulToken,       \
+                      LPMESSAGE lpSent, ULONG ulFlags, ULONG ulStatus,        \
+                      ULONG ulMsgFlags, ULONG ulAccess, LPSTR lpszClass)PURE; \
+  STDMETHOD(PrepareForm)(THIS_ LPCIID lpIFace, LPMESSAGE lpMsg,               \
+                         ULONG *lpToken) PURE;
+
+
+/*** ISpoolerHook methods ***/
+#define MY_ISPOOLERHOOK_METHODS \
+  STDMETHOD(InboundMsgHook)(THIS_ LPMESSAGE message, LPMAPIFOLDER folder,     \
+                            LPMDB mdb, ULONG FAR *r_flags,                    \
+                            ULONG FAR *n_entryid, LPBYTE FAR *entryid) PURE;  \
+  STDMETHOD(OutboundMsgHook)(THIS_ LPMESSAGE message, LPMAPIFOLDER folder,    \
+                             LPMDB mdb, ULONG FAR *r_flags,                   \
+                             ULONG FAR *n_entryid, LPBYTE FAR *entryid) PURE
 
 
 
+\f
 EXTERN_C const IID IID_IMAPIProp;
 #undef INTERFACE
 #define INTERFACE IMAPIProp
 DECLARE_INTERFACE_(IMAPIProp,IUnknown)
 {
-  /*** IUnknown methods ***/
-  STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID*) PURE;
-  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
-  STDMETHOD_(ULONG,Release)(THIS) PURE;
-
-  /*** IMAPIProp methods ***/
-  STDMETHOD(GetLastError)(THIS_ HRESULT, ULONG, LPMAPIERROR FAR*);
-  STDMETHOD(SaveChanges)(THIS_ ULONG);
-  STDMETHOD(GetProps)(THIS_ LPSPropTagArray, ULONG, ULONG FAR*,
-                      LPSPropValue FAR*);
-  STDMETHOD(GetPropList)(THIS_ ULONG, LPSPropTagArray FAR *);
-  STDMETHOD(OpenProperty)(THIS_ ULONG, LPCIID lpiid, ULONG,
-                          ULONG, LPUNKNOWN FAR*);
-  STDMETHOD(SetProps)(THIS_ LONG, LPSPropValue, LPSPropProblemArray FAR*);
-  STDMETHOD(DeleteProps)(THIS_ LPSPropTagArray, LPSPropProblemArray FAR *);
-  STDMETHOD(CopyTo)(THIS_ ULONG, LPCIID, LPSPropTagArray, ULONG,
-                    LPMAPIPROGRESS, LPCIID lpInterface, LPVOID,
-                    ULONG, LPSPropProblemArray FAR*);
-  STDMETHOD(CopyProps)(THIS_ LPSPropTagArray, ULONG, LPMAPIPROGRESS,
-                       LPCIID, LPVOID, ULONG, LPSPropProblemArray FAR*);  
-  STDMETHOD(GetNamesFromIDs)(THIS_ LPSPropTagArray FAR*, LPGUID,
-                             ULONG, ULONG FAR*, LPMAPINAMEID FAR* FAR*);
-  STDMETHOD(GetIDsFromNames)(THIS_ ULONG, LPMAPINAMEID FAR*, ULONG,
-                             LPSPropTagArray FAR*);
+  MY_IUNKNOWN_METHODS;
+  MY_IMAPIPROP_METHODS;
+};
 
+
+
+EXTERN_C const IID IID_IMsgStore;
+#undef INTERFACE
+#define INTERFACE IMsgStore
+DECLARE_INTERFACE_(IMsgStore,IMAPIProp)
+{
+  MY_IUNKNOWN_METHODS;
+  MY_IMAPIPROP_METHODS;
+  MY_IMSGSTORE_METHODS;
 };
 
 
@@ -595,40 +891,32 @@ EXTERN_C const IID IID_IMessage;
 #define INTERFACE IMessage
 DECLARE_INTERFACE_(IMessage,IMAPIProp)
 {
-  /*** IUnknown methods ***/
-  STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID*) PURE;
-  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
-  STDMETHOD_(ULONG,Release)(THIS) PURE;
-
-  /*** IMAPIProp methods ***/
-  STDMETHOD(GetLastError)(THIS_ HRESULT, ULONG, LPMAPIERROR FAR*);
-  STDMETHOD(SaveChanges)(THIS_ ULONG);
-  STDMETHOD(GetProps)(THIS_ LPSPropTagArray, ULONG,ULONG FAR*,
-                      LPSPropValue FAR*);
-  STDMETHOD(GetPropList)(THIS_ ULONG, LPSPropTagArray FAR *);
-  STDMETHOD(OpenProperty)(THIS_ ULONG, LPCIID lpiid, ULONG,
-                          ULONG, LPUNKNOWN FAR*);
-  STDMETHOD(SetProps)(THIS_ LONG, LPSPropValue, LPSPropProblemArray FAR*);
-  STDMETHOD(DeleteProps)(THIS_ LPSPropTagArray, LPSPropProblemArray FAR *);
-  STDMETHOD(CopyTo)(THIS_ ULONG, LPCIID, LPSPropTagArray, ULONG,
-                    LPMAPIPROGRESS, LPCIID lpInterface, LPVOID,
-                    ULONG, LPSPropProblemArray FAR*);
-  STDMETHOD(CopyProps)(THIS_ LPSPropTagArray, ULONG, LPMAPIPROGRESS,
-                       LPCIID, LPVOID, ULONG, LPSPropProblemArray FAR*);  
-  STDMETHOD(GetNamesFromIDs)(THIS_ LPSPropTagArray FAR*, LPGUID,
-                             ULONG, ULONG FAR*, LPMAPINAMEID FAR* FAR*);
-  STDMETHOD(GetIDsFromNames)(THIS_ ULONG, LPMAPINAMEID FAR*, ULONG,
-                             LPSPropTagArray FAR*);
-
-  /*** IMessage methods ***/
-  STDMETHOD(GetAttachmentTable)(THIS_ ULONG, LPMAPITABLE FAR*);
-  STDMETHOD(OpenAttach)(THIS_ ULONG, LPCIID, ULONG, LPATTACH FAR*);
-  STDMETHOD(CreateAttach)(THIS_ LPCIID, ULONG, ULONG FAR*, LPATTACH FAR*);
-  STDMETHOD(DeleteAttach)(THIS_ ULONG, ULONG, LPMAPIPROGRESS, ULONG);
-  STDMETHOD(GetRecipientTable)(THIS_ ULONG, LPMAPITABLE FAR*);
-  STDMETHOD(ModifyRecipients)(THIS_ ULONG, LPADRLIST);
-  STDMETHOD(SubmitMessage)(THIS_ ULONG);
-  STDMETHOD(SetReadFlag)(THIS_ ULONG);
+  MY_IUNKNOWN_METHODS;
+  MY_IMAPIPROP_METHODS;
+  MY_IMESSAGE_METHODS;
+};
+
+
+EXTERN_C const IID IID_IMAPIContainer;
+#undef INTERFACE
+#define INTERFACE IMAPIContainer
+DECLARE_INTERFACE_(IMAPIContainer,IMAPIProp)
+{
+  MY_IUNKNOWN_METHODS;
+  MY_IMAPIPROP_METHODS;
+  MY_IMAPICONTAINER_METHODS;
+};
+
+
+EXTERN_C const IID IID_IMAPIFolder;
+#undef INTERFACE
+#define INTERFACE IMAPIFolder
+DECLARE_INTERFACE_(IMAPIFolder,IMAPIContainer)
+{
+  MY_IUNKNOWN_METHODS;
+  MY_IMAPIPROP_METHODS;
+  MY_IMAPICONTAINER_METHODS;
+  MY_IMAPIFOLDER_METHODS;
 };
 
 
@@ -637,31 +925,8 @@ EXTERN_C const IID IID_IAttachment;
 #define INTERFACE IAttach
 DECLARE_INTERFACE_(IAttach, IMAPIProp)
 {
-  /*** IUnknown methods ***/
-  STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID*) PURE;
-  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
-  STDMETHOD_(ULONG,Release)(THIS) PURE;
-
-  /*** IMAPIProp methods ***/
-  STDMETHOD(GetLastError)(THIS_ HRESULT, ULONG, LPMAPIERROR FAR*);
-  STDMETHOD(SaveChanges)(THIS_ ULONG);
-  STDMETHOD(GetProps)(THIS_ LPSPropTagArray, ULONG,ULONG FAR*,
-                      LPSPropValue FAR*);
-  STDMETHOD(GetPropList)(THIS_ ULONG, LPSPropTagArray FAR *);
-  STDMETHOD(OpenProperty)(THIS_ ULONG, LPCIID lpiid, ULONG,
-                          ULONG, LPUNKNOWN FAR*);
-  STDMETHOD(SetProps)(THIS_ LONG, LPSPropValue, LPSPropProblemArray FAR*);
-  STDMETHOD(DeleteProps)(THIS_ LPSPropTagArray, LPSPropProblemArray FAR *);
-  STDMETHOD(CopyTo)(THIS_ ULONG, LPCIID, LPSPropTagArray, ULONG,
-                    LPMAPIPROGRESS, LPCIID lpInterface, LPVOID,
-                    ULONG, LPSPropProblemArray FAR*);
-  STDMETHOD(CopyProps)(THIS_ LPSPropTagArray, ULONG, LPMAPIPROGRESS,
-                       LPCIID, LPVOID, ULONG, LPSPropProblemArray FAR*);  
-  STDMETHOD(GetNamesFromIDs)(THIS_ LPSPropTagArray FAR*, LPGUID,
-                             ULONG, ULONG FAR*, LPMAPINAMEID FAR* FAR*);
-  STDMETHOD(GetIDsFromNames)(THIS_ ULONG, LPMAPINAMEID FAR*, ULONG,
-                             LPSPropTagArray FAR*);
-
+  MY_IUNKNOWN_METHODS;
+  MY_IMAPIPROP_METHODS;
   /*** IAttach methods ***/
   /* No methods */
 };
@@ -672,66 +937,101 @@ EXTERN_C const IID IID_IMAPITableData;
 #define INTERFACE IMAPITable
 DECLARE_INTERFACE_(IMAPITable,IUnknown)
 {
-  /*** IUnknown methods ***/
-  STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID*) PURE;
-  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
-  STDMETHOD_(ULONG,Release)(THIS) PURE;
-
-  /*** IMAPITable methods ***/
-  STDMETHOD(GetLastError)(THIS_ HRESULT, ULONG, LPMAPIERROR*) PURE;
-  STDMETHOD(Advise)(THIS_ ULONG, LPMAPIADVISESINK, ULONG*) PURE;
-  STDMETHOD(Unadvise)(THIS_ ULONG ulCxn) PURE;
-  STDMETHOD(GetStatus)(THIS_ ULONG*, ULONG*) PURE;
-  STDMETHOD(SetColumns)(THIS_ LPSPropTagArray, ULONG) PURE;
-  STDMETHOD(QueryColumns)(THIS_ ULONG, LPSPropTagArray*) PURE;
-  STDMETHOD(GetRowCount)(THIS_ ULONG, ULONG *) PURE;
-  STDMETHOD(SeekRow)(THIS_ BOOKMARK, LONG, LONG*) PURE;
-  STDMETHOD(SeekRowApprox)(THIS_ ULONG, ULONG) PURE;
-  STDMETHOD(QueryPosition)(THIS_ ULONG*, ULONG*, ULONG*) PURE;
-  STDMETHOD(FindRow)(THIS_ LPSRestriction, BOOKMARK, ULONG) PURE;
-  STDMETHOD(Restrict)(THIS_ LPSRestriction, ULONG) PURE;
-  STDMETHOD(CreateBookmark)(THIS_ BOOKMARK*) PURE;
-  STDMETHOD(FreeBookmark)(THIS_ BOOKMARK) PURE;
-  STDMETHOD(SortTable)(THIS_ LPSSortOrderSet, ULONG) PURE;
-  STDMETHOD(QuerySortOrder)(THIS_ LPSSortOrderSet*) PURE;
-  STDMETHOD(QueryRows)(THIS_ LONG, ULONG, LPSRowSet*) PURE;
-  STDMETHOD(Abort)(THIS) PURE;
-  STDMETHOD(ExpandRow)(THIS_ ULONG, LPBYTE, ULONG, ULONG, 
-                       LPSRowSet*, ULONG*) PURE;
-  STDMETHOD(CollapseRow)(THIS_ ULONG, LPBYTE, ULONG, ULONG*) PURE;
-  STDMETHOD(WaitForCompletion)(THIS_ ULONG, ULONG, ULONG*) PURE;
-  STDMETHOD(GetCollapseState)(THIS_ ULONG, ULONG, LPBYTE, ULONG*,LPBYTE*) PURE;
-  STDMETHOD(SetCollapseState)(THIS_ ULONG, ULONG, LPBYTE, BOOKMARK*) PURE;
+  MY_IUNKNOWN_METHODS;
+  MY_IMAPITABLE_METHODS;
 };
 
 
+EXTERN_C const IID IID_IMAPISession;
+#undef INTERFACE
+#define INTERFACE IMAPISession
+DECLARE_INTERFACE_(IMAPISession, IUnknown)
+{
+  MY_IUNKNOWN_METHODS;
+  MY_IMAPISESSION_METHODS;
+};
+
+
+
 
 EXTERN_C const IID IID_IConverterSession;
 #undef INTERFACE
 #define INTERFACE IConverterSession
 DECLARE_INTERFACE_(IConverterSession, IUnknown)
 {
-  /*** IUnknown methods ***/
-  STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID*) PURE;
-  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
-  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  MY_IUNKNOWN_METHODS;
 
   /*** IConverterSession ***/
-  STDMETHOD(PlaceHolder1)(THIS);
+
+  /* Pass a MAPI address book to be used for name resultion to the
+     converter.  */
+  STDMETHOD(SetAdrBook)(THIS_ LPADRBOOK pab);
+  /* For an encoding for the outermost MIME container.  */
   STDMETHOD(SetEncoding)(THIS_ ENCODINGTYPE);
-  STDMETHOD(PlaceHolder2)(THIS);
-  STDMETHOD(MIMEToMAPI)(THIS_ LPSTREAM, LPMESSAGE, LPCSTR, ULONG);
-  STDMETHOD(MAPIToMIMEStm)(THIS_ LPMESSAGE,LPSTREAM,ULONG);
   STDMETHOD(PlaceHolder3)(THIS);
-  STDMETHOD(PlaceHolder4)(THIS);
-  STDMETHOD(PlaceHolder5)(THIS);
+  /* Convert a MIME stream to a MAPI message.  SRC_SRV needs to be
+     NULL. */
+  STDMETHOD(MIMEToMAPI)(THIS_ LPSTREAM pstm, LPMESSAGE pmsg,
+                        LPCSTR src_srv, ULONG flags);
+  /* Convert a MAPI message to a MIME stream. */
+  STDMETHOD(MAPIToMIMEStm)(THIS_ LPMESSAGE pmsg, LPSTREAM pstm, ULONG flags);
+  STDMETHOD(PlaceHolder6)(THIS);
+  STDMETHOD(PlaceHolder7)(THIS);
+  STDMETHOD(PlaceHolder8)(THIS);
+  /* Enable text wrapping and the maximum line length.  */
   STDMETHOD(SetTextWrapping)(THIS_ BOOL, ULONG);
+  /* Set the MIME save format.  The default is SAVE_RFC1521 (MIME) but
+     my be changed using this function to SAVE_RFC822 (uuencode).  */
   STDMETHOD(SetSaveFormat)(THIS_ MIMESAVETYPE);
-  STDMETHOD(PlaceHolder8)(THIS);
-  STDMETHOD(PlaceHolder9)(THIS);
+  STDMETHOD(PlaceHolder11)(THIS);
+  /* Tell which character set to use.  HCHARSET is either NULL or a
+     handle retrieved by (e.g.) MimeOleGetCodePageCharset.  If FAPPLY
+     is false, HCHARSET is not used.  */
+  STDMETHOD(SetCharset)(THIS_ BOOL fApply, HCHARSET hcharset,
+                        CSETAPPLYTYPE csetapplytype);
 };
 
 
+EXTERN_C const IID IID_ISpoolerHook;
+#undef INTERFACE
+#define INTERFACE ISpoolerHook
+DECLARE_INTERFACE_(ISpoolerHook, IUnknown)
+{
+  MY_IUNKNOWN_METHODS;
+  MY_ISPOOLERHOOK_METHODS;
+};
+
+
+#undef MY_IUNKNOWN_METHODS
+#undef MY_IMAPIPROP_METHODS
+#undef MY_IMSGSTORE_METHODS
+#undef MY_IMESSAGE_METHODS
+#undef MY_IMAPICONTAINER_METHODS
+#undef MY_IMAPIFOLDER_METHODS
+#undef MY_IMAPITABLE_METHODS
+#undef MY_IMAPISESSION_METHODS
+#undef MY_ISPOOLERHOOK_METHODS
+
+
+\f
+/**** C Wrapper ****/
+#ifdef COBJMACROS
+
+#define IMessage_CreateAttach(This,a,b,c,d) \
+                (This)->lpVtbl->CreateAttach ((This),(a),(b),(c),(d))
+#define IMessage_DeleteAttach(This,a,b,c,d) \
+                (This)->lpVtbl->DeleteAttach ((This),(a),(b),(c),(d))
+
+#define IAttach_Release(This)  (This)->lpVtbl->Release ((This))
+#define IAttach_SaveChanges(This,a) (This)->lpVtbl->SaveChanges ((This),(a))
+#define IAttach_OpenProperty(This,a,b,c,d,e) \
+                (This)->lpVtbl->OpenProperty ((This),(a),(b),(c),(d),(e))
+
+
+
+
+#endif /*COBJMACROS*/
+
 \f
 /****  Function prototypes. *****/
 
@@ -761,7 +1061,7 @@ SCODE WINAPI MAPIAllocateBuffer (ULONG, LPVOID FAR *);
 ULONG WINAPI MAPIFreeBuffer (LPVOID);
 
 void    MAPIUninitialize (void);
-HRESULT MAPIInitialize (LPVOID lpMapiInit);  
+HRESULT MAPIInitialize (LPVOID lpMapiInit);
 
 #if defined (UNICODE)
 HRESULT WINAPI OpenStreamOnFile(LPALLOCATEBUFFER,LPFREEBUFFER,
index 609abc2..4c7d746 100644 (file)
 #define PR_CONTROL_ID                         PROP_TAG( PT_BINARY,      0x3F07)
 #define PR_INITIAL_DETAILS_PANE               PROP_TAG( PT_LONG,        0x3F08)
 #define PR_MSG_EDITOR_FORMAT                  PROP_TAG( PT_LONG,        0x5903)
+#define PR_ATTACHMENT_HIDDEN                  PROP_TAG( PT_BOOLEAN,     0x7ffe)
 
 #define PROP_ID_SECURE_MIN                0x67F0
 #define PROP_ID_SECURE_MAX                0x67FF
index 1178b67..dd129d2 100644 (file)
@@ -29,7 +29,7 @@
 #include "mymapitags.h"
 #include "myexchext.h"
 #include "display.h"
-#include "intern.h"
+#include "common.h"
 #include "gpgmsg.hh"
 #include "msgcache.h"
 #include "engine.h"
index a67cebb..80db60a 100644 (file)
@@ -27,6 +27,7 @@ class GpgolSessionEvents;
 class GpgolMessageEvents;
 class GpgolAttachedFileEvents;
 class GpgolPropertySheets;
+class GpgolItemEvents;
 
 bool GPGOptionsDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
index 21d5da6..b3b0b5c 100644 (file)
 #include <windows.h>
 #include <prsht.h>
 
-#include "intern.h"
 #include "mymapi.h"
 #include "mymapitags.h"
+#include "myexchext.h"
+#include "common.h"
 #include "display.h"
-
+#include "ol-ext-callback.h"
 #include "olflange-def.h"
 #include "olflange-ids.h"
 
index b796f09..8a5a806 100644 (file)
@@ -34,8 +34,9 @@
 #include "mymapi.h"
 #include "mymapitags.h"
 #include "myexchext.h"
+
+#include "common.h"
 #include "display.h"
-#include "intern.h"
 #include "gpgmsg.hh"
 #include "msgcache.h"
 #include "engine.h"
 #include "message-events.h"
 #include "property-sheets.h"
 #include "attached-file-events.h"
+#include "item-events.h"
 
-
+/* The GUID for this plugin.  */
 #define CLSIDSTR_GPGOL   "{42d30988-1a3a-11da-c687-000d6080e735}"
 DEFINE_GUID(CLSID_GPGOL, 0x42d30988, 0x1a3a, 0x11da, 
             0xc6, 0x87, 0x00, 0x0d, 0x60, 0x80, 0xe7, 0x35);
 
+/* For documentation: The GUID used for our custom properties: 
+   {31805ab8-3e92-11dc-879c-00061b031004}
+ */
+
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                                      SRCNAME, __func__, __LINE__); \
@@ -91,6 +97,20 @@ ext_context_name (unsigned long no)
 }
 
 
+/* Wrapper around UlRelease with error checking. */
+/* FIXME: Duplicated code.  */
+static void 
+ul_release (LPVOID punk)
+{
+  ULONG res;
+  
+  if (!punk)
+    return;
+  res = UlRelease (punk);
+//   log_debug ("%s UlRelease(%p) had %lu references\n", __func__, punk, res);
+}
+
+
 \f
 /* Registers this module as an Exchange extension. This basically updates
    some Registry entries. */
@@ -143,7 +163,7 @@ DllRegisterServer (void)
      -    IExchExtModeless
      -    IExchExtModelessCallback
                    ___1234567___ */
-  lstrcat (szEntry, ";1111110"); 
+  lstrcat (szEntry, ";11111101"); 
   ec = RegCreateKeyEx (HKEY_LOCAL_MACHINE, szKeyBuf, 0, NULL, 
                        REG_OPTION_NON_VOLATILE,
                        KEY_ALL_ACCESS, NULL, &hkey, NULL);
@@ -272,19 +292,27 @@ GpgolExt::GpgolExt (void)
   m_hWndExchange = 0;
   m_gpgEncrypt = FALSE;
   m_gpgSign = FALSE;
+  msgtype = MSGTYPE_UNKNOWN;
+  msgtype_valid = FALSE;
 
   m_pExchExtCommands           = new GpgolExtCommands (this);
   m_pExchExtSessionEvents      = new GpgolSessionEvents (this);
   m_pExchExtMessageEvents      = new GpgolMessageEvents (this);
   m_pExchExtAttachedFileEvents = new GpgolAttachedFileEvents (this);
   m_pExchExtPropertySheets     = new GpgolPropertySheets (this);
+  m_pOutlookExtItemEvents      = new GpgolItemEvents (this);
   if (!m_pExchExtCommands
       || !m_pExchExtSessionEvents
       || !m_pExchExtMessageEvents
       || !m_pExchExtAttachedFileEvents
-      || !m_pExchExtPropertySheets)
+      || !m_pExchExtPropertySheets
+      || !m_pOutlookExtItemEvents)
     out_of_core ();
-  
+
+  /* For this class we need to bump the reference counter intially.
+     The question is why it works at all with the other stuff.  */
+  m_pOutlookExtItemEvents->AddRef ();
+
   if (!g_initdll)
     {
       if (opt.compat.auto_decrypt)
@@ -304,6 +332,9 @@ GpgolExt::~GpgolExt (void)
   log_debug ("%s:%s: cleaning up GpgolExt object; context=%s\n",
              SRCNAME, __func__, ext_context_name (m_lContext));
     
+  if (m_pOutlookExtItemEvents)
+    m_pOutlookExtItemEvents->Release ();
+
   if (m_lContext == EECONTEXT_SESSION)
     {
       if (g_initdll)
@@ -315,6 +346,7 @@ GpgolExt::~GpgolExt (void)
           log_debug ("%s:%s: DLL closed down\n", SRCNAME, __func__);
        }       
     }
+  
 
 }
 
@@ -360,6 +392,10 @@ GpgolExt::QueryInterface(REFIID riid, LPVOID *ppvObj)
        return E_NOINTERFACE;
       *ppvObj = (LPUNKNOWN) m_pExchExtPropertySheets;
     }
+  else if (riid == IID_IOutlookExtItemEvents)
+    {
+      *ppvObj = (LPUNKNOWN)m_pOutlookExtItemEvents;
+    }  
   else
     hr = E_NOINTERFACE;
   
@@ -382,6 +418,8 @@ GpgolExt::QueryInterface(REFIID riid, LPVOID *ppvObj)
 STDMETHODIMP 
 GpgolExt::Install(LPEXCHEXTCALLBACK pEECB, ULONG lContext, ULONG lFlags)
 {
+  static int version_shown;
+  
   ULONG lBuildVersion;
   ULONG lActualVersion;
   ULONG lVirtualVersion;
@@ -397,23 +435,27 @@ GpgolExt::Install(LPEXCHEXTCALLBACK pEECB, ULONG lContext, ULONG lFlags)
   pEECB->GetVersion (&lBuildVersion, EECBGV_GETBUILDVERSION);
   pEECB->GetVersion (&lActualVersion, EECBGV_GETACTUALVERSION);
   pEECB->GetVersion (&lVirtualVersion, EECBGV_GETVIRTUALVERSION);
-  log_debug ("%s:%s: detected Outlook build version 0x%lx (%lu.%lu)\n",
-             SRCNAME, __func__, lBuildVersion,
-             (lBuildVersion & EECBGV_BUILDVERSION_MAJOR_MASK) >> 16,
-             (lBuildVersion & EECBGV_BUILDVERSION_MINOR_MASK));
-  log_debug ("%s:%s:                 actual version 0x%lx (%u.%u.%u.%u)\n",
-             SRCNAME, __func__, lActualVersion, 
-             (unsigned int)((lActualVersion >> 24) & 0xff),
-             (unsigned int)((lActualVersion >> 16) & 0xff),
+  if (!version_shown)
+    {
+      version_shown = 1;
+      log_debug ("%s:%s: detected Outlook build version 0x%lx (%lu.%lu)\n",
+                 SRCNAME, __func__, lBuildVersion,
+                 (lBuildVersion & EECBGV_BUILDVERSION_MAJOR_MASK) >> 16,
+                 (lBuildVersion & EECBGV_BUILDVERSION_MINOR_MASK));
+      log_debug ("%s:%s:                 actual version 0x%lx (%u.%u.%u.%u)\n",
+                 SRCNAME, __func__, lActualVersion, 
+                 (unsigned int)((lActualVersion >> 24) & 0xff),
+                 (unsigned int)((lActualVersion >> 16) & 0xff),
              (unsigned int)((lActualVersion >> 8) & 0xff),
-             (unsigned int)(lActualVersion & 0xff));
-  log_debug ("%s:%s:                virtual version 0x%lx (%u.%u.%u.%u)\n",
-             SRCNAME, __func__, lVirtualVersion, 
-             (unsigned int)((lVirtualVersion >> 24) & 0xff),
-             (unsigned int)((lVirtualVersion >> 16) & 0xff),
+                 (unsigned int)(lActualVersion & 0xff));
+      log_debug ("%s:%s:                virtual version 0x%lx (%u.%u.%u.%u)\n",
+                 SRCNAME, __func__, lVirtualVersion, 
+                 (unsigned int)((lVirtualVersion >> 24) & 0xff),
+                 (unsigned int)((lVirtualVersion >> 16) & 0xff),
              (unsigned int)((lVirtualVersion >> 8) & 0xff),
-             (unsigned int)(lVirtualVersion & 0xff));
-
+                 (unsigned int)(lVirtualVersion & 0xff));
+    }
+  
   if (EECBGV_BUILDVERSION_MAJOR
       != (lBuildVersion & EECBGV_BUILDVERSION_MAJOR_MASK))
     {
@@ -467,5 +509,32 @@ GpgolExt::Install(LPEXCHEXTCALLBACK pEECB, ULONG lContext, ULONG lFlags)
 }
 
 
+/* Return the message type for the current message.  EECB needs to be
+   passed to allow access to the message object.  The function caches
+   the message class so there is no overhead in calling this
+   method. */
+msgtype_t 
+GpgolExt::getMsgtype (LPEXCHEXTCALLBACK eecb)
+{
+  LPMDB mdb = NULL;
+  LPMESSAGE message = NULL;
 
+  if (msgtype_valid)
+    return msgtype;
+  if (!eecb)
+    {
+      log_error ("%s:%s: eecp not passed", SRCNAME, __func__);
+      return MSGTYPE_UNKNOWN;
+    }
+      
+  eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
+  msgtype = mapi_get_message_type (message);
+  log_debug ("%s:%s: found msgtype %d\n", SRCNAME, __func__, msgtype);
+  msgtype_valid = TRUE;
+
+  ul_release (message);
+  ul_release (mdb);
+
+  return msgtype;
+}
 
index ab166d0..6ad5d49 100644 (file)
@@ -22,6 +22,8 @@
 #ifndef OLFLANGE_H
 #define OLFLANGE_H
 
+#include "mapihelp.h"
+
 
 /*
  GpgolExt 
@@ -46,12 +48,17 @@ private:
   ULONG m_lRef;
   ULONG m_lContext;
   
+  /* Information pertaining to the current message.  */
+  msgtype_t msgtype;    /* Type of the current message.  */
+  BOOL msgtype_valid;   /* Indicates that MSGTYPE is valid.  */
+
   /* Pointer to the other extension objects.  */
-  GpgolExtCommands           *m_pExchExtCommands;
-  GpgolSessionEvents            *m_pExchExtSessionEvents;
+  GpgolExtCommands        *m_pExchExtCommands;
+  GpgolSessionEvents      *m_pExchExtSessionEvents;
   GpgolMessageEvents      *m_pExchExtMessageEvents;
   GpgolPropertySheets     *m_pExchExtPropertySheets;
   GpgolAttachedFileEvents *m_pExchExtAttachedFileEvents;
+  GpgolItemEvents         *m_pOutlookExtItemEvents;
 
 public:
   STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj);
@@ -64,6 +71,7 @@ public:
       return lCount;   
     };
   STDMETHODIMP Install(LPEXCHEXTCALLBACK pEECB, ULONG lContext, ULONG lFlags);
+  msgtype_t getMsgtype (LPEXCHEXTCALLBACK eecb);
 };
 
 
index ec5e2d6..aedd89d 100644 (file)
@@ -29,9 +29,9 @@
 #include <assert.h>
 #include <gpgme.h>
 
+#include "common.h"
 #include "gpgol-ids.h"
 #include "passcache.h"
-#include "intern.h"
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                                      SRCNAME, __func__, __LINE__); \
index d73d975..b1dc6f6 100644 (file)
 
 #include "mymapi.h"
 #include "mymapitags.h"
-
 #include "rfc822parse.h"
-#include "intern.h"
-#include "util.h"
+
+#include "common.h"
 #include "pgpmime.h"
 #include "engine.h"
 
    only for 1000 bytes; thus 2000 seems to be a reasonable value. */
 #define LINEBUFSIZE 2000
 
-/* The reverse base-64 list used for base-64 decoding. */
-static unsigned char const asctobin[256] = {
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 
-  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 
-  0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 
-  0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 
-  0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 
-  0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-  0xff, 0xff, 0xff, 0xff
-};
-
-
-
 
 /* The context object we use to track information. */
 struct pgpmime_context
@@ -120,14 +91,7 @@ struct pgpmime_context
 
   LPSTREAM outstream;     /* NULL or a stream to write a part to. */
 
-  /* Helper to keep the state of the base64 decoder. */
-  struct 
-  {
-    int idx;
-    unsigned char val;
-    int stop_seen;
-    int invalid_encoding;
-  } base64;
+  b64_state_t base64;     /* The state of the BAse-64 decoder.  */
 
   int line_too_long;  /* Indicates that a received line was too long. */
   int parser_error;   /* Indicates that we encountered a error from
@@ -175,96 +139,6 @@ latin1_data_write (gpgme_data_t data, const char *line, size_t len)
 }
 
 
-
-/* Do in-place decoding of quoted-printable data of LENGTH in BUFFER.
-   Returns the new length of the buffer. */
-static size_t
-qp_decode (char *buffer, size_t length)
-{
-  char *d, *s;
-
-  for (s=d=buffer; length; length--)
-    if (*s == '=' && length > 2 && hexdigitp (s+1) && hexdigitp (s+2))
-      {
-        s++;
-        *(unsigned char*)d++ = xtoi_2 (s);
-        s += 2;
-        length -= 2;
-      }
-    else
-      *d++ = *s++;
-  
-  return d - buffer;
-}
-
-
-/* Do in-place decoding of base-64 data of LENGTH in BUFFER.  Returns
-   the new length of the buffer. CTX is required to return errors and
-   to maintain state of the decoder.  */
-static size_t
-base64_decode (pgpmime_context_t ctx, char *buffer, size_t length)
-{
-  int idx = ctx->base64.idx;
-  unsigned char val = ctx->base64.val;
-  int c;
-  char *d, *s;
-
-  if (ctx->base64.stop_seen)
-    return 0;
-
-  for (s=d=buffer; length; length--, s++)
-    {
-      if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
-        continue;
-      if (*s == '=')
-        { 
-          /* Pad character: stop */
-          if (idx == 1)
-            *d++ = val; 
-          ctx->base64.stop_seen = 1;
-          break;
-        }
-
-      if ((c = asctobin[*(unsigned char *)s]) == 255) 
-        {
-          if (!ctx->base64.invalid_encoding)
-            log_debug ("%s: invalid base64 character %02X at pos %d skipped\n",
-                       __func__, *(unsigned char*)s, (int)(s-buffer));
-          ctx->base64.invalid_encoding = 1;
-          continue;
-        }
-
-      switch (idx) 
-        {
-        case 0: 
-          val = c << 2;
-          break;
-        case 1: 
-          val |= (c>>4)&3;
-          *d++ = val;
-          val = (c<<4)&0xf0;
-          break;
-        case 2: 
-          val |= (c>>2)&15;
-          *d++ = val;
-          val = (c<<6)&0xc0;
-          break;
-        case 3: 
-          val |= c&0x3f;
-          *d++ = val;
-          break;
-        }
-      idx = (idx+1) % 4;
-    }
-
-  
-  ctx->base64.idx = idx;
-  ctx->base64.val = val;
-  return d - buffer;
-}
-
-
-
 /* Print the message event EVENT. */
 static void
 debug_message_event (pgpmime_context_t ctx, rfc822parse_event_t event)
@@ -418,10 +292,7 @@ message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
           else if (!stricmp (p+off, "base64"))
             {
               ctx->is_base64_encoded = 1;
-              ctx->base64.idx = 0;
-              ctx->base64.val = 0;
-              ctx->base64.stop_seen = 0;
-              ctx->base64.invalid_encoding = 0;
+              b64_init (&ctx->base64);
             }
           free (p);
         }
@@ -595,7 +466,7 @@ plaintext_handler (void *handle, const void *buffer, size_t size)
                   if (ctx->is_qp_encoded)
                     len = qp_decode (ctx->linebuf, pos);
                   else if (ctx->is_base64_encoded)
-                    len = base64_decode (ctx, ctx->linebuf, pos);
+                    len = b64_decode (&ctx->base64, ctx->linebuf, pos);
                   else
                     len = pos;
                   if (len)
@@ -621,7 +492,7 @@ plaintext_handler (void *handle, const void *buffer, size_t size)
                   if (ctx->is_qp_encoded)
                     len = qp_decode (ctx->linebuf, pos);
                   else if (ctx->is_base64_encoded)
-                    len = base64_decode (ctx, ctx->linebuf, pos);
+                    len = b64_decode (&ctx->base64, ctx->linebuf, pos);
                   else
                     len = pos;
                   if (len)
@@ -651,7 +522,7 @@ plaintext_handler (void *handle, const void *buffer, size_t size)
                   if (ctx->is_qp_encoded)
                     len = qp_decode (ctx->linebuf, pos);
                   else if (ctx->is_base64_encoded)
-                    len = base64_decode (ctx, ctx->linebuf, pos);
+                    len = b64_decode (&ctx->base64, ctx->linebuf, pos);
                   else
                     len = pos;
                   if (len)
@@ -711,7 +582,8 @@ pgpmime_decrypt (LPSTREAM instream, int ttl, char **body,
     goto leave;
 
   tmp = native_to_utf8 (_("[PGP/MIME message]"));
-  err = op_decrypt_stream_to_gpgme (instream, plaintext, ttl, tmp,
+  err = op_decrypt_stream_to_gpgme (GPGME_PROTOCOL_OpenPGP,
+                                    instream, plaintext, ttl, tmp,
                                     attestation, preview_mode);
   xfree (tmp);
   if (!err && (ctx->parser_error || ctx->line_too_long))
@@ -818,7 +690,8 @@ pgpmime_verify (const char *message, int ttl, char **body,
       gpgme_data_seek (ctx->signed_data, 0, SEEK_SET);
       gpgme_data_seek (ctx->sig_data, 0, SEEK_SET);
       tmp = native_to_utf8 (_("[PGP/MIME signature]"));
-      err = op_verify_detached_sig_gpgme (ctx->signed_data, ctx->sig_data,
+      err = op_verify_detached_sig_gpgme (GPGME_PROTOCOL_OpenPGP,
+                                          ctx->signed_data, ctx->sig_data,
                                           tmp, attestation);
       xfree (tmp);
     }
index 6e35c3f..4d3c2d1 100644 (file)
@@ -28,8 +28,8 @@
 #include "mymapi.h"
 #include "mymapitags.h"
 #include "myexchext.h"
+#include "common.h"
 #include "display.h"
-#include "intern.h"
 #include "gpgmsg.hh"
 #include "msgcache.h"
 #include "engine.h"
index c0793a1..f8d873f 100644 (file)
@@ -34,9 +34,9 @@
 #include <gpgme.h>
 #include <assert.h>
 
+#include "common.h"
 #include "gpgol-ids.h"
-#include "intern.h"
-#include "util.h"
+
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                                      SRCNAME, __func__, __LINE__); \
index 79da4e8..aa1c0c4 100644 (file)
@@ -1010,7 +1010,8 @@ is_parameter (TOKEN t)
    With LOWER_VALUE set to true, a matching field value will be
    lowercased.
  
-   Note, that ATTR should be lowercase.
+   Note, that ATTR should be lowercase.  A CTX of NULL is allowed and
+   will return NULL.
  */
 const char *
 rfc822parse_query_parameter (rfc822parse_field_t ctx, const char *attr,
index ade5c64..5e0ed26 100644 (file)
@@ -29,7 +29,7 @@
 #include "mymapitags.h"
 #include "myexchext.h"
 #include "display.h"
-#include "intern.h"
+#include "common.h"
 #include "gpgmsg.hh"
 #include "msgcache.h"
 #include "engine.h"
@@ -107,6 +107,10 @@ GpgolSessionEvents::OnDelivery (LPEXCHEXTCALLBACK pEECB)
   log_debug ("%s:%s: received\n", SRCNAME, __func__);
   pEECB->GetObject (&pMDB, (LPMAPIPROP *)&pMessage);
   log_mapi_property (pMessage, PR_MESSAGE_CLASS,"PR_MESSAGE_CLASS");
+  /* Note, that at this point even an OpenPGP signed message has the
+     message class IPM.Note.SMIME.MultipartSigned.  If we would not
+     change the message class here, OL will change it later (before an
+     OnRead) to IPM.Note. */
   mapi_change_message_class (pMessage);
   log_mapi_property (pMessage, PR_MESSAGE_CLASS,"PR_MESSAGE_CLASS");
   ul_release (pMessage);
index 8e993cd..7a0ebd2 100644 (file)
@@ -63,6 +63,9 @@ char *read_w32_registry_string (const char *root, const char *dir,
 
 
 /*-- main.c --*/
+const void *get_128bit_session_key (void);
+void *create_initialization_vector (size_t nbytes);
+
 void log_debug (const char *fmt, ...) __attribute__ ((format (printf,1,2)));
 void log_error (const char *fmt, ...) __attribute__ ((format (printf,1,2)));
 void log_vdebug (const char *fmt, va_list a);
index 1049420..dd80c9d 100644 (file)
@@ -1,5 +1,5 @@
 /* verify-dialog.c
- *     Copyright (C) 2005 g10 Code GmbH
+ *     Copyright (C) 2005, 2007 g10 Code GmbH
  *
  * This file is part of GPGol.
  * 
 
 #include <windows.h>
 #include <time.h>
-#include <gpgme.h>
 
+#include "common.h"
 #include "gpgol-ids.h"
-#include "intern.h"
-#include "util.h"
+
 
 struct dialog_context
 {
   gpgme_verify_result_t res;
+  gpgme_protocol_t protocol;
   const char *filename;
 };
 
@@ -78,7 +78,7 @@ load_akalist (HWND dlg, gpgme_key_t key)
 
 
 static void 
-load_sigbox (HWND dlg, gpgme_verify_result_t ctx)
+load_sigbox (HWND dlg, gpgme_verify_result_t ctx, gpgme_protocol_t protocol)
 {
   gpgme_error_t err;
   gpgme_key_t key;
@@ -109,6 +109,7 @@ load_sigbox (HWND dlg, gpgme_verify_result_t ctx)
     key = NULL;
     if (!gpgme_new (&gctx))
       {
+        gpgme_set_protocol (gctx, protocol);
         err = gpgme_get_key (gctx, buf+2, &key, 0);
         if (err)
           {
@@ -208,12 +209,26 @@ verify_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
     case WM_INITDIALOG:
       
        ctx = (struct dialog_context *)lparam;
-       load_sigbox (dlg, ctx->res);
+       load_sigbox (dlg, ctx->res, ctx->protocol);
        center_window (dlg, NULL);
        SetForegroundWindow (dlg);
         if (ctx->filename)
           {
-            const char *s = _("Verification Result");
+            const char *s;
+
+            switch (ctx->protocol)
+              {
+              case GPGME_PROTOCOL_OpenPGP:
+                s = _("OpenPGP Verification Result");
+                break;
+              case GPGME_PROTOCOL_CMS:
+                s = _("S/MIME Verification Result");
+                break;
+              default:
+                s = "?";
+                break;
+              }
+                  
             char *tmp = xmalloc (strlen (ctx->filename) 
                                  + strlen (s) + 100);
             strcpy (stpcpy (stpcpy (stpcpy (tmp, s),
@@ -239,13 +254,15 @@ verify_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
    RES. FILENAME is used to modify the caption of the dialog; it may
    be NULL. */
 int
-verify_dialog_box (gpgme_verify_result_t res, const char *filename)
+verify_dialog_box (gpgme_protocol_t protocol, 
+                   gpgme_verify_result_t res, const char *filename)
 {
   struct dialog_context ctx;
   int resid;
 
   memset (&ctx,0, sizeof ctx);
   ctx.res = res;
+  ctx.protocol = protocol;
   ctx.filename = filename;
 
   if (!strncmp (gettext_localename (), "de", 2))
index e53bf4a..64a5f99 100644 (file)
@@ -27,9 +27,8 @@
 #include "mymapi.h"
 #include "myexchext.h"
 #include "mymapitags.h"
+#include "common.h"
 #include "gpgmsg.hh"
-#include "util.h"
-#include "intern.h"
 
 /* Exchange callback context to retrieve the last message. */
 static LPEXCHEXTCALLBACK g_cb = NULL;