summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2016-08-30 13:42:20 +0200
committerJan-Marek Glogowski <glogow@fbihome.de>2016-09-23 23:25:49 +0200
commit3c4dfb872d50413b605fb846dfdebd28947026e8 (patch)
treed8c53251254a416528ecdf6babb30a0bd7d71da4
parent260cd3aeea2d02507dd131ee2028c4f48f7562f8 (diff)
tdf#94987 Create directories for temp filenames
Per default a temporary file is construted from a path and a leading pattern for the filename. For mail merge the filename can be read from a database column. If the path is not existing, a temporary directory is created. Normally the temp file function would fail, if the filename contains a slash and the sub-directory of the filename doesn't exists as a subdirectory of path. To implement tdf#94987, this adds an option to the temp file class to create the parent directories of the filename pattern. Change-Id: I02bf34294dac85598ee153d8cfcf00bc5d7775af
-rw-r--r--include/unotools/tempfile.hxx5
-rw-r--r--sw/qa/extras/mailmerge/data/10-testing-addresses.odsbin12130 -> 14816 bytes
-rw-r--r--sw/qa/extras/mailmerge/mailmerge.cxx71
-rw-r--r--sw/source/uibase/dbui/dbmgr.cxx29
-rw-r--r--unotools/source/ucbhelper/tempfile.cxx42
5 files changed, 110 insertions, 37 deletions
diff --git a/include/unotools/tempfile.hxx b/include/unotools/tempfile.hxx
index 4b8bff801edb..edb9c9f39498 100644
--- a/include/unotools/tempfile.hxx
+++ b/include/unotools/tempfile.hxx
@@ -66,8 +66,11 @@ public:
rLeadingChars="abc" means "abc0","abc1" and so on, depending on existing files in the folder ).
The extension string may be f.e. ".txt" or "", if no extension string is given, ".tmp" is used
@param _bStartWithZero If set to false names will be generated like "abc","abc0","abc1"
+ @param bCreateParentDirs If rLeadingChars contains a slash, this will create the required
+ parent directories.
*/
- TempFile( const OUString& rLeadingChars, bool _bStartWithZero=true, const OUString* pExtension=nullptr, const OUString* pParent=nullptr);
+ TempFile( const OUString& rLeadingChars, bool _bStartWithZero=true, const OUString* pExtension=nullptr,
+ const OUString* pParent=nullptr, bool bCreateParentDirs=false );
/**
TempFile will be removed from disk in dtor if EnableKillingFile(true) was called before.
diff --git a/sw/qa/extras/mailmerge/data/10-testing-addresses.ods b/sw/qa/extras/mailmerge/data/10-testing-addresses.ods
index 33b82e65a28b..6792da491733 100644
--- a/sw/qa/extras/mailmerge/data/10-testing-addresses.ods
+++ b/sw/qa/extras/mailmerge/data/10-testing-addresses.ods
Binary files differ
diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx
index 36009a179be6..bb4ec55cce75 100644
--- a/sw/qa/extras/mailmerge/mailmerge.cxx
+++ b/sw/qa/extras/mailmerge/mailmerge.cxx
@@ -70,7 +70,8 @@ public:
* The 'verify' method actually has to execute the mail merge by
* calling executeMailMerge() after modifying the job arguments.
*/
- void executeMailMergeTest(const char* filename, const char* datasource, const char* tablename, bool file, int selection)
+ void executeMailMergeTest( const char* filename, const char* datasource, const char* tablename,
+ bool file, int selection, const char* column )
{
maMMtestFilename = filename;
header();
@@ -79,8 +80,9 @@ public:
utl::TempFile aTempDir(nullptr, true);
const OUString aWorkDir = aTempDir.GetURL();
const OUString aURI( m_directories.getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(datasource) );
- OUString aDBName = registerDBsource( aURI, aWorkDir );
- initMailMergeJobAndArgs( filename, tablename, aDBName, "LOMM_", aWorkDir, file, selection );
+ const OUString aPrefix = column ? OUString::createFromAscii( column ) : "LOMM_";
+ const OUString aDBName = registerDBsource( aURI, aWorkDir );
+ initMailMergeJobAndArgs( filename, tablename, aDBName, aPrefix, aWorkDir, file, selection, column != nullptr );
verify();
finish();
@@ -130,7 +132,8 @@ public:
}
void initMailMergeJobAndArgs( const char* filename, const char* tablename, const OUString &aDBName,
- const OUString &aPrefix, const OUString &aWorkDir, bool file, int nDataSets )
+ const OUString &aPrefix, const OUString &aWorkDir, bool file, int nDataSets,
+ const bool bPrefixIsColumn )
{
uno::Reference< task::XJob > xJob( getMultiServiceFactory()->createInstance( "com.sun.star.text.MailMerge" ), uno::UNO_QUERY_THROW );
mxJob.set( xJob );
@@ -144,6 +147,9 @@ public:
args.push_back( beans::NamedValue( OUString( UNO_NAME_OUTPUT_URL ), uno::Any( aWorkDir ) ) );
args.push_back( beans::NamedValue( OUString( UNO_NAME_FILE_NAME_PREFIX ), uno::Any( aPrefix )) );
+ if (bPrefixIsColumn)
+ args.push_back( beans::NamedValue( OUString( UNO_NAME_FILE_NAME_FROM_COLUMN ), uno::Any( true ) ) );
+
if (tablename)
{
args.push_back( beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND_TYPE ), uno::Any( sdb::CommandType::TABLE ) ) );
@@ -174,6 +180,7 @@ public:
const beans::NamedValue *pArguments = mSeqMailMergeArgs.getConstArray();
bool bOk = true;
+ bool bMMFilenameFromColumn = false;
sal_Int32 nArgs = mSeqMailMergeArgs.getLength();
for (sal_Int32 i = 0; i < nArgs; ++i) {
@@ -187,6 +194,8 @@ public:
bOk &= rValue >>= mailMergeOutputPrefix;
else if (rName == UNO_NAME_OUTPUT_TYPE)
bOk &= rValue >>= mnCurOutputType;
+ else if (rName == UNO_NAME_FILE_NAME_FROM_COLUMN)
+ bOk &= rValue >>= bMMFilenameFromColumn;
}
CPPUNIT_ASSERT(bOk);
@@ -205,7 +214,8 @@ public:
else
{
CPPUNIT_ASSERT(res == true);
- loadMailMergeDocument( 0 );
+ if( !bMMFilenameFromColumn )
+ loadMailMergeDocument( 0 );
}
}
@@ -221,26 +231,31 @@ public:
return parseExportInternal( mailMergeOutputURL + "/" + 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(mailMergeOutputURL + "/" + 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 = mailMergeOutputPrefix + 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;
@@ -254,7 +269,7 @@ protected:
const char* maMMtestFilename;
};
-#define DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, file, BaseClass, selection) \
+#define DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, file, BaseClass, selection, column) \
class TestName : public BaseClass { \
protected: \
virtual OUString getTestName() override { return OUString(#TestName); } \
@@ -264,7 +279,7 @@ protected:
CPPUNIT_TEST_SUITE_END(); \
\
void MailMerge() { \
- executeMailMergeTest(filename, datasource, tablename, file, selection); \
+ executeMailMergeTest(filename, datasource, tablename, file, selection, column); \
} \
void verify() override; \
}; \
@@ -273,14 +288,17 @@ protected:
// Will generate the resulting document in mxMMDocument.
#define DECLARE_SHELL_MAILMERGE_TEST(TestName, filename, datasource, tablename) \
- DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, false, MMTest, 0)
+ DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, false, MMTest, 0, nullptr)
// Will generate documents as files, use loadMailMergeDocument().
#define DECLARE_FILE_MAILMERGE_TEST(TestName, filename, datasource, tablename) \
- DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, true, MMTest, 0)
+ DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, true, MMTest, 0, nullptr)
#define DECLARE_SHELL_MAILMERGE_TEST_SELECTION(TestName, filename, datasource, tablename, selection) \
- DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, false, MMTest, selection)
+ DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, false, MMTest, selection, nullptr)
+
+#define DECLARE_FILE_MAILMERGE_TEST_COLUMN(TestName, filename, datasource, tablename, column) \
+ DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, true, MMTest, 0, column)
int MMTest::documentStartPageNumber( int document ) const
{ // See documentStartPageNumber() .
@@ -568,5 +586,22 @@ DECLARE_SHELL_MAILMERGE_TEST(test_sections_first_last, "sections_first_last.odt"
}
}
+DECLARE_FILE_MAILMERGE_TEST_COLUMN(testDirMailMerge, "simple-mail-merge.odt", "10-testing-addresses.ods", "testing-addresses", "Filename")
+{
+ executeMailMerge();
+ for( int doc = 1;
+ doc <= 10;
+ ++doc )
+ {
+ OUString filename = "sub/lastname" + OUString::number( doc )
+ + " firstname" + OUString::number( doc ) + ".odt";
+ loadMailMergeDocument( filename );
+ CPPUNIT_ASSERT_EQUAL( 1, getPages());
+ CPPUNIT_ASSERT_EQUAL( OUString( "Fixed text." ), getRun( getParagraph( 1 ), 1 )->getString());
+ CPPUNIT_ASSERT_EQUAL( OUString( "lastname" + OUString::number( doc )), getRun( getParagraph( 2 ), 1 )->getString());
+ CPPUNIT_ASSERT_EQUAL( OUString( "Another fixed text." ), getRun( getParagraph( 3 ), 1 )->getString());
+ }
+}
+
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 ff90ea629dba..86e2d7e171ca 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1314,7 +1314,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
{
nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
- OUString sPath = rMergeDescriptor.sPath;
OUString sColumnData;
// Read the indicated data column, which should contain a valid mail
@@ -1322,28 +1321,32 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
if( bMT_EMAIL || bColumnName )
{
sColumnData = GetDBField( xColumnProp, aColumnDBFormat );
- if( !bMT_EMAIL )
- {
- if (sColumnData.isEmpty())
- sColumnData = "_";
- sPath += sColumnData;
- }
}
// create a new temporary file name - only done once in case of bCreateSingleFile
if( bNeedsTempFiles && ( !bWorkDocInitialized || !bCreateSingleFile ))
{
- INetURLObject aEntry(sPath);
+ OUString sPath = rMergeDescriptor.sPath;
OUString sLeading;
+
//#i97667# if the name is from a database field then it will be used _as is_
- if( !sColumnData.isEmpty() )
- sLeading = sColumnData;
+ if( bColumnName && !bMT_EMAIL )
+ {
+ if (!sColumnData.isEmpty())
+ sLeading = sColumnData;
+ else
+ sLeading = "_";
+ }
else
+ {
+ INetURLObject aEntry( sPath );
sLeading = aEntry.GetBase();
- aEntry.removeSegment();
- sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE );
+ aEntry.removeSegment();
+ sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE );
+ }
+
OUString sExt(comphelper::string::stripStart(pStoreToFilter->GetDefaultExtension(), '*'));
- aTempFile.reset( new utl::TempFile(sLeading, sColumnData.isEmpty(), &sExt, &sPath) );
+ aTempFile.reset( new utl::TempFile(sLeading, sColumnData.isEmpty(), &sExt, &sPath, true) );
if( !aTempFile->IsValid() )
{
ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED );
diff --git a/unotools/source/ucbhelper/tempfile.cxx b/unotools/source/ucbhelper/tempfile.cxx
index dcc4068b2ac3..fa2cbf567436 100644
--- a/unotools/source/ucbhelper/tempfile.cxx
+++ b/unotools/source/ucbhelper/tempfile.cxx
@@ -225,11 +225,39 @@ private:
sal_uInt32 UniqueTokens::globalValue = SAL_MAX_UINT32;
+namespace
+{
+ class TempDirCreatedObserver : public DirectoryCreationObserver
+ {
+ public:
+ virtual void DirectoryCreated(const rtl::OUString& aDirectoryUrl) override
+ {
+ File::setAttributes( aDirectoryUrl, osl_File_Attribute_OwnRead |
+ osl_File_Attribute_OwnWrite | osl_File_Attribute_OwnExe );
+ };
+ };
+};
+
OUString lcl_createName(
const OUString& rLeadingChars, Tokens & tokens, const OUString* pExtension,
- const OUString* pParent, bool bDirectory, bool bKeep, bool bLock)
+ const OUString* pParent, bool bDirectory, bool bKeep, bool bLock,
+ bool bCreateParentDirs )
{
- OUString aName = ConstructTempDir_Impl( pParent ) + rLeadingChars;
+ OUString aName = ConstructTempDir_Impl( pParent );
+ if ( bCreateParentDirs )
+ {
+ sal_Int32 nOffset = rLeadingChars.lastIndexOf("/");
+ if (-1 != nOffset)
+ {
+ OUString aDirName = aName + OUString( rLeadingChars.getStr(), nOffset );
+ TempDirCreatedObserver observer;
+ FileBase::RC err = Directory::createPath( aDirName, &observer );
+ if ( err != FileBase::E_None && err != FileBase::E_EXIST )
+ return OUString();
+ }
+ }
+ aName += rLeadingChars;
+
OUString token;
while (tokens.next(&token))
{
@@ -306,7 +334,8 @@ OUString CreateTempName_Impl( const OUString* pParent, bool bKeep, bool bDir = t
aEyeCatcher += aPidString;
#endif
UniqueTokens t;
- return lcl_createName(aEyeCatcher, t, nullptr, pParent, bDir, bKeep, false);
+ return lcl_createName( aEyeCatcher, t, nullptr, pParent, bDir, bKeep,
+ false, false);
}
OUString TempFile::CreateTempName()
@@ -328,13 +357,16 @@ TempFile::TempFile( const OUString* pParent, bool bDirectory )
aName = CreateTempName_Impl( pParent, true, bDirectory );
}
-TempFile::TempFile( const OUString& rLeadingChars, bool _bStartWithZero, const OUString* pExtension, const OUString* pParent)
+TempFile::TempFile( const OUString& rLeadingChars, bool _bStartWithZero,
+ const OUString* pExtension, const OUString* pParent,
+ bool bCreateParentDirs )
: pStream( nullptr )
, bIsDirectory( false )
, bKillingFileEnabled( false )
{
SequentialTokens t(_bStartWithZero);
- aName = lcl_createName(rLeadingChars, t, pExtension, pParent, false/*bDirectory*/, true, true);
+ aName = lcl_createName( rLeadingChars, t, pExtension, pParent, false,
+ true, true, bCreateParentDirs );
}
TempFile::~TempFile()