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