Improve validation of xml mindmaps during save.

This commit is contained in:
Paulo Gustavo Veiga 2022-02-22 14:16:50 -08:00
parent 342099194d
commit c3f93fdf4a
8 changed files with 116 additions and 41 deletions

View File

@ -0,0 +1,56 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.exceptions;
import org.springframework.lang.Nullable;
import javax.validation.constraints.NotNull;
public class InvalidMindmapException
extends ClientException {
private static final String EMPTY_MINDMAP = "MINDMAP_EMPTY_ERROR";
private static final String INVALID_MINDMAP_FORMAT = "INVALID_MINDMAP_FORMAT";
private static final String TOO_BIG_MINDMAP = "TOO_BIG_MINDMAP";
private final String bundleKey;
private InvalidMindmapException(@NotNull String bundleKey, @Nullable String xmlDoc) {
super("Invalid mindmap format:" + xmlDoc, Severity.SEVERE);
this.bundleKey = bundleKey;
}
static public InvalidMindmapException emptyMindmap() {
return new InvalidMindmapException(EMPTY_MINDMAP,"");
}
static public InvalidMindmapException invalidFormat(@Nullable String xmlDoc) {
return new InvalidMindmapException(INVALID_MINDMAP_FORMAT,xmlDoc);
}
static public InvalidMindmapException tooBigMindnap() {
return new InvalidMindmapException(TOO_BIG_MINDMAP,"");
}
@NotNull
@Override
protected String getMsgBundleKey() {
return bundleKey;
}
}

View File

@ -19,6 +19,7 @@
package com.wisemapping.model;
import com.wisemapping.exceptions.AccessDeniedSecurityException;
import com.wisemapping.exceptions.InvalidMindmapException;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.util.ZipUtils;
import org.apache.commons.lang.StringEscapeUtils;
@ -94,7 +95,9 @@ public class Mindmap implements Serializable {
}
}
public void setXmlStr(@NotNull String xml) {
public void setXmlStr(@NotNull String xml) throws InvalidMindmapException {
// Is a valid mindmap ... ?
MindmapUtils.verifyMindmap(xml);
this.setUnzipXml(xml.getBytes(StandardCharsets.UTF_8));
}

View File

@ -0,0 +1,27 @@
package com.wisemapping.model;
import com.wisemapping.exceptions.InvalidMindmapException;
import org.jetbrains.annotations.Nullable;
abstract public class MindmapUtils {
private static final int MAX_SUPPORTED_NODES = 500;
public static void verifyMindmap(@Nullable String xmlDoc) throws InvalidMindmapException {
if (xmlDoc == null || xmlDoc.trim().isEmpty()) {
// Perform basic structure validation. Must have a map node and
throw InvalidMindmapException.emptyMindmap();
}
// Perform basic structure validation without parsing the XML.
if (!xmlDoc.trim().endsWith("</map>") || !xmlDoc.trim().startsWith("<map")) {
throw InvalidMindmapException.invalidFormat(xmlDoc);
}
// Validate that the number of nodes is not bigger 500 nodes.
if (xmlDoc.split("<topic").length > MAX_SUPPORTED_NODES) {
throw InvalidMindmapException.tooBigMindnap();
}
}
}

View File

@ -133,10 +133,7 @@ public class MindmapController extends BaseController {
collaborationProperties.setMindmapProperties(properties);
// Validate content ...
String xml = restMindmap.getXml();
if (xml == null) {
throw new IllegalArgumentException("Map xml can not be null");
}
final String xml = restMindmap.getXml();
mindmap.setXmlStr(xml);
// Update map ...
@ -164,14 +161,10 @@ public class MindmapController extends BaseController {
@RequestMapping(method = RequestMethod.PUT, value = {"/maps/{id}/document/xml"}, consumes = {"text/plain"})
@ResponseBody
public void updateDocument(@PathVariable int id, @RequestBody String xmlDoc) throws WiseMappingException, IOException {
final Mindmap mindmap = findMindmapById(id);
final User user = Utils.getUser();
if (xmlDoc != null && !xmlDoc.isEmpty()) {
mindmap.setXmlStr(xmlDoc);
}
mindmap.setXmlStr(xmlDoc);
saveMindmapDocument(false, mindmap, user);
}
@ -273,7 +266,6 @@ public class MindmapController extends BaseController {
// Is there a map with the same name ?
if (mindmapService.getMindmapByTitle(title, user) != null) {
throw buildValidationException("title", "You already have a mindmap with this title");
}

View File

@ -1,20 +1,20 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.rest.model;
@ -22,9 +22,9 @@ package com.wisemapping.rest.model;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.wisemapping.exceptions.InvalidMindmapException;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.model.*;
import com.wisemapping.security.Utils;
import com.wisemapping.util.TimeUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -34,10 +34,6 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.IOException;
import java.util.Calendar;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@XmlRootElement(name = "map")
@XmlAccessorType(XmlAccessType.PROPERTY)
@ -71,7 +67,7 @@ public class RestMindmap {
}
}
public void setCreationTime(final String creationTime){
public void setCreationTime(final String creationTime) {
// Ignore
}
@ -154,11 +150,11 @@ public class RestMindmap {
return mindmap.getXmlStr();
}
public void setXml(@Nullable String xml) throws IOException {
if (xml != null)
public void setXml(@Nullable String xml) throws IOException, InvalidMindmapException {
if (xml != null) {
mindmap.setXmlStr(xml);
}
}
public String getOwner() {
final User owner = mindmap.getCreator();

View File

@ -19,6 +19,7 @@
package com.wisemapping.service;
import com.wisemapping.dao.UserManager;
import com.wisemapping.exceptions.InvalidMindmapException;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.mail.NotificationService;
import com.wisemapping.model.*;
@ -146,7 +147,7 @@ public class UserServiceImpl
return user;
}
public Mindmap buildTutorialMindmap(@NotNull String firstName) {
public Mindmap buildTutorialMindmap(@NotNull String firstName) throws InvalidMindmapException {
//To change body of created methods use File | Settings | File Templates.
final Locale locale = LocaleContextHolder.getLocale();
Mindmap result = new Mindmap();

View File

@ -53,3 +53,6 @@ NO_ENOUGH_PERMISSIONS=This mind map can opened.
NO_ENOUGH_PERMISSIONS_DETAILS=You do not have enough right access to see this map. This map has been changed to private or deleted.
CAPTCHA_TIMEOUT_OUT_DUPLICATE=Please, refresh the page and try again.
CAPTCHA_INVALID_INPUT_RESPONSE="Invalid input response, refresh the page and try again.
MINDMAP_EMPTY_ERROR=Midnmap can not be empty.
INVALID_MINDMAP_FORMAT=Mindmap format is not valid format.
TOO_BIG_MINDMAP=You have reached the limit of 500 topics in a mindmap.

View File

@ -33,14 +33,11 @@
</script>
<script type="text/javascript">
var mapId = '${mindmap.id}';
var memoryPersistence = ${memoryPersistence};
var readOnly = ${readOnlyMode};
var lockTimestamp = '${lockTimestamp}';
var lockSession = '${lockSession}';
var mindmapLocked = ${mindmapLocked};
var mindmapLockedMsg = '<spring:message code="MINDMAP_LOCKED" arguments="${lockInfo.user.fullName},${lockInfo.user.email}"/>';
var userOptions = ${mindmap.properties};
var isAuth = ${principal != null};
var accountName = '${principal.fullName}';
var accountEmail = '${principal.email}';
var mapTitle = '${mindmap.title}';