001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with this work for additional
004 * information regarding copyright ownership.  The ASF licenses this file to You under the Apache
005 * License, Version 2.0 (the "License"); you may not use this file except in compliance with
006 * the License.  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software distributed under the
011 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
012 * express or implied.  See the License for the specific language governing permissions and
013 * limitations under the License.
014 */
015package org.apache.juneau.console.views;
016
017/**
018 * How a field-grid catalog entry (or a remaining declarative field) is painted.
019 *
020 * <p>
021 * Each constant carries the lowercase token emitted on {@code format} / {@code data-juneau-field-format}.
022 * {@link #TEXT} is omitted from the wire (the default).
023 *
024 * @since 10.0.0
025 */
026public enum FieldFormat {
027
028   /** Paint with {@code textContent}.  The default. */
029   TEXT("text"),
030
031   /**
032    * Treat the value as sanitizing-markdown HTML and copy allowlisted nodes into the slot.
033    * Never {@code innerHTML}.
034    */
035   MARKDOWN("markdown"),
036
037   /**
038    * Treat the value as rich HTML the <b>caller has already sanitized server-side</b>, and paint it
039    * through this runtime's own second allowlist &mdash; a wider one than {@link #MARKDOWN}'s, admitting
040    * {@code <img>} and the remaining table/typographic tags a full-fidelity rich-text body needs.
041    *
042    * <p>
043    * <b>This is not a raw-HTML sink.</b>  Like {@link #MARKDOWN}, the client parses the value with
044    * {@code DOMParser} into an inert document and copies allowlisted nodes via {@code createElement}/
045    * {@code createTextNode}; it never assigns {@code innerHTML}, and it never serializes back to a string (so
046    * the mutation-XSS class that a parse&rarr;serialize&rarr;reparse sanitizer is prone to cannot arise).
047    * Attributes are copied by an explicit per-tag allowlist, so {@code on*} handlers, {@code srcdoc},
048    * {@code style} and every other unnamed attribute cannot survive <i>by construction</i> rather than by a
049    * deny-list that has to anticipate them.  {@code href} and {@code src} are scheme-checked in two layers,
050    * not one: an explicit prefix reject for {@code javascript:}, {@code data:} and {@code vbscript:}, plus a
051    * <b>colon-fallback</b> rule underneath it that rejects any value containing a colon outside the
052    * explicitly allowlisted absolute prefixes ({@code http:}/{@code https:}/{@code mailto:} for
053    * {@code href}; {@code http:}/{@code https:} for {@code src}).  <b>The colon-fallback, not the named-
054    * scheme prefix check, is the load-bearing defense</b>: it is what still rejects an obfuscated spelling
055    * of one of those three schemes (e.g. one split by a stray whitespace/control character that a browser's
056    * URL parser strips before resolving, such as {@code java\tscript:}) &mdash; the prefix check alone would
057    * miss it, but the obfuscated string still contains a colon and matches none of the allowed prefixes, so
058    * it still fails closed. A future "simplification" to a longer bare {@code javascript:}/{@code data:}/
059    * {@code vbscript:} deny-list that drops the colon-fallback as apparently redundant would silently
060    * reopen that hole.
061    *
062    * <p>
063    * <b>The contract is nonetheless caller-sanitizes-first.</b>  This runtime's allowlist is a second,
064    * independent gate &mdash; defense in depth &mdash; not a substitute for a real server-side sanitizer.  Juneau
065    * takes on no HTML-sanitizer dependency and makes no claim to sanitize hostile input on the caller's behalf:
066    * an application pointing this format at externally-authored HTML is expected to have run that HTML through
067    * a dedicated allowlist sanitizer at its own trust boundary first.  What this format guarantees is narrower
068    * and worth stating exactly: <i>if that upstream pass is wrong, a script still does not execute here.</i>
069    *
070    * <p>
071    * Fidelity is bounded by the allowlist.  Tags outside it are unwrapped (their children are kept), so an
072    * unexpected element degrades to its text rather than rendering &mdash; a body that needs an element this
073    * allowlist does not name will silently lose that element's markup, not its content.
074    *
075    * <p>
076    * Like {@link #MARKDOWN}, a field with this format spans full width.
077    */
078   SANITIZED_HTML("sanitizedHtml");
079
080   private final String wire;
081
082   FieldFormat(String wire) {
083      this.wire = wire;
084   }
085
086   /**
087    * Returns the lowercase wire token for this format.
088    *
089    * @return The wire token (e.g. <c>"markdown"</c>).
090    */
091   public String wire() {
092      return wire;
093   }
094}