Skip to content

Commit

Permalink
Expose HtmlComponentSerializer to API and add HtmlStripper
Browse files Browse the repository at this point in the history
  • Loading branch information
jpenilla committed Sep 3, 2023
1 parent 72ad8a3 commit ae6108e
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 19 deletions.
1 change: 1 addition & 0 deletions api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ java {
dependencies {
compileOnly(libs.paperApi)
compileOnlyApi(libs.checkerQual)
compileOnlyApi(libs.adventureApi)
}

indra {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package xyz.jpenilla.squaremap.api;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.serializer.ComponentEncoder;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.jetbrains.annotations.ApiStatus;

/**
* Safely encodes {@link Component Components} as HTML text.
*
* <p>Mostly useful for marker tooltips.</p>
*
* @see Squaremap#htmlComponentSerializer()
*/
@DefaultQualifier(NonNull.class)
public interface HtmlComponentSerializer extends ComponentEncoder<Component, String> {

/**
* Create a new {@link HtmlComponentSerializer} using the provided {@link ComponentFlattener}.
*
* @param flattener component flattener
* @return serializer
*/
static HtmlComponentSerializer withFlattener(final ComponentFlattener flattener) {
return ProviderHolder.HTML_SERIALIZER.create(flattener);
}

@ApiStatus.Internal
interface Provider {
HtmlComponentSerializer create(ComponentFlattener flattener);
}

}
36 changes: 36 additions & 0 deletions api/src/main/java/xyz/jpenilla/squaremap/api/HtmlStripper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package xyz.jpenilla.squaremap.api;

import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.jetbrains.annotations.ApiStatus;

/**
* Strips HTML tags from text. Allows sanitizing untrusted strings before use in
* marker tooltips.
*/
@DefaultQualifier(NonNull.class)
public interface HtmlStripper {

/**
* Get an {@link HtmlStripper}.
*
* @return HTML stripper
*/
static HtmlStripper htmlStripper() {
return ProviderHolder.HTML_STRIPPER.instance();
}

/**
* Strips HTML tags from the provided string.
*
* @param string untrusted string
* @return sanitized string
*/
String stripHtml(String string);

@ApiStatus.Internal
interface Provider {
HtmlStripper instance();
}

}
13 changes: 13 additions & 0 deletions api/src/main/java/xyz/jpenilla/squaremap/api/ProviderHolder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package xyz.jpenilla.squaremap.api;

import net.kyori.adventure.util.Services;

final class ProviderHolder {
static final HtmlComponentSerializer.Provider HTML_SERIALIZER = service(HtmlComponentSerializer.Provider.class);
static final HtmlStripper.Provider HTML_STRIPPER = service(HtmlStripper.Provider.class);

private static <T> T service(final Class<T> clazz) {
return Services.service(clazz)
.orElseThrow(() -> new IllegalStateException("Could not find " + clazz.getName() + " implementation"));
}
}
8 changes: 8 additions & 0 deletions api/src/main/java/xyz/jpenilla/squaremap/api/Squaremap.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.nio.file.Path;
import java.util.Collection;
import java.util.Optional;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import org.checkerframework.checker.nullness.qual.NonNull;

/**
Expand Down Expand Up @@ -63,4 +64,11 @@ public interface Squaremap {
*/
@NonNull Path webDir();

/**
* Get an {@link HtmlComponentSerializer} using the platform {@link ComponentFlattener}.
*
* @return serializer
*/
@NonNull HtmlComponentSerializer htmlComponentSerializer();

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package xyz.jpenilla.squaremap.common;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.function.Function;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.framework.qual.DefaultQualifier;
import xyz.jpenilla.squaremap.api.HtmlComponentSerializer;
import xyz.jpenilla.squaremap.api.MapWorld;
import xyz.jpenilla.squaremap.api.PlayerManager;
import xyz.jpenilla.squaremap.api.Registry;
Expand All @@ -24,17 +27,20 @@ public final class SquaremapApiProvider implements Squaremap {
private final PlayerManager playerManager;
private final WorldManager worldManager;
private final IconRegistry iconRegistry;
private final Provider<ComponentFlattener> flattener;

@Inject
private SquaremapApiProvider(
final DirectoryProvider directoryProvider,
final AbstractPlayerManager playerManager,
final WorldManager worldManager
final WorldManager worldManager,
final Provider<ComponentFlattener> flattener
) {
this.directoryProvider = directoryProvider;
this.playerManager = playerManager;
this.worldManager = worldManager;
this.iconRegistry = new IconRegistry(directoryProvider);
this.flattener = flattener;
}

@Override
Expand All @@ -61,4 +67,9 @@ public PlayerManager playerManager() {
public Path webDir() {
return this.directoryProvider.webDirectory();
}

@Override
public HtmlComponentSerializer htmlComponentSerializer() {
return HtmlComponentSerializer.withFlattener(this.flattener.get());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.DefaultQualifier;
import xyz.jpenilla.squaremap.api.HtmlComponentSerializer;
import xyz.jpenilla.squaremap.common.AbstractPlayerManager;
import xyz.jpenilla.squaremap.common.ServerAccess;
import xyz.jpenilla.squaremap.common.config.ConfigManager;
import xyz.jpenilla.squaremap.common.config.WorldConfig;
import xyz.jpenilla.squaremap.common.data.DirectoryProvider;
import xyz.jpenilla.squaremap.common.util.FileUtil;
import xyz.jpenilla.squaremap.common.util.HtmlComponentSerializer;
import xyz.jpenilla.squaremap.common.util.Util;

@DefaultQualifier(NonNull.class)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.ThreadLocalRandom;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.flattener.FlattenerListener;
import net.kyori.adventure.text.format.Style;
Expand All @@ -15,6 +15,7 @@
import org.checkerframework.framework.qual.DefaultQualifier;
import org.owasp.html.PolicyFactory;
import org.owasp.html.Sanitizers;
import xyz.jpenilla.squaremap.api.HtmlComponentSerializer;

@DefaultQualifier(NonNull.class)
final class HtmlComponentSerializerImpl implements HtmlComponentSerializer {
Expand All @@ -27,7 +28,7 @@ final class HtmlComponentSerializerImpl implements HtmlComponentSerializer {
}

@Override
public String serialize(final ComponentLike componentLike) {
public String serialize(final Component componentLike) {
final HtmlFlattener state = new HtmlFlattener();
this.flattener.flatten(componentLike.asComponent(), state);
return SANITIZER.sanitize(state.toString());
Expand Down Expand Up @@ -118,4 +119,11 @@ private static String asHtml(final TextFormat format) {
throw new IllegalArgumentException("Cannot handle format: " + format + " (" + format.getClass().getTypeName() + ")");
}
}

public static final class Provider implements HtmlComponentSerializer.Provider {
@Override
public HtmlComponentSerializer create(final ComponentFlattener flattener) {
return new HtmlComponentSerializerImpl(flattener);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package xyz.jpenilla.squaremap.common.util;

import java.util.Objects;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.owasp.html.HtmlPolicyBuilder;
import org.owasp.html.PolicyFactory;
import xyz.jpenilla.squaremap.api.HtmlStripper;

@DefaultQualifier(NonNull.class)
public final class HtmlStripperImpl implements HtmlStripper {
private static final PolicyFactory SANITIZER = new HtmlPolicyBuilder().toFactory();

private HtmlStripperImpl() {
}

@Override
public String stripHtml(final String string) {
Objects.requireNonNull(string, "Parameter 'string' must not be null");
return SANITIZER.sanitize(string);
}

public static final class Provider implements HtmlStripper.Provider {
private static final HtmlStripper INSTANCE = new HtmlStripperImpl();

@Override
public HtmlStripper instance() {
return INSTANCE;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xyz.jpenilla.squaremap.common.util.HtmlComponentSerializerImpl$Provider
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xyz.jpenilla.squaremap.common.util.HtmlStripperImpl$Provider

0 comments on commit ae6108e

Please sign in to comment.