From 2fc88c27a7c329753f2c58ec5ee1caa3678200ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Mon, 24 Feb 2014 15:27:36 +0000 Subject: [PATCH] Related: rhbz#1065807 rework #i66157# for multiple writable template dirs if there are multiple user-level template dirs then we should be able to remove/rename content in all of them, not just the default writable target. The target scenario here is to default to ~/Templates when it exists as the template dir, but to retain ~/.config/libreoffice/user/template in the dir for any pre-existing templates and to treat both as equivalent in terms of removing their content etc. i#66157# wanted to avoid remove extensions templates and other internal ones, so rework that logic to instead just be hands off internal templates and allow modification of the remainder Change-Id: I56afe991d4297ba692e914ae95ea02d68553f60a --- sfx2/source/doc/doctemplates.cxx | 82 ++++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 15 deletions(-) diff --git a/sfx2/source/doc/doctemplates.cxx b/sfx2/source/doc/doctemplates.cxx index ff07ef3..fe43a40 100644 --- a/sfx2/source/doc/doctemplates.cxx +++ b/sfx2/source/doc/doctemplates.cxx @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -180,6 +181,7 @@ class SfxDocTplService_Impl ::osl::Mutex maMutex; Sequence< OUString > maTemplateDirs; + Sequence< OUString > maInternalTemplateDirs; OUString maRootURL; NameList_Impl maNames; Locale maLocale; @@ -264,8 +266,16 @@ class SfxDocTplService_Impl void updateData( DocTemplates_EntryData_Impl *pData ); + //See: #i66157# and rhbz#1065807 + //return which template dir the rURL is a subpath of + OUString findParentTemplateDir(const OUString& rURL) const; + + //See: #i66157# and rhbz#1065807 + //return true if rURL is a path (or subpath of) a dir which is not a user path + //which implies neither it or its contents can be removed + bool isInternalTemplateDir(const OUString& rURL) const; public: - SfxDocTplService_Impl( const uno::Reference< XComponentContext > & xContext ); + SfxDocTplService_Impl( const uno::Reference< XComponentContext > & xContext ); ~SfxDocTplService_Impl(); sal_Bool init() { if ( !mbIsInitialized ) init_Impl(); return mbIsInitialized; } @@ -545,7 +555,7 @@ void SfxDocTplService_Impl::getDirList() // TODO/LATER: let use service, register listener INetURLObject aURL; OUString aDirs = SvtPathOptions().GetTemplatePath(); - sal_uInt16 nCount = comphelper::string::getTokenCount(aDirs, C_DELIM); + sal_Int32 nCount = comphelper::string::getTokenCount(aDirs, C_DELIM); maTemplateDirs = Sequence< OUString >( nCount ); @@ -553,7 +563,7 @@ void SfxDocTplService_Impl::getDirList() const OUString aPrefix( "vnd.sun.star.expand:" ); - for ( sal_uInt16 i=0; i xPathSettings = + css::util::PathSettings::create( mxContext ); + + // load internal paths + OUString sProp( "Template_internal" ); + Any aAny = xPathSettings->getPropertyValue( sProp ); + aAny >>= maInternalTemplateDirs; + + nCount = maInternalTemplateDirs.getLength(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + //expand vnd.sun.star.expand: and remove "..." from them + //to normalize into the expected url patterns + maRelocator.makeRelocatableURL(maInternalTemplateDirs[i]); + maRelocator.makeAbsoluteURL(maInternalTemplateDirs[i]); + } + // Store the template dir list setProperty( maRootContent, aPropName, aValue ); } @@ -1547,13 +1574,16 @@ sal_Bool SfxDocTplService_Impl::removeGroup( const OUString& rGroupName ) if ( !maTemplateDirs.getLength() ) return sal_False; - OUString aGeneralTempPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ]; // check that the fs location is in writeble folder and this is not a "My templates" folder INetURLObject aGroupParentFolder( aGroupTargetURL ); - if ( !aGroupParentFolder.removeSegment() - || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath, - aGroupParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) ) + if (!aGroupParentFolder.removeSegment()) + return sal_False; + + OUString aGeneralTempPath = findParentTemplateDir( + aGroupParentFolder.GetMainURL(INetURLObject::NO_DECODE)); + + if (aGeneralTempPath.isEmpty()) return sal_False; // now get the content of the Group @@ -1661,14 +1691,14 @@ sal_Bool SfxDocTplService_Impl::renameGroup( const OUString& rOldName, if ( !maTemplateDirs.getLength() ) return sal_False; - OUString aGeneralTempPath = maTemplateDirs[ maTemplateDirs.getLength() - 1 ]; // check that the fs location is in writeble folder and this is not a "My templates" folder INetURLObject aGroupParentFolder( aGroupTargetURL ); - if ( !aGroupParentFolder.removeSegment() - || !::utl::UCBContentHelper::IsSubPath( aGeneralTempPath, - aGroupParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) ) + if (!aGroupParentFolder.removeSegment() || + isInternalTemplateDir(aGroupParentFolder.GetMainURL(INetURLObject::NO_DECODE))) + { return sal_False; + } // check that the group can be renamed ( all the contents must be in target location ) sal_Bool bCanBeRenamed = sal_False; @@ -1770,7 +1800,7 @@ sal_Bool SfxDocTplService_Impl::storeTemplate( const OUString& rGroupName, aValue >>= aTemplateToRemoveTargetURL; if ( aGroupTargetURL.isEmpty() || !maTemplateDirs.getLength() - || (!aTemplateToRemoveTargetURL.isEmpty() && !::utl::UCBContentHelper::IsSubPath( maTemplateDirs[ maTemplateDirs.getLength() - 1 ], aTemplateToRemoveTargetURL )) ) + || (!aTemplateToRemoveTargetURL.isEmpty() && isInternalTemplateDir(aTemplateToRemoveTargetURL)) ) return sal_False; // it is not allowed to remove the template } @@ -1909,6 +1939,30 @@ sal_Bool SfxDocTplService_Impl::storeTemplate( const OUString& rGroupName, } } +bool SfxDocTplService_Impl::isInternalTemplateDir(const OUString& rURL) const +{ + const sal_Int32 nDirs = maInternalTemplateDirs.getLength(); + const OUString* pDirs = maInternalTemplateDirs.getConstArray(); + for (sal_Int32 i = 0; i < nDirs; ++i, ++pDirs) + { + if (::utl::UCBContentHelper::IsSubPath(*pDirs, rURL)) + return true; + } + return false; +} + +OUString SfxDocTplService_Impl::findParentTemplateDir(const OUString& rURL) const +{ + const sal_Int32 nDirs = maTemplateDirs.getLength(); + const OUString* pDirs = maTemplateDirs.getConstArray(); + for (sal_Int32 i = 0; i < nDirs; ++i, ++pDirs) + { + if (::utl::UCBContentHelper::IsSubPath(*pDirs, rURL)) + return *pDirs; + } + return OUString(); +} + //----------------------------------------------------------------------------- sal_Bool SfxDocTplService_Impl::addTemplate( const OUString& rGroupName, const OUString& rTemplateName, @@ -2032,7 +2086,6 @@ sal_Bool SfxDocTplService_Impl::addTemplate( const OUString& rGroupName, catch ( Exception& ) { return sal_False; } - // either the document has title and it is the same as requested, or we have to set it sal_Bool bCorrectTitle = ( bDocHasTitle && aTitle.equals( rTemplateName ) ); if ( !bCorrectTitle ) @@ -2101,8 +2154,7 @@ sal_Bool SfxDocTplService_Impl::removeTemplate( const OUString& rGroupName, // delete the target template if ( !aTargetURL.isEmpty() ) { - if ( !maTemplateDirs.getLength() - || !::utl::UCBContentHelper::IsSubPath( maTemplateDirs[ maTemplateDirs.getLength() - 1 ], aTargetURL ) ) + if (isInternalTemplateDir(aTargetURL)) return sal_False; removeContent( aTargetURL ); -- 1.8.5.3