Skip to content

Commit

Permalink
Merge branch 'torusrxxx--patch-5' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
ArneBab committed Nov 11, 2024
2 parents 523d84b + 2bc2fc2 commit a6ba4c4
Show file tree
Hide file tree
Showing 7 changed files with 459 additions and 234 deletions.
160 changes: 116 additions & 44 deletions src/freenet/client/filter/CSSTokenizerFilter.java

Large diffs are not rendered by default.

125 changes: 67 additions & 58 deletions src/freenet/client/filter/ElementInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

public class ElementInfo {

Expand Down Expand Up @@ -53,42 +54,6 @@ public class ElementInfo {
"button"
)));

// FIXME add some more languages.
public static final Set<String> LANGUAGES =
Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
"az",
"be",
"bg",
"cs",
"de",
"el",
"en",
"es",
"fi",
"fr",
"id",
"it",
"ja",
"ka",
"kk",
"ky",
"lv",
"mo",
"nl",
"no",
"pl",
"pt",
"ro",
"ru",
"sv",
"tl",
"tr",
"tt",
"uk",
"zh-hans",
"zh-hant"
)));

public static final Set<String> MEDIA =
Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
"all",
Expand Down Expand Up @@ -182,13 +147,22 @@ public class ElementInfo {
"new york6"
)));

// https://developer.mozilla.org/en-US/docs/Web/CSS/font-family
public static final Set<String> GENERIC_FONT_KEYWORDS =
Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
"serif",
"sans-serif",
"cursive",
"fantasy",
"monospace"
"monospace",
"system-ui",
"ui-serif",
"ui-sans-serif",
"ui-monospace",
"ui-rounded",
"emoji",
"math",
"fangsong"
)));

public static final Set<String> GENERIC_VOICE_KEYWORDS =
Expand All @@ -206,19 +180,37 @@ public class ElementInfo {
"nth-last-child",
"nth-of-type",
"nth-last-of-type",
"link",
"visited",
"link", // inverse of visited (see BANNED_PSEUDOCLASS below)
"visited", // privacy risk (see BANNED_PSEUDOCLASS below)
"hover",
"active",
"checked",
"checked", // forms
"focus",
"focus-within",
"lang",
"first-line",
"first-letter",
"before",
"after",
"target"
"target",
"any-link",
"default", // forms
"defined", // Javascript only (BANNED_PSEUDOCLASS)
"disabled", // forms
"empty",
"enabled", // forms
"focus-visible",
"indeterminate", // forms
"in-range", // forms
"invalid", // forms
"only-child",
"only-of-type",
"optional", // forms
"out-of-range", // forms
"placeholder-shown", // forms
"read-only", // forms
"read-write", // forms
"required", // forms
"root"
)));

public static final Set<String> BANNED_PSEUDOCLASS =
Expand Down Expand Up @@ -249,7 +241,10 @@ public class ElementInfo {
// is considered too much of a danger, so we scrub that pseudoclass.
//
// [1] http://lcamtuf.coredump.cx/css_calc/
"visited"
"link",
"visited",
// Javascript only
"defined"
)));

public static boolean isSpecificFontFamily(String font) {
Expand Down Expand Up @@ -432,49 +427,63 @@ public static boolean isBannedPseudoClass(String cname)
// Pseudo-classes can be chained, at least dynamic ones can, see CSS2.1 section 5.11.3
String[] split = cname.split(":");
for(String s : split)
if(isBannedPseudoClass(s)) return true;
if(isBannedPseudoClass2(s)) return true;
return false;
} else {
return isBannedPseudoClass2(cname);
}
cname=cname.toLowerCase();
return BANNED_PSEUDOCLASS.contains(cname);
}

private static boolean isBannedPseudoClass2(String cname)
{
return BANNED_PSEUDOCLASS.contains(cname.toLowerCase());
}

public static boolean isValidPseudoClass(String cname)
{
if(cname.indexOf(':') != -1) {
// Pseudo-classes can be chained, at least dynamic ones can, see CSS2.1 section 5.11.3
String[] split = cname.split(":");
for(String s : split)
if(!isValidPseudoClass(s)) return false;
if(!isValidPseudoClass2(s)) return false;
return true;
} else {
return isValidPseudoClass2(cname);
}
}

private static boolean isValidPseudoClass2(String cname)
{
cname=cname.toLowerCase();
if(PSEUDOCLASS.contains(cname))
return true;


else if(cname.contains("lang") && LANGUAGES.contains(getPseudoClassArg(cname, "lang")))
else if(cname.startsWith("lang") && Pattern.matches("[\\w\\-*]{1,30}", getPseudoClassArg(cname, "lang")))
{
// FIXME accept unknown languages as long as they are [a-z-]
// More than 8000 valid BCP-47 language codes. Just let through all of them.
return true;
}

else if(cname.contains("nth-child") && FilterUtils.isNth(getPseudoClassArg(cname, "nth-child")))
else if(cname.startsWith("nth-child") && FilterUtils.isNth(getPseudoClassArg(cname, "nth-child")))
return true;
else if(cname.contains("nth-last-child") && FilterUtils.isNth(getPseudoClassArg(cname, "nth-last-child")))
else if(cname.startsWith("nth-last-child") && FilterUtils.isNth(getPseudoClassArg(cname, "nth-last-child")))
return true;
else if(cname.contains("nth-of-type") && FilterUtils.isNth(getPseudoClassArg(cname, "nth-of-type")))
else if(cname.startsWith("nth-of-type") && FilterUtils.isNth(getPseudoClassArg(cname, "nth-of-type")))
return true;
else if(cname.contains("nth-last-of-type") && FilterUtils.isNth(getPseudoClassArg(cname, "nth-last-of-type")))
else if(cname.startsWith("nth-last-of-type") && FilterUtils.isNth(getPseudoClassArg(cname, "nth-last-of-type")))
return true;

else if(cname.startsWith("dir")) {
String arg = getPseudoClassArg(cname, "dir");
return arg.equalsIgnoreCase("ltr") || arg.equalsIgnoreCase("rtl");
}
return false;
}
}

public static String getPseudoClassArg(String cname, String cname_sans_arg) {
String arg="";
int cnameIndex=cname.indexOf(cname_sans_arg);
int firstIndex=cname.indexOf('(');
int secondIndex=cname.lastIndexOf(')');
if(cnameIndex == -1 || firstIndex == -1 || secondIndex == -1)
return "";
if(cname.substring(cnameIndex + cname_sans_arg.length(), firstIndex).trim().isEmpty() && cname.substring(0, cnameIndex).trim().isEmpty() && cname.substring(secondIndex + 1, cname.length()).trim().isEmpty())
{
arg=CSSTokenizerFilter.removeOuterQuotes(cname.substring(firstIndex+1,secondIndex).trim());
Expand Down
139 changes: 64 additions & 75 deletions src/freenet/client/filter/FilterUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.regex.Pattern;

public class FilterUtils {
private static volatile boolean logDEBUG;
Expand Down Expand Up @@ -289,6 +290,7 @@ else if(value.contains("rad"))
SVGcolorKeywords.add("whitesmoke");
SVGcolorKeywords.add("yellow");
SVGcolorKeywords.add("yellowgreen");
SVGcolorKeywords.add("rebeccapurple"); // CSS Colors Level 4: #663399
}
private final static HashSet<String> CSScolorKeywords=new HashSet<String>();
static
Expand All @@ -315,34 +317,34 @@ else if(value.contains("rad"))
}
private final static HashSet<String> CSSsystemColorKeywords=new HashSet<String>();
static {
CSScolorKeywords.add("ActiveBorder");
CSScolorKeywords.add("ActiveCaption");
CSScolorKeywords.add("AppWorkspace");
CSScolorKeywords.add("Background");
CSScolorKeywords.add("ButtonFace");
CSScolorKeywords.add("ButtonHighlight");
CSScolorKeywords.add("ButtonShadow");
CSScolorKeywords.add("ButtonText");
CSScolorKeywords.add("CaptionText");
CSScolorKeywords.add("GrayText");
CSScolorKeywords.add("Highlight");
CSScolorKeywords.add("HighlightText");
CSScolorKeywords.add("InactiveBorder");
CSScolorKeywords.add("InactiveCaption");
CSScolorKeywords.add("InactiveCaptionText");
CSScolorKeywords.add("InfoBackground");
CSScolorKeywords.add("InfoText");
CSScolorKeywords.add("Menu");
CSScolorKeywords.add("MenuText");
CSScolorKeywords.add("Scrollbar");
CSScolorKeywords.add("ThreeDDarkShadow");
CSScolorKeywords.add("ThreeDFace");
CSScolorKeywords.add("ThreeDHighlight");
CSScolorKeywords.add("ThreeDLightShadow");
CSScolorKeywords.add("ThreeDShadow");
CSScolorKeywords.add("Window");
CSScolorKeywords.add("WindowFrame");
CSScolorKeywords.add("WindowText");
CSScolorKeywords.add("activeborder");
CSScolorKeywords.add("activecaption");
CSScolorKeywords.add("appworkspace");
CSScolorKeywords.add("background");
CSScolorKeywords.add("buttonface");
CSScolorKeywords.add("buttonhighlight");
CSScolorKeywords.add("buttonshadow");
CSScolorKeywords.add("buttontext");
CSScolorKeywords.add("captiontext");
CSScolorKeywords.add("graytext");
CSScolorKeywords.add("highlight");
CSScolorKeywords.add("highlighttext");
CSScolorKeywords.add("inactiveborder");
CSScolorKeywords.add("inactivecaption");
CSScolorKeywords.add("inactivecaptiontext");
CSScolorKeywords.add("infobackground");
CSScolorKeywords.add("infotext");
CSScolorKeywords.add("menu");
CSScolorKeywords.add("menutext");
CSScolorKeywords.add("scrollbar");
CSScolorKeywords.add("threeddarkshadow");
CSScolorKeywords.add("threedface");
CSScolorKeywords.add("threedhighlight");
CSScolorKeywords.add("threedlightshadow");
CSScolorKeywords.add("threedshadow");
CSScolorKeywords.add("window");
CSScolorKeywords.add("windowframe");
CSScolorKeywords.add("windowtext");
}
public static boolean isValidCSSShape(String value)
{
Expand Down Expand Up @@ -370,70 +372,57 @@ public static boolean isValidCSSShape(String value)
public static boolean isMedia(String media) {
return cssMedia.contains(media);
}

public static final Pattern hexColorPattern = Pattern.compile("#(?>[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3,4})", Pattern.CASE_INSENSITIVE);

public static boolean isColor(String value)
{
value=value.trim();
value=value.trim().toLowerCase();

if(CSScolorKeywords.contains(value) || CSSsystemColorKeywords.contains(value) || SVGcolorKeywords.contains(value))
return true;

if(value.indexOf('#')==0)
{

if(value.length()==4)
return hexColorPattern.matcher(value).matches();
}
if((value.startsWith("rgb(") || value.startsWith("rgba(")) && value.indexOf(')')==value.length()-1)
{
// rgba is an alias to rgb
if(value.contains(","))
{
try{
Integer.valueOf(value.substring(1,2),16).intValue();
Integer.valueOf(value.substring(2,3),16).intValue();
Integer.valueOf(value.substring(3,4),16).intValue();
return true;
}
catch(Exception e)
// Legacy format rgba(r,g,b,a)
String[] colorParts=value.substring(value.indexOf("(")+1,value.length()-1).split(",");
if(colorParts.length!=3&&colorParts.length!=4)
return false;
for(int i=0; i<3; i++)
{
if(!(isPercentage(colorParts[i].trim()) || isInteger(colorParts[i].trim())))
return false;
}

}
else if(value.length()==7)
{

try{
Integer.valueOf(value.substring(1,3),16).intValue();
Integer.valueOf(value.substring(3,5),16).intValue();
Integer.valueOf(value.substring(5,7),16).intValue();
if(colorParts.length<=3 || isNumber(colorParts[3]))
return true;
}else{
if(value.contains("/")){
// Modern format rgba(r g b / a)
String alphaPart=value.substring(value.indexOf("/")+1,value.length()-1).trim();
if(!alphaPart.isEmpty() && !isPercentage(alphaPart) && !isNumber(alphaPart) && !alphaPart.equalsIgnoreCase("none"))
return false;
value=value.substring(0,value.indexOf("/"))+")"; // Strip alpha value, proceed to the following tests
}
// Modern format rgba(r g b)
String[] colorParts=value.substring(value.indexOf("(")+1,value.length()-1).split(" ");
if(colorParts.length!=3) {
return false;
}
catch(Exception e)
for(int i=0; i<3; i++)
{
String trimmed = colorParts[i].trim();
if(!(trimmed.equalsIgnoreCase("none") || isPercentage(trimmed) || (isInteger(trimmed) && isIntegerInRange(trimmed, 0, 255))))
return false;
}
}
}
if(value.indexOf("rgb(")==0 && value.indexOf(')')==value.length()-1)
{
String[] colorParts=value.substring(4,value.length()-1).split(",");
if(colorParts.length!=3)
return false;
boolean isValidColorParts=true;
for(int i=0; i<colorParts.length && isValidColorParts;i++)
{
if(!(isPercentage(colorParts[i].trim()) || isInteger(colorParts[i].trim())))
isValidColorParts = false;
}
if(isValidColorParts)
return true;
}
if(value.indexOf("rgba(")==0 && value.indexOf(')')==value.length()-1)
{
String[] colorParts=value.substring(5,value.length()-1).split(",");
if(colorParts.length!=4)
return false;
boolean isValidColorParts=true;
for(int i=0; i<colorParts.length-1 && isValidColorParts;i++)
{
if(!(isPercentage(colorParts[i].trim()) || isInteger(colorParts[i].trim())))
isValidColorParts = false;
}
if(isValidColorParts && isNumber(colorParts[3]))
return true;
}

if(value.indexOf("hsl(")==0 && value.indexOf(')')==value.length()-1)
Expand Down
Loading

0 comments on commit a6ba4c4

Please sign in to comment.