From 6805be76c930312d18e732f4572b6c2611cc8e0f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
Date: Mon, 24 Feb 2014 15:27:36 +0000
Subject: [PATCH 2/4] 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 | 80 +++++++++++++++++++++++++++++++++-------
1 file changed, 66 insertions(+), 14 deletions(-)
diff --git a/sfx2/source/doc/doctemplates.cxx b/sfx2/source/doc/doctemplates.cxx
index ff07ef3..4cf76c4 100644
--- a/sfx2/source/doc/doctemplates.cxx
+++ b/sfx2/source/doc/doctemplates.cxx
@@ -55,6 +55,7 @@
#include <com/sun/star/ucb/XContentAccess.hpp>
#include <com/sun/star/frame/ModuleManager.hpp>
#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/util/PathSettings.hpp>
#include <svtools/templatefoldercache.hxx>
#include <unotools/configmgr.hxx>
@@ -181,6 +182,7 @@
::osl::Mutex maMutex;
Sequence< OUString > maTemplateDirs;
+ Sequence< OUString > maInternalTemplateDirs;
OUString maRootURL;
NameList_Impl maNames;
Locale maLocale;
@@ -265,8 +267,16 @@
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; }
@@ -574,7 +584,7 @@
// TODO/LATER: let use service, register listener
INetURLObject aURL;
String 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 );
@@ -582,7 +592,7 @@
const OUString aPrefix(
"vnd.sun.star.expand:" );
- for ( sal_uInt16 i=0; i<nCount; i++ )
+ for (sal_Int32 i = 0; i < nCount; ++i)
{
aURL.SetSmartProtocol( INET_PROT_FILE );
aURL.SetURL( aDirs.GetToken( i, C_DELIM ) );
@@ -600,6 +610,23 @@
aValue <<= maTemplateDirs;
+ css::uno::Reference< css::util::XPathSettings > 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 );
}
@@ -1575,13 +1602,16 @@
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
@@ -1689,14 +1719,14 @@
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;
@@ -1798,7 +1828,7 @@
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
}
@@ -1937,6 +1967,30 @@
}
}
+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,
@@ -2060,7 +2114,6 @@
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 )
@@ -2129,8 +2182,7 @@
// 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 );