/* * DialogHtmlSanitizer.java * * Copyright (C) 2009-16 by RStudio, Inc. * * Unless you have received this program directly from RStudio pursuant * to the terms of a commercial license agreement with RStudio, then * this program is licensed to you under the terms of version 3 of the * GNU Affero General Public License. This program is distributed WITHOUT * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details. * */ package org.rstudio.studio.client.common.rstudioapi; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.rstudio.core.client.StringUtil; import com.google.gwt.safehtml.shared.HtmlSanitizer; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlUtils; public final class DialogHtmlSanitizer implements HtmlSanitizer { private static final Set<String> TAG_WHITELIST = new HashSet<String>( Arrays.asList( "p", "em", "strong", "b", "i" ) ); public static SafeHtml sanitizeHtml(String html) { if (StringUtil.isNullOrEmpty(html)) { html = ""; } return SafeHtmlUtils.fromTrustedString(dialogSanitize(html)); } private static String dialogSanitize(String text) { StringBuilder sanitized = new StringBuilder(); boolean firstSegment = true; for (String segment : text.split("<", -1)) { if (firstSegment) { firstSegment = false; sanitized.append(SafeHtmlUtils.htmlEscapeAllowEntities(segment)); continue; } int tagStart = 0; int tagEnd = segment.indexOf('>'); String tag = null; boolean isValidTag = false; if (tagEnd > 0) { if (segment.charAt(0) == '/') { tagStart = 1; } tag = segment.substring(tagStart, tagEnd).toLowerCase(); if (TAG_WHITELIST.contains(tag)) { isValidTag = true; } } if (isValidTag) { if (tagStart == 0) { sanitized.append('<'); } else { sanitized.append("</"); } sanitized.append(tag).append('>'); sanitized.append(SafeHtmlUtils.htmlEscapeAllowEntities( segment.substring(tagEnd + 1))); } else { sanitized.append("<").append( SafeHtmlUtils.htmlEscapeAllowEntities(segment)); } } return sanitized.toString(); } private DialogHtmlSanitizer() { } public SafeHtml sanitize(String html) { return sanitizeHtml(html); } }