mirror of
https://github.com/Alfresco/alfresco-transform-core.git
synced 2026-09-16 18:12:54 +00:00
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:
co-authored by
Damian Ujma
parent
7ce90de3d4
commit
f988401a75
@@ -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
|
||||
{
|
||||
|
||||
+181
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -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()
|
||||
|
||||
+6
-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.
|
||||
* -
|
||||
@@ -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}
|
||||
+10
@@ -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>
|
||||
+103
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user