Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@
return imagePath;
}
} else {
try (DirectoryStream<Path> possibleLogos = Files.newDirectoryStream(logosDir, imageName + ".*")) {

Check failure on line 36 in core/src/main/java/org/fao/geonet/resources/FileResources.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Change this code to not construct the path from user-controlled data.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zHqsFkeTS6Nl5Q7&open=AZ6r_zHqsFkeTS6Nl5Q7&pullRequest=9322
for (final Path next: possibleLogos) {
String ext = FilenameUtils.getExtension(next.getFileName().toString());
if (IMAGE_EXTENSIONS.contains(ext.toLowerCase())) {
if (IMAGE_EXTENSIONS.contains(ext.toLowerCase()) || "svg".equalsIgnoreCase(ext)) {
return next;
}
}
Expand Down Expand Up @@ -106,7 +106,7 @@
file = IO.toPath(filename);
}

if (!Files.exists(file)) {

Check warning on line 109 in core/src/main/java/org/fao/geonet/resources/FileResources.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Change this code to not construct the path from user-controlled data.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zHqsFkeTS6Nl5Q9&open=AZ6r_zHqsFkeTS6Nl5Q9&pullRequest=9322
Path webappCopy = null;
if (context != null) {
final String realPath = context.getRealPath(filename);
Expand All @@ -118,7 +118,7 @@
if (webappCopy == null) {
webappCopy = appPath.resolve(filename);
}
if (Files.exists(webappCopy)) {

Check warning on line 121 in core/src/main/java/org/fao/geonet/resources/FileResources.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Change this code to not construct the path from user-controlled data.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zHqsFkeTS6Nl5Q8&open=AZ6r_zHqsFkeTS6Nl5Q8&pullRequest=9322
IO.copyDirectoryOrFile(webappCopy, file, false);
}

Expand All @@ -127,7 +127,7 @@
final String suffixless = FilenameUtils.removeExtension(fileName);
final String suffix = FilenameUtils.getExtension(fileName);

if (!Files.exists(file) && IMAGE_WRITE_SUFFIXES.contains(suffix.toLowerCase())) {

Check warning on line 130 in core/src/main/java/org/fao/geonet/resources/FileResources.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Change this code to not construct the path from user-controlled data.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zHqsFkeTS6Nl5Q-&open=AZ6r_zHqsFkeTS6Nl5Q-&pullRequest=9322
// find a different format and convert it to our desired format
DirectoryStream.Filter<Path> filter = entry -> {
String name = entry.getFileName().toString();
Expand All @@ -136,13 +136,13 @@
boolean canReadImage = name.length() > indexOfDot && IMAGE_READ_SUFFIXES.contains(ext);
return startsWith && canReadImage;
};
try (DirectoryStream<Path> paths = Files.newDirectoryStream(file.getParent(), filter)) {

Check failure on line 139 in core/src/main/java/org/fao/geonet/resources/FileResources.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Change this code to not construct the path from user-controlled data.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zHqsFkeTS6Nl5Q6&open=AZ6r_zHqsFkeTS6Nl5Q6&pullRequest=9322
Iterator<Path> iter = paths.iterator();
if (iter.hasNext()) {
Path path = iter.next();
try (
InputStream in = IO.newInputStream(path);
OutputStream out = Files.newOutputStream(file)

Check failure on line 145 in core/src/main/java/org/fao/geonet/resources/FileResources.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Change this code to not construct the path from user-controlled data.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zHqsFkeTS6Nl5Q5&open=AZ6r_zHqsFkeTS6Nl5Q5&pullRequest=9322
) {
try {
BufferedImage image = ImageIO.read(in);
Expand Down
16 changes: 14 additions & 2 deletions core/src/main/java/org/fao/geonet/resources/ResourceFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@
import jeeves.config.springutil.JeevesDelegatingFilterProxy;
import org.fao.geonet.NodeInfo;
import org.fao.geonet.domain.Pair;
import org.fao.geonet.domain.Source;
import org.fao.geonet.domain.SourceType;

Check warning on line 32 in core/src/main/java/org/fao/geonet/resources/ResourceFilter.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'org.fao.geonet.domain.SourceType'.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zIzsFkeTS6Nl5RA&open=AZ6r_zIzsFkeTS6Nl5RA&pullRequest=9322
Comment thread
fxprunayre marked this conversation as resolved.
Outdated
import org.fao.geonet.kernel.GeonetworkDataDirectory;
import org.fao.geonet.kernel.setting.SettingManager;
import org.fao.geonet.repository.SourceRepository;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.ServletWebRequest;
Expand All @@ -40,6 +43,8 @@
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.util.List;

Check warning on line 46 in core/src/main/java/org/fao/geonet/resources/ResourceFilter.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'java.util.List'.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zIzsFkeTS6Nl5RB&open=AZ6r_zIzsFkeTS6Nl5RB&pullRequest=9322
Comment thread
fxprunayre marked this conversation as resolved.
Outdated
import java.util.Optional;
import java.util.concurrent.ConcurrentMap;

/**
Expand All @@ -52,6 +57,7 @@
* User: jeichar Date: 1/17/12 Time: 4:03 PM
*/
public class ResourceFilter implements Filter {
public static final String DEFAULT_LOGO = "GN3.png";
private static final int FIVE_DAYS = 60 * 60 * 24 * 5;
private static final int SIX_HOURS = 60 * 60 * 6;
private FilterConfig config;
Expand Down Expand Up @@ -94,10 +100,14 @@
this.siteId = applicationContext.getBean(SettingManager.class).getSiteId();
this.resourcesDir = resources.locateResourcesDir(servletContext, applicationContext);
this.schemaPublicationDir = applicationContext.getBean(GeonetworkDataDirectory.class).getSchemaPublicationDir();
SourceRepository sourceRepository = applicationContext.getBean(SourceRepository.class);
this.nodeId = applicationContext.getBean(NodeInfo.class).getId();
if (defaultImage == null) {
defaultImage = resources.loadResource(resourcesDir, servletContext, appPath, "images/logos/" + siteId + ".png", new byte[0], -1);
Optional<Source> catalogues = sourceRepository.findById(this.nodeId);
String defaultImageName = "images/logos/" + (

Check failure on line 107 in core/src/main/java/org/fao/geonet/resources/ResourceFilter.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "images/logos/" 4 times.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zIzsFkeTS6Nl5Q_&open=AZ6r_zIzsFkeTS6Nl5Q_&pullRequest=9322
Comment thread
fxprunayre marked this conversation as resolved.
Outdated
catalogues.isPresent() ? catalogues.get().getLogo() : DEFAULT_LOGO);
defaultImage = resources.loadResource(resourcesDir, servletContext, appPath, defaultImageName, new byte[0], -1);
}
this.nodeId = applicationContext.getBean(NodeInfo.class).getId();
if (!faviconMap.containsKey(nodeId)) {
final byte[] defaultImageBytes = defaultImage.one();
addFavIcon(nodeId, resources.loadResource(resourcesDir, servletContext, appPath, "images/logos/" + siteId + ".ico",
Expand Down Expand Up @@ -186,6 +196,8 @@
contentType = MediaType.APPLICATION_XML_VALUE;
} else if(ext.equals("txt")) {
contentType = MediaType.TEXT_PLAIN_VALUE;
} else if (ext.equals("svg")) {
contentType = "image/svg+xml";
Comment thread
fxprunayre marked this conversation as resolved.
Outdated
} else {
contentType = "image/" + ext;
}
Expand Down
102 changes: 102 additions & 0 deletions services/src/main/java/org/fao/geonet/api/LogoUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (C) 2001-2026 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
* Rome - Italy. email: geonetwork@osgeo.org
*/

package org.fao.geonet.api;

import jeeves.server.context.ServiceContext;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.fao.geonet.api.records.attachments.AttachmentsApi;
import org.fao.geonet.resources.Resources;
import org.springframework.web.context.request.WebRequest;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;

public final class LogoUtils {
public static final String API_GET_LOGO_NOTE = "If last-modified header "
+ "is present it is used to check if the logo has been modified since "
+ "the header date. If it hasn't been modified returns an empty 304 Not"
+ " Modified response. If modified returns the image. If there is "
+ "no logo then returns a transparent 1x1 px PNG image.";

private static final int SIX_HOURS = 60 * 60 * 6;

private static final String TRANSPARENT_1_X_1_PNG_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR"
+ "42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==";

private static final byte[] TRANSPARENT_1_X_1_PNG = org.apache.commons.codec.binary.Base64.decodeBase64(TRANSPARENT_1_X_1_PNG_BASE64);

private LogoUtils() {
}

public static Resources.ResourceHolder getImage(Resources resources,
ServiceContext serviceContext,
String logoRef) throws IOException {
final Path logosDir = resources.locateLogosDir(serviceContext);
final Path harvesterLogosDir = resources.locateHarvesterLogosDir(serviceContext);
Resources.ResourceHolder image = null;
if (isLocalLogoRef(logoRef)) {
image = resources.getImage(serviceContext, logoRef, logosDir);
if (image == null) {
image = resources.getImage(serviceContext, logoRef, harvesterLogosDir);
}
}
return image;
}

public static void writeImageOrTransparentLogo(WebRequest webRequest,
HttpServletResponse response,
Resources.ResourceHolder image) throws IOException {
if (image != null) {
FileTime lastModifiedTime = image.getLastModifiedTime();
response.setDateHeader("Expires", System.currentTimeMillis() + SIX_HOURS * 1000L);
if (webRequest.checkNotModified(lastModifiedTime.toMillis())) {
return;
}
response.setContentType(AttachmentsApi.getFileContentType(image.getPath().getFileName().toString()));
response.setContentLength((int) Files.size(image.getPath()));
response.addHeader("Cache-Control", "max-age=" + SIX_HOURS + ", public");
FileUtils.copyFile(image.getPath().toFile(), response.getOutputStream());
return;
}

if (webRequest.checkNotModified(0L)) {
return;
}
response.setContentType("image/png");
response.setContentLength(TRANSPARENT_1_X_1_PNG.length);
response.addHeader("Cache-Control", "max-age=" + SIX_HOURS + ", public");
response.getOutputStream().write(TRANSPARENT_1_X_1_PNG);
}

private static boolean isLocalLogoRef(String logoRef) {
return StringUtils.isNotBlank(logoRef)
&& !logoRef.startsWith("http://")
&& !logoRef.startsWith("https://")
&& !logoRef.startsWith("https//");
}
}
71 changes: 4 additions & 67 deletions services/src/main/java/org/fao/geonet/api/groups/GroupsApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@
import java.util.regex.Pattern;
import jeeves.server.UserSession;
import jeeves.server.context.ServiceContext;
import org.apache.commons.io.FileUtils;

Check warning on line 37 in services/src/main/java/org/fao/geonet/api/groups/GroupsApi.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'org.apache.commons.io.FileUtils'.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zFbsFkeTS6Nl5Qz&open=AZ6r_zFbsFkeTS6Nl5Qz&pullRequest=9322
import org.apache.commons.lang.StringUtils;

Check warning on line 38 in services/src/main/java/org/fao/geonet/api/groups/GroupsApi.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'org.apache.commons.lang.StringUtils'.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zFbsFkeTS6Nl5Q0&open=AZ6r_zFbsFkeTS6Nl5Q0&pullRequest=9322
Comment thread
fxprunayre marked this conversation as resolved.
Outdated
import org.apache.commons.lang.exception.ExceptionUtils;
import org.fao.geonet.ApplicationContextHolder;
import org.fao.geonet.api.API;
import org.fao.geonet.api.ApiParams;
import org.fao.geonet.api.ApiUtils;
import org.fao.geonet.api.LogoUtils;
import org.fao.geonet.api.exception.NotAllowedException;
import org.fao.geonet.api.exception.ResourceNotFoundException;
import org.fao.geonet.api.records.attachments.AttachmentsApi;
import org.fao.geonet.api.tools.i18n.LanguageUtils;
import org.fao.geonet.api.tools.i18n.TranslationPackBuilder;
import org.fao.geonet.constants.Geonet;
Expand Down Expand Up @@ -77,14 +77,12 @@
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.fao.geonet.api.LogoUtils.API_GET_LOGO_NOTE;
import static org.springframework.data.jpa.domain.Specification.where;

@RequestMapping(value = {
Expand All @@ -111,27 +109,6 @@
public static final int GROUPNAME_MAX_LENGHT = 32;


/**
* API logo note.
*/
private static final String API_GET_LOGO_NOTE = "If last-modified header "
+ "is present it is used to check if the logo has been modified since "
+ "the header date. If it hasn't been modified returns an empty 304 Not"
+ " Modified response. If modified returns the image. If the group has "
+ "no logo then returns a transparent 1x1 px PNG image.";
/**
* Six hours in seconds.
*/
private static final int SIX_HOURS = 60 * 60 * 6;
/**
* Transparent 1x1 px PNG encoded in Base64.
*/
private static final String TRANSPARENT_1_X_1_PNG_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR"
+ "42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==";
/**
* Transparent 1x1 px PNG.
*/
private static final byte[] TRANSPARENT_1_X_1_PNG = org.apache.commons.codec.binary.Base64.decodeBase64(TRANSPARENT_1_X_1_PNG_BASE64);
/**
* Message source.
*/
Expand Down Expand Up @@ -169,20 +146,6 @@
@Autowired
private PageRepository pageRepository;

private static Resources.ResourceHolder getImage(Resources resources, ServiceContext serviceContext, Group group) throws IOException {
final Path logosDir = resources.locateLogosDir(serviceContext);
final Path harvesterLogosDir = resources.locateHarvesterLogosDir(serviceContext);
final String logoUUID = group.getLogo();
Resources.ResourceHolder image = null;
if (StringUtils.isNotBlank(logoUUID) && !logoUUID.startsWith("http://") && !logoUUID.startsWith("https//")) {
image = resources.getImage(serviceContext, logoUUID, logosDir);
if (image == null) {
image = resources.getImage(serviceContext, logoUUID, harvesterLogosDir);
}
}
return image;
}

/**
* Writes the group logo image to the response. If no image is found, it
* writes a 1x1 transparent PNG. If the request contains cache-related
Expand Down Expand Up @@ -220,35 +183,9 @@
}
try {
final Resources resources = context.getBean(Resources.class);
final String logoUUID = group.get().getLogo();
if (StringUtils.isNotBlank(logoUUID) && !logoUUID.startsWith("http://") && !logoUUID.startsWith("https//")) {
try (Resources.ResourceHolder image = getImage(resources, serviceContext, group.get())) {
if (image != null) {
FileTime lastModifiedTime = image.getLastModifiedTime();
response.setDateHeader("Expires", System.currentTimeMillis() + SIX_HOURS * 1000L);
if (webRequest.checkNotModified(lastModifiedTime.toMillis())) {
// webRequest.checkNotModified sets the right HTTP headers
return;
}
response.setContentType(AttachmentsApi.getFileContentType(image.getPath().getFileName().toString()));
response.setContentLength((int) Files.size(image.getPath()));
response.addHeader("Cache-Control", "max-age=" + SIX_HOURS + ", public");
FileUtils.copyFile(image.getPath().toFile(), response.getOutputStream());
return;
}
}
}

// no logo image found. Return a transparent 1x1 png
FileTime lastModifiedTime = FileTime.fromMillis(0);
if (webRequest.checkNotModified(lastModifiedTime.toMillis())) {
return;
try (Resources.ResourceHolder image = LogoUtils.getImage(resources, serviceContext, group.get().getLogo())) {
LogoUtils.writeImageOrTransparentLogo(webRequest, response, image);
}
response.setContentType("image/png");
response.setContentLength(TRANSPARENT_1_X_1_PNG.length);
response.addHeader("Cache-Control", "max-age=" + SIX_HOURS + ", public");
response.getOutputStream().write(TRANSPARENT_1_X_1_PNG);

} catch (IOException e) {
Log.error(LOGGER, String.format("There was an error accessing the logo of the group with id '%d'",
groupId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.fao.geonet.domain.HarvestHistory;
import org.fao.geonet.domain.ISODate;
import org.fao.geonet.domain.Source;
import org.fao.geonet.domain.SourceType;
import org.fao.geonet.kernel.DataManager;
import org.fao.geonet.kernel.datamanager.IMetadataManager;
import org.fao.geonet.kernel.datamanager.IMetadataUtils;
Expand All @@ -62,6 +63,7 @@
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -173,6 +175,34 @@
return new HttpEntity<>(HttpStatus.NO_CONTENT);
}

@io.swagger.v3.oas.annotations.Operation(
summary = "Get harvester logo image.",
description = "Redirect to source logo endpoint."
)
@RequestMapping(

Check warning on line 182 in services/src/main/java/org/fao/geonet/api/harvesting/HarvestersApi.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace "@RequestMapping(method = RequestMethod.GET)" with "@GetMapping"

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zGwsFkeTS6Nl5Q2&open=AZ6r_zGwsFkeTS6Nl5Q2&pullRequest=9322
value = "/{harvesterUuid}/logo",
method = RequestMethod.GET
)
@ResponseStatus(value = HttpStatus.FOUND)
public void getHarvesterLogo(
@Parameter(
description = "The harvester UUID"
)
@PathVariable
String harvesterUuid,
HttpServletRequest request,
HttpServletResponse response
) throws Exception {

Check warning on line 195 in services/src/main/java/org/fao/geonet/api/harvesting/HarvestersApi.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zGwsFkeTS6Nl5Q1&open=AZ6r_zGwsFkeTS6Nl5Q1&pullRequest=9322
Source source = sourceRepository.findOneByUuid(harvesterUuid);
if (source == null || source.getType() != SourceType.harvester) {
throw new ResourceNotFoundException(String.format(
"Harvester with UUID '%s' not found.",
harvesterUuid));
}

response.sendRedirect(request.getRequestURI().replace("/api/harvesters/", "/api/sources/"));

Check warning

Code scanning / CodeQL

URL redirection from remote source Medium

Untrusted URL redirection depends on a
user-provided value
.
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
}


@io.swagger.v3.oas.annotations.Operation(
summary = "Reindexes all records of an harvester",
Expand Down
4 changes: 1 addition & 3 deletions services/src/main/java/org/fao/geonet/api/site/LogosApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import org.fao.geonet.api.exception.ResourceAlreadyExistException;
import org.fao.geonet.api.exception.ResourceNotFoundException;
import org.fao.geonet.domain.Group;
import org.fao.geonet.kernel.GeonetworkDataDirectory;

Check warning on line 40 in services/src/main/java/org/fao/geonet/api/site/LogosApi.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'org.fao.geonet.kernel.GeonetworkDataDirectory'.

See more on https://sonarcloud.io/project/issues?id=geonetwork_core-geonetwork&issues=AZ6r_zEHsFkeTS6Nl5Qu&open=AZ6r_zEHsFkeTS6Nl5Qu&pullRequest=9322
Comment thread
fxprunayre marked this conversation as resolved.
Outdated
import org.fao.geonet.kernel.setting.SettingManager;
import org.fao.geonet.repository.GroupRepository;
import org.fao.geonet.resources.Resources;
Expand Down Expand Up @@ -71,10 +71,8 @@
description = "Logos operations")
@Controller("siteLogos")
public class LogosApi {
private static final String[] iconExt = {".gif", ".png", ".jpg", ".jpeg"};
private static final String[] iconExt = {".gif", ".png", ".jpg", ".jpeg", ".svg"};

@Autowired
GeonetworkDataDirectory dataDirectory;
@Autowired
SettingManager settingManager;

Expand Down
Loading
Loading