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];
};
msg24078/pgp00000.pgp
Description: PGP signature
