ACS-10505 Prevent blind ssrf attacks in libre office transformations (#1167)

* ACS-10505 modifying libreoffice workdir and user's registryconfig file to block external links

* ACS-10505 modifying libreoffice workdir and user's registryconfig file to block external links

* ACS-10505 modifying libreoffice workdir and user's registryconfig file to block external links

* ACS-10505 modifying libreoffice workdir and user's registryconfig file to block external links

* ACS-10505 used a temp office manager to create a temp user profile.

* ACS-10505 libreoffice yml corrected

* ACS-10505 PMD Fixes

* ACS-10505 generating xcu file via script instead of officemanager

* ACS-10505 generating xcu file via script instead of officemanager

* ACS-10505 generating xcu file via script instead of officemanager

* ACS-10505 generating xcu file via script instead of officemanager

* ACS-10505 generating xcu file via script instead of officemanager

* ACS-10505 generating xcu file via script instead of officemanager

* ACS-10505 generating xcu file via script instead of officemanager

* ACS-10505 PMD fixes

* ACS-10505 PMD fixes

* ACS-10505 PMD fixes

* ACS-10505 registrymodifications.xcu is predefined

* ACS-10505 registrymodifications.xcu is predefined

* ACS-10505 registrymodifications.xcu is predefined in resources of libreoffice

* ACS-10505 libreoffice path corrected

* ACS-10505 header updated and test cases updated

* ACS-10505  test cases updated

* ACS-10505 removing redundent classes

* ACS-10505 removing redundent scripts

* ACS-10505 PMD Fixes

* ACS-10505 fixing review comments

* ACS-10505 fixing unit test cases

* ACS-10505 fixing unit test cases

* ACS-10505 updated md file and configurations

* ACS-10505 fixing test cases

* ACS-10505 fixing test cases for /test endpoints

* ACS-10505 fixing test cases for LibreOfficeProfileManagerTest

* ACS-10505 PMD Fixes

* Update engines/libreoffice/src/main/java/org/alfresco/transform/libreoffice/patch/LibreOfficeProfileManager.java

Co-authored-by: Damian Ujma <92095156+damianujma@users.noreply.github.com>

* ACS-10505 Logger warn fix

* ACS-10505 simplifying return statement.

* ACS-10505 simplifying return statement.

---------

Co-authored-by: Damian Ujma <92095156+damianujma@users.noreply.github.com>
This commit is contained in:
Sayan Bhattacharya
2026-01-13 11:53:05 +05:30
committed by GitHub
co-authored by Damian Ujma
parent 7ce90de3d4
commit f988401a75
12 changed files with 361 additions and 36 deletions
+32 -26
View File
@@ -5,17 +5,18 @@ In order to configure an external property it needs to be set as ENV property.
The following externalized T-engines properties are available:
## Tika
| Property | Description | Default value |
|----------|-------------|---------------|
| SERVER_PORT | T-Engine Port. | 8090 |
| HOSTNAME | T-Engine Name. | t-engine |
| ACTIVEMQ_URL | ActiveMQ URL. | nio://localhost:61616 |
| ACTIVEMQ_USER | ActiveMQ User. | admin |
| ACTIVEMQ_PASSWORD | ActiveMQ Password. | admin |
| ACTIVEMQ_URL_PARAMS | ActiveMQ connection options. | ?jms.watchTopicAdvisories=false |
| FILE_STORE_URL | T-Engine Port. | http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file |
| Property | Description | Default value |
|----------|------------------------------------------------------------------------------------------------------|---------------|
| SERVER_PORT | T-Engine Port. | 8090 |
| HOSTNAME | T-Engine Name. | t-engine |
| ACTIVEMQ_URL | ActiveMQ URL. | nio://localhost:61616 |
| ACTIVEMQ_USER | ActiveMQ User. | admin |
| ACTIVEMQ_PASSWORD | ActiveMQ Password. | admin |
| ACTIVEMQ_URL_PARAMS | ActiveMQ connection options. | ?jms.watchTopicAdvisories=false |
| FILE_STORE_URL | T-Engine Port. | http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file |
| TEST_ENDPOINT_ENABLED | Enable /Disable **/test** endpoint | false
| PDFBOX_NOTEXTRACTBOOKMARKS_DEFAULT | The default behaviour for notExtractBookmarksText when this request param is omitted from a request. | false |
| TRANSFORM_ENGINE_REQUEST_QUEUE | T-Engine queue used for receiving async requests. | org.alfresco.transform.engine.tika.acs |
| TRANSFORM_ENGINE_REQUEST_QUEUE | T-Engine queue used for receiving async requests. | org.alfresco.transform.engine.tika.acs |
## Pdf-renderer
@@ -28,6 +29,7 @@ The following externalized T-engines properties are available:
| ACTIVEMQ_PASSWORD | ActiveMQ Password. | admin |
| ACTIVEMQ_URL_PARAMS | ActiveMQ connection options. | ?jms.watchTopicAdvisories=false |
| FILE_STORE_URL | T-Engine Port. | http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file |
| TEST_ENDPOINT_ENABLED | Enable /Disable **/test** endpoint | false
| TRANSFORM_ENGINE_REQUEST_QUEUE | T-Engine queue used for async requests. | org.alfresco.transform.engine.alfresco-pdf-renderer.acs |
| PDFRENDERER_EXE | Path to Pdf-renderer EXE. | /usr/bin/alfresco-pdf-renderer |
@@ -41,27 +43,29 @@ The following externalized T-engines properties are available:
| ACTIVEMQ_PASSWORD | ActiveMQ Password. | admin |
| ACTIVEMQ_URL_PARAMS | ActiveMQ connection options. | ?jms.watchTopicAdvisories=false |
| FILE_STORE_URL | T-Engine Port. | http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file |
| TEST_ENDPOINT_ENABLED | Enable /Disable **/test** endpoint | false
| TRANSFORM_ENGINE_REQUEST_QUEUE | T-Engine queue used for async requests. | org.alfresco.transform.engine.misc.acs |
| MISC_PDFBOX_DEFAULT_FONT | Default font used by PdfBox | NotoSans-Regular |
| MISC_HTML_COLLAPSE | Html Collasping Option for HTML to TXT transformation | true |
## Libreoffice
| Property | Description | Default value |
|----------|-------------|---------------|
| SERVER_PORT | T-Engine Port | 8090 |
| HOSTNAME | T-Engine Name. | t-engine |
| ACTIVEMQ_URL | ActiveMQ URL. | nio://localhost:61616 |
| ACTIVEMQ_USER | ActiveMQ User. | admin |
| ACTIVEMQ_PASSWORD | ActiveMQ Password. | admin |
| ACTIVEMQ_URL_PARAMS | ActiveMQ connection options. | ?jms.watchTopicAdvisories=false |
| Property | Description | Default value |
|----------|-------------|--------------------------------------------------------------------------|
| SERVER_PORT | T-Engine Port | 8090 |
| HOSTNAME | T-Engine Name. | t-engine |
| ACTIVEMQ_URL | ActiveMQ URL. | nio://localhost:61616 |
| ACTIVEMQ_USER | ActiveMQ User. | admin |
| ACTIVEMQ_PASSWORD | ActiveMQ Password. | admin |
| ACTIVEMQ_URL_PARAMS | ActiveMQ connection options. | ?jms.watchTopicAdvisories=false |
| FILE_STORE_URL | T-Engine Port. | http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file |
| TRANSFORM_ENGINE_REQUEST_QUEUE | T-Engine queue used for async requests. | org.alfresco.transform.engine.libreoffice.acs |
| LIBREOFFICE_HOME | Path to LibreOffice_Home. | /opt/libreoffice7.2 |
| LIBREOFFICE_MAX_TASKS_PER_PROCESS | Number of maximum tasks per process. | 200 |
| LIBREOFFICE_TIMEOUT | Timeout value for LibreOffice `execution timeout`, `queue timeout` and `connection timeout`. | 1200000 |
| LIBREOFFICE_PORT_NUMBERS | LibreOffice port. | 8100 |
| LIBREOFFICE_TEMPLATE_PROFILE_DIR | Path to user profile. | |
| LIBREOFFICE_IS_ENABLED | Enables Libreoffice executioner. | true |
| TEST_ENDPOINT_ENABLED | Enable /Disable **/test** endpoint | false
| TRANSFORM_ENGINE_REQUEST_QUEUE | T-Engine queue used for async requests. | org.alfresco.transform.engine.libreoffice.acs |
| LIBREOFFICE_HOME | Path to LibreOffice_Home. | /opt/libreoffice7.2 |
| LIBREOFFICE_MAX_TASKS_PER_PROCESS | Number of maximum tasks per process. | 200 |
| LIBREOFFICE_TIMEOUT | Timeout value for LibreOffice `execution timeout`, `queue timeout` and `connection timeout`. | 1200000 |
| LIBREOFFICE_PORT_NUMBERS | LibreOffice port. | 8100 |
| LIBREOFFICE_TEMPLATE_PROFILE_DIR | Path to user profile. | alfresco_default |
| LIBREOFFICE_IS_ENABLED | Enables Libreoffice executioner. | true |
## Imagemagick
| Property | Description | Default value |
@@ -73,6 +77,7 @@ The following externalized T-engines properties are available:
| ACTIVEMQ_PASSWORD | ActiveMQ Password. | admin |
| ACTIVEMQ_URL_PARAMS | ActiveMQ connection options. | ?jms.watchTopicAdvisories=false |
| FILE_STORE_URL | T-Engine Port. | http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file |
| TEST_ENDPOINT_ENABLED | Enable /Disable **/test** endpoint | false
| TRANSFORM_ENGINE_REQUEST_QUEUE | T-Engine queue used for async requests. | org.alfresco.transform.engine.imagemagick.acs |
| IMAGEMAGICK_ROOT | Path to Imagemagick Root. | /usr/lib64/ImageMagick-7.0.10 |
| IMAGEMAGICK_DYN | Path to Imagemagick DYLD. | /usr/lib64/ImageMagick-7.0.10/lib |
@@ -91,6 +96,7 @@ The following externalized T-engines properties are available:
| ACTIVEMQ_PASSWORD | ActiveMQ Password. | admin |
| ACTIVEMQ_URL_PARAMS | ActiveMQ connection options. | ?jms.watchTopicAdvisories=false |
| FILE_STORE_URL | T-Engine Port. | http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file |
| TEST_ENDPOINT_ENABLED | Enable /Disable **/test** endpoint | false
| PDFBOX_NOTEXTRACTBOOKMARKS_DEFAULT | The default behaviour for notExtractBookmarksText when this request param is omitted from a request. | false |
| TRANSFORM_ENGINE_REQUEST_QUEUE | T-Engine queue used for async requests. | org.alfresco.transform.engine.aio.acs |
| PDFRENDERER_EXE | Path to Pdf-renderer EXE. | /usr/bin/alfresco-pdf-renderer |
@@ -99,7 +105,7 @@ The following externalized T-engines properties are available:
| LIBREOFFICE_MAX_TASKS_PER_PROCESS | Number of maximum tasks per process. | 200 |
| LIBREOFFICE_TIMEOUT | Timeout value for LibreOffice `execution timeout`, `queue timeout` and `connection timeout`. | 1200000 |
| LIBREOFFICE_PORT_NUMBERS | LibreOffice port. | 8100 |
| LIBREOFFICE_TEMPLATE_PROFILE_DIR | Path to user profile. | |
| LIBREOFFICE_TEMPLATE_PROFILE_DIR | Path to user profile. | alfresco_default |
| LIBREOFFICE_IS_ENABLED | Enables Libreoffice executioner. | true |
| IMAGEMAGICK_ROOT | Path to Imagemagick Root. | /usr/lib64/ImageMagick-7.0.10 |
| IMAGEMAGICK_DYN | Path to Imagemagick DYLD. | /usr/lib64/ImageMagick-7.0.10/lib |
@@ -10,7 +10,7 @@ transform:
maxTasksPerProcess: ${LIBREOFFICE_MAX_TASKS_PER_PROCESS:200}
timeout: ${LIBREOFFICE_TIMEOUT:1200000}
portNumbers: ${LIBREOFFICE_PORT_NUMBERS:8100}
templateProfileDir: ${LIBREOFFICE_TEMPLATE_PROFILE_DIR:}
templateProfileDir: ${LIBREOFFICE_TEMPLATE_PROFILE_DIR:alfresco_default}
isEnabled: ${LIBREOFFICE_IS_ENABLED:true}
imagemagick:
root: ${IMAGEMAGICK_ROOT:/usr/lib64/ImageMagick-7.1.2}
@@ -2,7 +2,7 @@
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2023 Alfresco Software Limited
* Copyright (C) 2005 - 2026 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
@@ -29,6 +29,7 @@ package org.alfresco.transform.base;
import static java.text.MessageFormat.format;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
@@ -117,6 +118,9 @@ public class TransformController
@Value("${container.behind-ingres}")
private boolean behindIngres;
@Value("${transform.endpoint.test.enable}")
private boolean enableTestEndpoint;
TransformEngine transformEngine;
private final AtomicReference<ProbeTransform> probeTransform = new AtomicReference<>();
@@ -314,6 +318,12 @@ public class TransformController
@RequestParam(value = TARGET_MIMETYPE, required = false) String targetMimetype,
@RequestParam Map<String, String> origRequestParameters)
{
if (!enableTestEndpoint)
{
throw new TransformException(FORBIDDEN, "Test endpoint is disabled");
}
// Remaps request parameters from test.html and hands them off to the normal transform endpoint.
// There are name<i> and value<i> parameters which allow dynamic names and values to be used.
Map<String, String> requestParameters = new HashMap<>();
@@ -36,6 +36,9 @@ logging:
filestore-url: ${FILE_STORE_URL:http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file}
transform:
endpoint:
test:
enable: ${TEST_ENDPOINT_ENABLED:false}
core:
version: @project.version@
engine:
@@ -52,6 +52,7 @@ public abstract class LivenessReadinessProbeTest
return transformCore.withEnv("livenessTransformEnabled", "true")
.withEnv("maxTransforms", MAX_TRANSFORMS.toString())
.withEnv("TRANSFORM_ENDPOINT_TEST_ENABLE", "true")
.withNetworkAliases(image)
.withExposedPorts(8090)
.waitingFor(Wait.forListeningPort());
@@ -2,7 +2,7 @@
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2022 - 2022 Alfresco Software Limited
* Copyright (C) 2022 - 2026 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
@@ -79,6 +79,7 @@ import ch.qos.logback.core.AppenderBase;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import org.codehaus.plexus.util.FileUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.stubbing.Answer;
@@ -139,6 +140,12 @@ public class TransformControllerTest
AbstractBaseTest.resetProbeForTesting(transformController.getProbeTransform());
}
@BeforeEach
void setUp()
{
ReflectionTestUtils.setField(transformController, "enableTestEndpoint", true);
}
@Test
public void testInitEngine() throws Exception
{
@@ -0,0 +1,181 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2026 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transform.libreoffice.patch;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
/**
* Manages LibreOffice user profile templates for transformations.
*
* @author Sayan Bhattacharya
*/
public class LibreOfficeProfileManager
{
private static final Logger LOGGER = LoggerFactory.getLogger(LibreOfficeProfileManager.class);
private static final String DEFAULT_LO_TEMPLATE_PROFILE = "libreoffice_templateProfile";
private static final String DEFAULT_TEMPLATE_MARKER = "alfresco_default";
private final String templateProfileDir;
public LibreOfficeProfileManager(String templateProfileDir)
{
this.templateProfileDir = templateProfileDir;
}
public String getEffectiveTemplateProfileDir()
{
if (DEFAULT_TEMPLATE_MARKER.equalsIgnoreCase(templateProfileDir))
{
return createDefaultTemplateProfileDirFromResource();
}
else if (StringUtils.isNotBlank(templateProfileDir))
{
LOGGER.warn("Template profile directory found. Make sure that the BlockUntrustedRefererLinks security setting is set to true in the registrymodifications.xcu file of the LibreOffice profile.");
}
else
{
LOGGER.warn("No template profile directory provided, using default settings. Untrusted referer links are allowed. " +
"It is recommended to set the template profile directory to `{}` to prevent Blind SSRF risks.", DEFAULT_TEMPLATE_MARKER);
}
return templateProfileDir;
}
private String createDefaultTemplateProfileDirFromResource()
{
try
{
String baseDir = "templateProfileDir";
Resource[] resources = loadResources("classpath:" + baseDir);
if (ArrayUtils.isEmpty(resources))
{
return null;
}
Path tempDir = Files.createTempDirectory(DEFAULT_LO_TEMPLATE_PROFILE);
for (Resource resource : resources)
{
// skip non-readable or empty resources
if (!resource.isReadable() || resource.contentLength() == 0)
{
continue;
}
String relative = resolveRelativePath(resource, baseDir);
if (StringUtils.isBlank(relative))
{
continue;
}
copyResource(resource, tempDir.resolve(relative));
}
return tempDir.toString();
}
catch (IOException e)
{
LOGGER.warn("Error creating temporary directory for LibreOffice profile. {}", e.getMessage());
return null;
}
}
private Resource[] loadResources(String classpathTemplateDir)
{
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources;
try
{
resources = resolver.getResources(classpathTemplateDir + "/**");
}
catch (Exception e)
{
LOGGER.warn("No resources found for classpath: {}.\n {}", classpathTemplateDir, e.getMessage());
return new Resource[0];
}
if (ArrayUtils.isEmpty(resources))
{
LOGGER.warn("No resources found for classpath: {}", classpathTemplateDir);
}
return resources;
}
private String resolveRelativePath(Resource resource, String baseDir)
{
try
{
String url = resource.getURL().toString();
if (!url.contains(baseDir))
{
LOGGER.warn("Base directory '{}' not found in resource URL '{}'. Skipping.", baseDir, url);
return null;
}
int baseIndex = url.indexOf(baseDir);
String relative = url.substring(baseIndex + baseDir.length() + 1);
if (relative.isEmpty())
{
LOGGER.warn("Relative path is empty for resource URL '{}'. Skipping.", url);
return null;
}
return relative;
}
catch (Exception e)
{
LOGGER.warn("Error resolving URL for resource: {}. {}", resource, e.getMessage());
return null;
}
}
private void copyResource(Resource resource, Path target)
{
try
{
Files.createDirectories(target.getParent());
try (InputStream in = resource.getInputStream())
{
LOGGER.info("Creating temporary libreoffice profile file");
Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
}
}
catch (IOException e)
{
LOGGER.error("Error copying resource to temporary file: {}", e.getMessage());
}
}
}
@@ -270,7 +270,7 @@ public class JodConverterSharedInstance implements JodConverter
}
/* (non-Javadoc)
*
*
* @see org.alfresco.repo.content.JodConverter#isAvailable() */
public boolean isAvailable()
{
@@ -278,7 +278,7 @@ public class JodConverterSharedInstance implements JodConverter
}
/* (non-Javadoc)
*
*
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */
@PostConstruct
public void afterPropertiesSet()
@@ -487,7 +487,7 @@ public class JodConverterSharedInstance implements JodConverter
}
/* (non-Javadoc)
*
*
* @see org.springframework.beans.factory.DisposableBean#destroy() */
@PreDestroy
public void destroy()
@@ -507,7 +507,7 @@ public class JodConverterSharedInstance implements JodConverter
}
/* (non-Javadoc)
*
*
* @see org.alfresco.repo.content.JodConverterWorker#getOfficeManager() */
@Override
public OfficeManager getOfficeManager()
@@ -2,7 +2,7 @@
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2023 Alfresco Software Limited
* Copyright (C) 2005 - 2026 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
@@ -53,6 +53,7 @@ import org.alfresco.transform.base.TransformManager;
import org.alfresco.transform.base.executors.JavaExecutor;
import org.alfresco.transform.base.util.CustomTransformerFileAdaptor;
import org.alfresco.transform.exceptions.TransformException;
import org.alfresco.transform.libreoffice.patch.LibreOfficeProfileManager;
/**
* JavaExecutor implementation for running LibreOffice transformations. It loads the transformation logic in the same JVM (check the {@link JodConverter} implementation).
@@ -110,6 +111,9 @@ public class LibreOfficeTransformer implements JavaExecutor, CustomTransformerFi
throw new IllegalArgumentException("LibreOfficeTransformer LIBREOFFICE_IS_ENABLED variable must be set to true/false");
}
LibreOfficeProfileManager profileManager = new LibreOfficeProfileManager(templateProfileDir);
String effectiveTemplateProfileDir = profileManager.getEffectiveTemplateProfileDir();
JodConverterSharedInstance sharedInstance = new JodConverterSharedInstance();
jodconverter = sharedInstance;
sharedInstance.setOfficeHome(path);
@@ -118,8 +122,8 @@ public class LibreOfficeTransformer implements JavaExecutor, CustomTransformerFi
sharedInstance.setTaskQueueTimeout(timeout);
sharedInstance.setConnectTimeout(timeout);
sharedInstance.setPortNumbers(portNumbers);
sharedInstance.setTemplateProfileDir(templateProfileDir);
sharedInstance.setEnabled(isEnabled);
sharedInstance.setTemplateProfileDir(effectiveTemplateProfileDir);
sharedInstance.afterPropertiesSet();
}
@@ -7,5 +7,5 @@ transform:
maxTasksPerProcess: ${LIBREOFFICE_MAX_TASKS_PER_PROCESS:200}
timeout: ${LIBREOFFICE_TIMEOUT:1200000}
portNumbers: ${LIBREOFFICE_PORT_NUMBERS:8100}
templateProfileDir: ${LIBREOFFICE_TEMPLATE_PROFILE_DIR:}
templateProfileDir: ${LIBREOFFICE_TEMPLATE_PROFILE_DIR:alfresco_default}
isEnabled: ${LIBREOFFICE_IS_ENABLED:true}
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<oor:items xmlns:oor="http://openoffice.org/2001/registry"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="BlockUntrustedRefererLinks" oor:op="fuse">
<value>true</value>
</prop>
</item>
</oor:items>
@@ -0,0 +1,103 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2026 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transform.libreoffice.patch;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
/**
* Test cases for LibreOfficeProfileManager
*
* @author Sayan Bhattacharya
*/
@RunWith(MockitoJUnitRunner.class)
class LibreOfficeProfileManagerTest
{
@Test
void testGetEffectiveTemplateProfileDir_WithNullInput()
{
LibreOfficeProfileManager profileManager = new LibreOfficeProfileManager(null);
String result = profileManager.getEffectiveTemplateProfileDir();
assertNull(result);
}
@Test
void testGetEffectiveTemplateProfileDir_WithEmptyString()
{
LibreOfficeProfileManager profileManager = new LibreOfficeProfileManager("");
String result = profileManager.getEffectiveTemplateProfileDir();
assertEquals("", result);
}
@Test
void testGetEffectiveTemplateProfileDir_WithBlankString()
{
LibreOfficeProfileManager profileManager = new LibreOfficeProfileManager(" ");
String result = profileManager.getEffectiveTemplateProfileDir();
assertEquals(" ", result);
}
@Test
void testGetEffectiveTemplateProfileDir_WithValidUserPath()
{
String validPath = "/path/to/template/profile";
LibreOfficeProfileManager profileManager = new LibreOfficeProfileManager(validPath);
String result = profileManager.getEffectiveTemplateProfileDir();
assertEquals(validPath, result);
}
@Test
void testGetEffectiveTemplateProfileDir_WithDefaultMarkerCreatesTempDir()
{
LibreOfficeProfileManager profileManager = new LibreOfficeProfileManager("alfresco_default");
String result = profileManager.getEffectiveTemplateProfileDir();
assertNotNull(result);
assertFalse(result.isBlank());
}
@Test
void testGetEffectiveTemplateProfileDir_WithMultiplePathFormats()
{
String[] paths = {
"C:\\path\\to\\template",
"/path/to/template",
"/path/to/template/",
"relative/path/to/template"
};
for (String path : paths)
{
LibreOfficeProfileManager manager = new LibreOfficeProfileManager(path);
String result = manager.getEffectiveTemplateProfileDir();
assertEquals(path, result);
}
}
}