diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2016-10-03 21:51:56 +0200 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2016-12-07 08:56:25 +0000 |
commit | 6c2dae8259bf666d906b4d0c1ccd64aa14c6500c (patch) | |
tree | 9dc1239373fec7232ab6ccf535d4ae0693b172bf | |
parent | 21be787405b840906233530702165bda3da96fc1 (diff) |
tdf#102010 Never overwrite MM files via UNO
Fixes the regression introduced by
commit e637b6743a506ef74c93ccbe15ab6642f3baa34f
This commit removed the crazy bSubjectIsFilename handling,
where I didn't understood the case of bSubjectIsFilename
and a user supplied prefix.
Mail merge to files never overwrites an existing document,
but there is the special case, when a user selects a target
filename in the MM dialog for single file MM.
Should be fixed by a successive commmit, reverting this and
removing an existing file before starting the MM job.
(cherry picked from commit bbf246e40c7814bfc4038d456d388d1f90048287)
Reviewed-on: https://gerrit.libreoffice.org/31207
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
(cherry picked from commit 5b4b60b2d81452c79ece99c51f63199b7dcf4b1d)
This commit also includes:
MM allow easier manipulation of MM test arguments
Keep the beans::NamedValue vector around and convert it to a
uno::Sequence just before executing the mail merge job.
(cherry picked from commit 660159a68acd54a8f213920457c1aeed79cffea5)
Reviewed-on: https://gerrit.libreoffice.org/31206
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
(cherry picked from commit fda376a5ebf765789cfa4cb81ee04e0f1dafe44b)
Change-Id: Idda487023e6984de9c1e701fc088a6b7f92e9847
Reviewed-on: https://gerrit.libreoffice.org/31636
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | sw/CppunitTest_sw_mailmerge.mk | 1 | ||||
-rw-r--r-- | sw/inc/dbmgr.hxx | 19 | ||||
-rw-r--r-- | sw/qa/extras/mailmerge/mailmerge.cxx | 109 | ||||
-rw-r--r-- | sw/source/uibase/dbui/dbmgr.cxx | 19 | ||||
-rw-r--r-- | sw/source/uibase/uno/unomailmerge.cxx | 2 |
5 files changed, 107 insertions, 43 deletions
diff --git a/sw/CppunitTest_sw_mailmerge.mk b/sw/CppunitTest_sw_mailmerge.mk index d948b892c761..5796fc446ced 100644 --- a/sw/CppunitTest_sw_mailmerge.mk +++ b/sw/CppunitTest_sw_mailmerge.mk @@ -21,6 +21,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_mailmerge, \ sfx \ sw \ test \ + tl \ unotest \ utl \ )) diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx index 442d0e1dfeb7..d3ef3af5ea45 100644 --- a/sw/inc/dbmgr.hxx +++ b/sw/inc/dbmgr.hxx @@ -162,7 +162,23 @@ struct SwMergeDescriptor * @defgroup file Mail merge as File settings * @addtogroup file * @{ */ - OUString sPath; + + /** + * Basename incl. the path for the generated files. + * + * The final filename will be created by concating a number to prevent + * overwriting an existing file and the extension based on the filter + * settings. + */ + OUString sPrefix; + /** + * Use the sPrefix as the target filename also overwriting an existing + * target file. + * + * Just used for the internal mail merge dialogs as mail merge never + * overwrites existing files (see SwDBManager::ExecuteFormLetter). + */ + bool bPrefixIsFilename; /** @} */ /** @@ -206,6 +222,7 @@ struct SwMergeDescriptor rSh(rShell), rDescriptor(rDesc), bCreateSingleFile( false ), + bPrefixIsFilename( false ), bSendAsHTML( true ), bSendAsAttachment( false ), bPrintAsync( false ), diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx index 8e13aef44069..ed290c2be74d 100644 --- a/sw/qa/extras/mailmerge/mailmerge.cxx +++ b/sw/qa/extras/mailmerge/mailmerge.cxx @@ -22,6 +22,8 @@ #include <com/sun/star/sdb/XDocumentDataSource.hpp> #include <com/sun/star/text/TextContentAnchorType.hpp> +#include <tools/urlobj.hxx> + #include <wrtsh.hxx> #include <ndtxt.hxx> #include <swdtflvr.hxx> @@ -111,31 +113,31 @@ public: uno::Reference< task::XJob > xJob( getMultiServiceFactory()->createInstance( "com.sun.star.text.MailMerge" ), uno::UNO_QUERY_THROW ); mxJob.set( xJob ); - int seq_id = 5; - if (tablename) seq_id += 2; - mSeqMailMergeArgs.realloc( seq_id ); - - seq_id = 0; - mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_OUTPUT_TYPE ), uno::Any( file ? text::MailMergeType::FILE : text::MailMergeType::SHELL ) ); - mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DOCUMENT_URL ), uno::Any( - ( OUString(m_directories.getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(filename)) ) ) ); - mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DATA_SOURCE_NAME ), uno::Any( aDBName ) ); - mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_OUTPUT_URL ), uno::Any( aWorkDir ) ); - mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_FILE_NAME_PREFIX ), uno::Any( aPrefix )); + mMMargs.reserve( 15 ); + + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_OUTPUT_TYPE ), uno::Any( file ? text::MailMergeType::FILE : text::MailMergeType::SHELL ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_DOCUMENT_URL ), uno::Any( + ( OUString( m_directories.getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(filename)) ) ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_DATA_SOURCE_NAME ), uno::Any( aDBName ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_OUTPUT_URL ), uno::Any( aWorkDir ) ) ); + if (file) + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_FILE_NAME_PREFIX ), uno::Any( aPrefix )) ); + if (tablename) { - mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND_TYPE ), uno::Any( sdb::CommandType::TABLE ) ); - mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND ), uno::Any( OUString::createFromAscii(tablename) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND_TYPE ), uno::Any( sdb::CommandType::TABLE ) ) ); + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND ), uno::Any( OUString::createFromAscii(tablename) ) ) ); } } - void executeMailMerge() + void executeMailMerge( bool bDontLoadResult = false ) { - uno::Any res = mxJob->execute( mSeqMailMergeArgs ); + uno::Sequence< beans::NamedValue > aSeqMailMergeArgs = comphelper::containerToSequence( mMMargs ); + uno::Any res = mxJob->execute( aSeqMailMergeArgs ); - const beans::NamedValue *pArguments = mSeqMailMergeArgs.getConstArray(); + const beans::NamedValue *pArguments = aSeqMailMergeArgs.getConstArray(); bool bOk = true; - sal_Int32 nArgs = mSeqMailMergeArgs.getLength(); + sal_Int32 nArgs = aSeqMailMergeArgs.getLength(); for (sal_Int32 i = 0; i < nArgs; ++i) { const OUString &rName = pArguments[i].Name; @@ -143,11 +145,13 @@ public: // all error checking was already done by the MM job execution if (rName == UNO_NAME_OUTPUT_URL) - bOk &= rValue >>= mailMergeOutputURL; + bOk &= rValue >>= msMailMergeOutputURL; else if (rName == UNO_NAME_FILE_NAME_PREFIX) - bOk &= rValue >>= mailMergeOutputPrefix; + bOk &= rValue >>= msMailMergeOutputPrefix; else if (rName == UNO_NAME_OUTPUT_TYPE) bOk &= rValue >>= mnCurOutputType; + else if (rName == UNO_NAME_DOCUMENT_URL) + bOk &= rValue >>= msMailMergeDocumentURL; } CPPUNIT_ASSERT(bOk); @@ -160,7 +164,8 @@ public: else { CPPUNIT_ASSERT(res == true); - loadMailMergeDocument( 0 ); + if( !bDontLoadResult ) + loadMailMergeDocument( 0 ); } } @@ -172,38 +177,54 @@ public: if (mnCurOutputType != text::MailMergeType::FILE) return nullptr; - OUString name = mailMergeOutputPrefix + OUString::number( 0 ) + ".odt"; - return parseExportInternal( mailMergeOutputURL + "/" + name, rStreamName ); + OUString name = msMailMergeOutputPrefix + OUString::number( 0 ) + ".odt"; + return parseExportInternal( msMailMergeOutputURL + "/" + name, rStreamName ); } - /** - Loads number-th document from mail merge. Requires file output from mail merge. - */ - void loadMailMergeDocument( int number ) + void loadMailMergeDocument( const OUString &filename ) { assert( mnCurOutputType == text::MailMergeType::FILE ); if (mxComponent.is()) mxComponent->dispose(); - OUString name = mailMergeOutputPrefix + OUString::number( number ) + ".odt"; // Output name early, so in the case of a hang, the name of the hanging input file is visible. - std::cout << name << ","; + std::cout << filename << ","; mnStartTime = osl_getGlobalTimer(); - mxComponent = loadFromDesktop(mailMergeOutputURL + "/" + name, "com.sun.star.text.TextDocument"); + mxComponent = loadFromDesktop(msMailMergeOutputURL + "/" + filename, "com.sun.star.text.TextDocument"); CPPUNIT_ASSERT( mxComponent.is()); - OString name2 = OUStringToOString( name, RTL_TEXTENCODING_UTF8 ); + OString name2 = OUStringToOString( filename, RTL_TEXTENCODING_UTF8 ); discardDumpedLayout(); if (mustCalcLayoutOf(name2.getStr())) calcLayout(); } + /** + Loads number-th document from mail merge. Requires file output from mail merge. + */ + void loadMailMergeDocument( int number ) + { + OUString name; + if (!msMailMergeOutputPrefix.isEmpty()) + name = msMailMergeOutputPrefix; + else + { + INetURLObject aURLObj; + aURLObj.SetSmartProtocol( INetProtocol::File ); + aURLObj.SetSmartURL( msMailMergeDocumentURL ); + name = aURLObj.GetBase(); + } + name += OUString::number( number ) + ".odt"; + loadMailMergeDocument( name ); + } + protected: // Returns page number of the first page of a MM document inside the large MM document (used in the SHELL case). int documentStartPageNumber( int document ) const; uno::Reference< css::task::XJob > mxJob; - uno::Sequence< beans::NamedValue > mSeqMailMergeArgs; - OUString mailMergeOutputURL; - OUString mailMergeOutputPrefix; + std::vector< beans::NamedValue > mMMargs; + OUString msMailMergeDocumentURL; + OUString msMailMergeOutputURL; + OUString msMailMergeOutputPrefix; sal_Int16 mnCurOutputType; uno::Reference< lang::XComponent > mxMMComponent; }; @@ -463,5 +484,27 @@ DECLARE_SHELL_MAILMERGE_TEST(testTdf92623, "tdf92623.odt", "10-testing-addresses CPPUNIT_ASSERT_EQUAL(sal_Int32(10), countFieldMarks); } +DECLARE_FILE_MAILMERGE_TEST(testTdf102010, "empty.odt", "10-testing-addresses.ods", "testing-addresses") +{ + // Create "correct" automatic filename for non-user-supplied-prefix + for (auto aNamedValueIter = mMMargs.begin(); aNamedValueIter != mMMargs.end();) + { + if ( aNamedValueIter->Name == UNO_NAME_FILE_NAME_PREFIX ) + aNamedValueIter = mMMargs.erase( aNamedValueIter ); + else + { + std::cout << aNamedValueIter->Name << ": " << aNamedValueIter->Value << std::endl; + ++aNamedValueIter; + } + } + mMMargs.push_back( beans::NamedValue( OUString( UNO_NAME_SAVE_AS_SINGLE_FILE ), uno::Any( true ) ) ); + + // Generate correct mail merge result filename + executeMailMerge(); + // Don't overwrite previous result + executeMailMerge( true ); + loadMailMergeDocument( 1 ); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index 7b4c2f698525..fe9e87f727bb 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -1100,11 +1100,13 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, bool bCheckSingleFile_ = rMergeDescriptor.bCreateSingleFile; if( bMT_EMAIL ) { + assert( !rMergeDescriptor.bPrefixIsFilename ); assert( bMT_EMAIL && !bCheckSingleFile_ ); bCheckSingleFile_ = false; } else if( bMT_SHELL || bMT_PRINTER ) { + assert( !rMergeDescriptor.bPrefixIsFilename ); assert( (bMT_SHELL || bMT_PRINTER) && bCheckSingleFile_ ); bCheckSingleFile_ = true; } @@ -1292,7 +1294,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, { nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0; - OUString sPath = rMergeDescriptor.sPath; + OUString sPrefix = rMergeDescriptor.sPrefix; OUString sColumnData; // Read the indicated data column, which should contain a valid mail @@ -1304,14 +1306,14 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, { if (sColumnData.isEmpty()) sColumnData = "_"; - sPath += sColumnData; + sPrefix += sColumnData; } } // create a new temporary file name - only done once in case of bCreateSingleFile if( bNeedsTempFiles && ( !bWorkDocInitialized || !bCreateSingleFile )) { - INetURLObject aEntry(sPath); + INetURLObject aEntry(sPrefix); OUString sLeading; //#i97667# if the name is from a database field then it will be used _as is_ if( !sColumnData.isEmpty() ) @@ -1319,9 +1321,9 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, else sLeading = aEntry.GetBase(); aEntry.removeSegment(); - sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE ); + sPrefix = aEntry.GetMainURL( INetURLObject::NO_DECODE ); OUString sExt(comphelper::string::stripStart(pStoreToFilter->GetDefaultExtension(), '*')); - aTempFile.reset( new utl::TempFile(sLeading, true, &sExt, &sPath) ); + aTempFile.reset( new utl::TempFile(sLeading, true, &sExt, &sPrefix) ); if( !aTempFile->IsValid() ) { ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED ); @@ -1538,11 +1540,11 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, // save merged document assert( aTempFile.get() ); INetURLObject aTempFileURL; - if( rMergeDescriptor.sPath.isEmpty() ) + if( rMergeDescriptor.sPrefix.isEmpty() || !rMergeDescriptor.bPrefixIsFilename ) aTempFileURL.SetURL( aTempFile->GetURL() ); else { - aTempFileURL.SetURL( rMergeDescriptor.sPath ); + aTempFileURL.SetURL( rMergeDescriptor.sPrefix ); // remove the unneeded temporary file aTempFile->EnableKillingFile(); } @@ -2840,7 +2842,8 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh, SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), rSh, aDescriptor ); aMergeDesc.sSaveToFilter = pImpl->pMergeDialog->GetSaveFilter(); aMergeDesc.bCreateSingleFile = pImpl->pMergeDialog->IsSaveSingleDoc(); - aMergeDesc.sPath = pImpl->pMergeDialog->GetTargetURL(); + aMergeDesc.bPrefixIsFilename = aMergeDesc.bCreateSingleFile; + aMergeDesc.sPrefix = pImpl->pMergeDialog->GetTargetURL(); if( !aMergeDesc.bCreateSingleFile && pImpl->pMergeDialog->IsGenerateFromDataBase() ) { aMergeDesc.sDBcolumn = pImpl->pMergeDialog->GetColumnName(); diff --git a/sw/source/uibase/uno/unomailmerge.cxx b/sw/source/uibase/uno/unomailmerge.cxx index 3c335f6ea779..2b18c785777b 100644 --- a/sw/source/uibase/uno/unomailmerge.cxx +++ b/sw/source/uibase/uno/unomailmerge.cxx @@ -741,7 +741,7 @@ uno::Any SAL_CALL SwXMailMerge::execute( aPath += aCurFileNamePrefix; } - aMergeDesc.sPath = aPath; + aMergeDesc.sPrefix = aPath; aMergeDesc.sSaveToFilter = m_sSaveFilter; aMergeDesc.sSaveToFilterOptions = m_sSaveFilterOptions; aMergeDesc.aSaveToFilterData = m_aSaveFilterData; |