/*
 * 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("&lt;").append(
            SafeHtmlUtils.htmlEscapeAllowEntities(segment));
         }
      }

      return sanitized.toString();
   }

   private DialogHtmlSanitizer() {
   }

   public SafeHtml sanitize(String html) {
      return sanitizeHtml(html);
   }
}
@@ -1109,16 +1109,21 @@
 %22b%22, %22i%22
+, %22a%22
 %0A      )
@@ -2113,32 +2113,571 @@
 ;%0A            %7D%0A
+            else %7B%0A               // check for links%0A               int tagSpace = segment.indexOf(' ');%0A               if (tagSpace %3E 0) %7B%0A                  String tagName = segment.substring(tagStart, tagSpace).toLowerCase();%0A                  if (tagName == %22a%22) %7B%0A                     %0A                     if (tag.matches(%22a href ?= ?%5C%22https?://%5B%5E%5C%22%5D+%5C%22%22)) %7B%0A                        tag = tag + %22 target=%5C%22_blank%5C%22%22;%0A                        isValidTag = true;%0A                     %7D%0A                  %7D%0A               %7D%0A            %7D%0A
          %7D%0A%0A    

add support to sanitize simple links in html