Attached is a patch to support encrypted .sdw files.

The sdw_cryptor.* files belong in the abiword-plugins/wp/impexp/sdw/xp/
directory, as you have surely guessed.

please commit it, thanks.

-- 
"They that can give up essential liberty to obtain a little temporary
safety deserve neither liberty nor safety."
                                                 -- Benjamin Franklin
? .thumbnails
? sdw_cryptor.cpp
? sdw_cryptor.h
Index: GNUmakefile.am
===================================================================
RCS file: /cvsroot/abiword-plugins/wp/impexp/sdw/xp/GNUmakefile.am,v
retrieving revision 1.1
diff -u -r1.1 GNUmakefile.am
--- GNUmakefile.am      22 Apr 2002 21:35:27 -0000      1.1
+++ GNUmakefile.am      29 Apr 2002 14:09:15 -0000
@@ -4,7 +4,8 @@
 
 plugin_LTLIBRARIES = libAbiSDW.la
 
-libAbiSDW_la_SOURCES = ie_imp_StarOffice.cpp
+libAbiSDW_la_SOURCES = ie_imp_StarOffice.cpp \
+                       sdw_cryptor.cpp
 
 libAbiSDW_la_LIBADD = @ABI_LIBS@
 
Index: Makefile
===================================================================
RCS file: /cvsroot/abiword-plugins/wp/impexp/sdw/xp/Makefile,v
retrieving revision 1.1
diff -u -r1.1 Makefile
--- Makefile    22 Apr 2002 21:35:27 -0000      1.1
+++ Makefile    29 Apr 2002 14:09:15 -0000
@@ -22,7 +22,8 @@
 include $(ABI_ROOT)/src/config/abi_defs.mk
 
 TARGETS=                       $(OBJS)
-CPPSRCS=                       ie_imp_StarOffice.cpp
+CPPSRCS=                       ie_imp_StarOffice.cpp \
+                               sdw_cryptor.cpp
 
 ifeq ($(ABI_FE), Win32)
        DEFINES+=-DABI_PLUGIN_VERSION=\"0.99.1Win32\"
Index: ie_imp_StarOffice.cpp
===================================================================
RCS file: /cvsroot/abiword-plugins/wp/impexp/sdw/xp/ie_imp_StarOffice.cpp,v
retrieving revision 1.3
diff -u -r1.3 ie_imp_StarOffice.cpp
--- ie_imp_StarOffice.cpp       25 Apr 2002 12:32:46 -0000      1.3
+++ ie_imp_StarOffice.cpp       29 Apr 2002 14:09:16 -0000
@@ -27,6 +27,12 @@
 #include "ie_imp_StarOffice.h"
 #include "ie_imp_StarOffice_encodings.h"
 
+#include "xap_Dialog.h"
+#include "xap_Frame.h" // for password dialog
+#include "xap_Dlg_Password.h"
+#include "xap_Dialog_Id.h"
+#include "xap_DialogFactory.h"
+
 #ifdef DEBUG
 #include <errno.h>
 #endif
@@ -35,6 +41,42 @@
 #define RETURN_IF_FALSE(err) do { if (!(err)) return UT_IE_BOGUSDOCUMENT; } while (0)
 
 // ********************************************************************************
+// Password getter, taken from Word97 importer
+
+#define GetPassword() _getPassword ( getDoc()->getApp()->getLastFocussedFrame() )
+
+static UT_String _getPassword (XAP_Frame * pFrame)
+{
+  UT_String password ( "" );
+
+  if ( pFrame )
+    {
+      pFrame->raise ();
+      
+      XAP_DialogFactory * pDialogFactory
+       = (XAP_DialogFactory *)(pFrame->getDialogFactory());
+      
+      XAP_Dialog_Password * pDlg = 
+static_cast<XAP_Dialog_Password*>(pDialogFactory->requestDialog(XAP_DIALOG_ID_PASSWORD));
+      UT_ASSERT(pDlg);
+      
+      pDlg->runModal (pFrame);
+      
+      XAP_Dialog_Password::tAnswer ans = pDlg->getAnswer();
+      bool bOK = (ans == XAP_Dialog_Password::a_OK);
+      
+      if (bOK)
+       password = pDlg->getPassword ();
+      
+      UT_DEBUGMSG(("SDW: Password is %s\n", password.c_str()));
+      
+      pDialogFactory->releaseDialog(pDlg);
+    }
+
+  return password;
+}
+
+
+// ********************************************************************************
 // Sniffer
 
 static const UT_Byte sdwSignature[] = {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 
0xE1};
@@ -118,6 +160,7 @@
        RETURN_IF_FALSE(err);
        err = streamRead(stream, nTime);
        RETURN_IF_FALSE(err);
+       UT_DEBUGMSG(("SDW: nDate %lu nTime %lu\n", nDate, nTime));
 
        // Find the name of the used encoding
        for (unsigned int i = 0; i < sizeof(SOEncodings)/sizeof(SOEncodings[0]); i++) {
@@ -143,11 +186,15 @@
                // XXX to be done see sw/source/core/sw3io/sw3imp.cxx#L1070
                UT_ASSERT(UT_NOT_IMPLEMENTED);
        }
-       // XXX Check the password, see sw/source/core/sw3io/sw3imp.cxx#L2721 and 
sw/source/core/sw3io/crypter.cxx#L77
 
        if (nFileFlags & SWGF_BAD_FILE)
                return UT_IE_BOGUSDOCUMENT;
 
+       if (nFileFlags & SWGF_HAS_PASSWD)
+               cryptor = new SDWCryptor(nDate, nTime, cPasswd);
+       else
+               cryptor = NULL;
+
        return UT_OK;
 }
 
@@ -188,7 +235,7 @@
        return true;
 }
 
-bool IE_Imp_StarOffice::readByteString(MsOleStream* stream, char*& str) {
+bool IE_Imp_StarOffice::readByteString(MsOleStream* stream, char*& str, UT_uint16* 
+aLength) {
        UT_uint16 length;
        str = NULL;
        if (!streamRead(stream, length))
@@ -197,15 +244,22 @@
        if (!streamRead(stream, str, length))
                return false;
        str[length] = 0;
+       if (aLength)
+               *aLength = length;
        return true;
 }
 
 bool IE_Imp_StarOffice::readByteString(MsOleStream* stream, UT_UCSChar*& str) {
+       UT_uint16 len;
        char* rawString;
        str = NULL;
-       if (!readByteString(stream, rawString))
+       if (!readByteString(stream, rawString, &len))
                return false;
-       str = (UT_UCSChar*)UT_convert_cd(rawString, strlen(rawString) + 1, 
mDocHdr.converter, NULL, NULL);
+       // decrypt
+       if (mDocHdr.cryptor)
+               mDocHdr.cryptor->Decrypt(rawString, rawString, len);
+
+       str = (UT_UCSChar*)UT_convert_cd(rawString, len + 1, mDocHdr.converter, NULL, 
+NULL);
 #ifdef DEBUG
        if (!str) {
                UT_DEBUGMSG(("SDW: UT_convert_cd returned %i (%s)\n", errno, 
strerror(errno)));
@@ -239,6 +293,14 @@
        if ((rv = mDocHdr.load(mDocStream)) != UT_OK)
                return rv;
 
+       // Verify the password
+       if (mDocHdr.cryptor) {
+               if (!mDocHdr.cryptor->SetPassword(GetPassword().c_str())) {
+                       UT_DEBUGMSG(("SDW: Wrong password\n"));
+                       return UT_IE_PROTECTED;
+               }
+       }
+
        // do the actual reading
        char type;
        bool done = false;
@@ -299,7 +361,6 @@
                                                        UT_UCSChar* str;
                                                        if 
(!readByteString(mDocStream, str))
                                                                return 
UT_IE_BOGUSDOCUMENT;
-                                                       // TODO: Decrypt (before 
converting charset!)
                                                        UT_uint32 len = 
UT_UCS_strlen(str);
                                                        if (len)
                                                                
getDoc()->appendSpan(str, len);
@@ -309,7 +370,7 @@
 
                                                }
                                                default:
-                                                       UT_DEBUGMSG(("SDW: 
SWG_CONTENT: Skipping %lu bytes for record type '%c'\n", size2, type));
+                                                       UT_DEBUGMSG(("SDW: 
+SWG_CONTENT: Skipping %lu bytes for record type '%c' (starting at %08lX)\n", size2, 
+type, ms_ole_stream_tell(mDocStream)));
                                                        if 
(ms_ole_stream_lseek(mDocStream, size2, MsOleSeekCur) < 0)
                                                                return 
UT_IE_BOGUSDOCUMENT;
                                        }
@@ -320,7 +381,7 @@
                                done = true;
                                break;
                        default:
-                               UT_DEBUGMSG(("SDW: Skipping %lu bytes for record type 
'%c'\n", recSize, type));
+                               UT_DEBUGMSG(("SDW: Skipping %lu bytes for record type 
+'%c' (starting at %08lX)\n", recSize, type, ms_ole_stream_tell(mDocStream)));
                                // Skip the record
                                if (ms_ole_stream_lseek(mDocStream, recSize, 
MsOleSeekCur) < 0)
                                        return UT_IE_BOGUSDOCUMENT;
Index: ie_imp_StarOffice.h
===================================================================
RCS file: /cvsroot/abiword-plugins/wp/impexp/sdw/xp/ie_imp_StarOffice.h,v
retrieving revision 1.2
diff -u -r1.2 ie_imp_StarOffice.h
--- ie_imp_StarOffice.h 25 Apr 2002 12:32:47 -0000      1.2
+++ ie_imp_StarOffice.h 29 Apr 2002 14:09:16 -0000
@@ -26,6 +26,8 @@
 #include "ut_types.h"
 #include "ie_imp.h"
 
+#include "sdw_cryptor.h"
+
 class PD_Document;
 
 // The following struct definition was taken from the OpenOffice file
@@ -88,10 +90,13 @@
                UT_UCSChar* sBlockName; // name of a text module
 
                UT_iconv_t converter; // Iconv handle for converting from the doc 
charset to UCS_2_INTERNAL
+
+               SDWCryptor* cryptor; // used for decrypting the document or null if 
+not encrypted
 };
 
 // File Flags: (from sw/source/core/sw3io/sw3ids.hxx lines 65ff)
 #define SWGF_BLOCKNAME  0x0002 // Header has textmodule
+#define SWGF_HAS_PASSWD 0x0008 // Stream is password protected
 #define SWGF_HAS_PGNUMS 0x0100 // Stream has pagenumbers
 #define SWGF_BAD_FILE   0x8000 // There was an error writing the file
 
@@ -177,14 +182,17 @@
                static bool readFlagRec(MsOleStream* stream, UT_uint8& flags, 
UT_uint32* newPos = NULL);
                /*! Reads a string from the file where the first sint32 contains the 
length. If it
                 * is zero-terminated, length must include the byte for termination. 
The string will
-                * be converted to the charset given in mDocHdr.
+                * be converted to the charset given in mDocHdr. If the document is 
+encrypted, the
+                * string will be decrypted before character set conversion.
                 * \param stream The stream to read from
                 * \param str Reference to pointer to UT_UCSChar, where the string is 
stored.
                 * Must be free'd. Is NULL if the function fails.
                 * \return true on success, false on failure */
-               bool readByteString(MsOleStream* stream, UT_UCSChar*& str); 
-               /*! As above, but no charset conversion is done. str must be 
delete[]'d, not free'd! */
-               bool readByteString(MsOleStream* stream, char*& str);
+               bool readByteString(MsOleStream* stream, UT_UCSChar*& str);
+               /*! As above, but no charset conversion is done. str must be 
+delete[]'d, not free'd! 
+                * only difference: aLength, if non-null, contains the length of the 
+string in bytes.
+                * Also, this function does not decrypt the string. */
+               bool readByteString(MsOleStream* stream, char*& str, UT_uint16* 
+aLength = NULL);
                /*! Finds the version number, given a version string.
                 * \return One of SOFFICE_FILEFORMAT_31, SOFFICE_FILEFORMAT_40 and
                 *         SOFFICE_FILEFORMAT_50 */
/* Abiword
 * Copyright (C) 2001 Christian Biesinger <[EMAIL PROTECTED]>
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program 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 General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  
 * 02111-1307, USA.
 */

/** @file
 * implementation of staroffice decryption routines, very much inspired by
 * openoffice's sw/source/core/sw3io/sw3imp.cxx#L2721 and 
sw/source/core/sw3io/crypter.cxx#L77 */

#include "sdw_cryptor.h"
#include "ut_debugmsg.h"

// random values for encrypting the password
static const UT_uint8 gEncode[] =
{ 0xab, 0x9e, 0x43, 0x05, 0x38, 0x12, 0x4d, 0x44,
  0xd5, 0x7e, 0xe3, 0x84, 0x98, 0x23, 0x3f, 0xba };

SDWCryptor::SDWCryptor(UT_uint32 aDate, UT_uint32 aTime, const UT_uint8* aFilePass)
: mDate(aDate), mTime(aTime) {
        if (aFilePass)
                memcpy(mFilePass, aFilePass, maxPWLen);
        else
                memset(mFilePass, 0, maxPWLen);
}

SDWCryptor::~SDWCryptor() {
}

bool SDWCryptor::SetPassword(const char* aPassword) {
        // Set the new password
        char pw[maxPWLen];
        strncpy(pw, aPassword, maxPWLen);
        size_t len = strlen(aPassword);
        // fill with spaces. only executed if len < maxPWLen
        for (int i = len; i < maxPWLen; i++)
                pw[i] = ' ';

        // the password needs to be encrypted
        memcpy(mPassword, gEncode, maxPWLen);
        Encrypt(pw, mPassword, maxPWLen);

        // Check password if we have valid date and/or time
        if (mDate || mTime) {
                char testString[17];
                snprintf(testString, sizeof(testString), "%08lx%08lx", mDate, mTime);
                Encrypt(testString, testString, 16);
                if (memcmp(testString, mFilePass, 16) != 0) {
                        return false; // wrong password
                }
        }
        return true;
}

// almost literally taken from openoffice code (crypter.cxx)
void SDWCryptor::Decrypt(const char* aEncrypted, char* aBuffer, UT_uint32 aLen) const {
        size_t nCryptPtr = 0;
        UT_uint8 cBuf[maxPWLen];
        memcpy(cBuf, mPassword, maxPWLen);
        UT_uint8* p = cBuf;

        if (!aLen)
                aLen = strlen(aEncrypted);

        UT_DEBUGMSG(("SDW: CRYPTOR: aLen=%lu\n", aLen));
        while (aLen--) {
                *aBuffer++ = *aEncrypted++ ^ ( *p ^ (UT_uint8) ( cBuf[ 0 ] * nCryptPtr 
) );
                *p += ( nCryptPtr < (maxPWLen-1) ) ? *(p+1) : cBuf[ 0 ];
                if( !*p ) *p += 1;
                p++;
                if( ++nCryptPtr >= maxPWLen ) {
                        nCryptPtr = 0;
                        p = cBuf;
                }
        }
}
/* Abiword
 * Copyright (C) 2001 Christian Biesinger <[EMAIL PROTECTED]>
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program 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 General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  
 * 02111-1307, USA.
 */

/** @file
 * Contains decryption routines for StarOffice files */

#include <string.h> // for memcpy
#include "ut_types.h"
#include "ut_string_class.h"

/** Decryptor for .sdw files */
class SDWCryptor {
        public:
                /** Maximum length of the password */
                enum { maxPWLen = 16 };
                /** Intializes the cryptor. The arguments are used to verify
                 * that the password is correct. A date and time of zero tells
                 * the cryptor to not use these values.
                 * If you give aDate and aTime, you really should also give aFilePass 
- 
                 * results might not be what you expect otherwise
                 * @param aDate The date given in the file header
                 * @param aTime Time from file header. */
                SDWCryptor(UT_uint32 aDate = 0, UT_uint32 aTime = 0, const UT_uint8* 
aFilePass = NULL);
                ~SDWCryptor();
                /** Sets date and time for verifying the password */
                void SetDateTime(UT_uint32 aDate, UT_uint32 aTime) { mDate = aDate; 
mTime = aTime; }
                /** Sets the password that will be used for decrypting. Even if the 
password
                 * is invalid, the current password will be modified.
                 * @param aPassword The password to use
                 * @param aFilePass The password given in the file header to
                 * check if the given password is correct or NULL if no check should be
                 * performed.
                 * @return true on success (also if aFilePass is NULL),
                 *         false on failure (e.g. invalid password) */
                bool SetPassword(const char* aPassword);

                /** Decrypts a given string.
                 * @param aEncrypted The string to decrypt
                 * @param aBuffer Decrypted string will be put here. Needs to be at 
least
                 * strlen(aEncrypted) bytes large. Can be the same as aEncrypted.
                 * @param aLen Length of the string to be encrypted, if 0 or not given
                 * strlen(aEncrypted) is used. */
                void Decrypt(const char* aEncrypted, char* aBuffer, UT_uint32 aLen = 
0) const;

                /** Encrypts a string. Works the same as SDWCryptor::Decrypt */
                void Encrypt(const char* aDecrypted, char* aBuffer, UT_uint32 aLen = 
0) const { Decrypt(aDecrypted, aBuffer, aLen); }
        protected:
                UT_uint32 mDate;
                UT_uint32 mTime;
                char mPassword[maxPWLen];
                UT_uint8 mFilePass[maxPWLen];
};


Attachment: msg24078/pgp00000.pgp
Description: PGP signature

Reply via email to