|
18 | 18 | import static it.niedermann.android.markdown.MarkdownUtil.removeMarkdown; |
19 | 19 | import static it.niedermann.android.markdown.MarkdownUtil.replaceCheckboxesWithEmojis; |
20 | 20 |
|
| 21 | +import java.util.regex.Pattern; |
| 22 | + |
21 | 23 | /** |
22 | 24 | * Provides basic functionality for Note operations. |
23 | 25 | */ |
@@ -69,18 +71,49 @@ private static String truncateString(@NonNull String str, @SuppressWarnings("Sam |
69 | 71 | */ |
70 | 72 | @NonNull |
71 | 73 | public static String generateNoteExcerpt(@NonNull String content, @Nullable String title) { |
72 | | - content = removeMarkdown(replaceCheckboxesWithEmojis(content.trim())); |
73 | | - if (TextUtils.isEmpty(content)) { |
| 74 | + final var trimmedContent = content.trim(); |
| 75 | + |
| 76 | + if (isHtml(trimmedContent)) { |
| 77 | + return sanitizeHtml(trimmedContent); |
| 78 | + } |
| 79 | + |
| 80 | + final var emojiReplacedWithCheckBoxesContent = replaceCheckboxesWithEmojis(trimmedContent); |
| 81 | + var result = removeMarkdown(emojiReplacedWithCheckBoxesContent); |
| 82 | + if (TextUtils.isEmpty(result)) { |
74 | 83 | return ""; |
75 | 84 | } |
| 85 | + |
76 | 86 | if (!TextUtils.isEmpty(title)) { |
77 | | - assert title != null; |
78 | 87 | final String trimmedTitle = removeMarkdown(replaceCheckboxesWithEmojis(title.trim())); |
79 | | - if (content.startsWith(trimmedTitle)) { |
80 | | - content = content.substring(trimmedTitle.length()); |
| 88 | + if (result.startsWith(trimmedTitle)) { |
| 89 | + result = result.substring(trimmedTitle.length()); |
81 | 90 | } |
82 | 91 | } |
83 | | - return truncateString(content.trim(), 200).replace("\n", EXCERPT_LINE_SEPARATOR); |
| 92 | + |
| 93 | + return truncateString(result.trim(), 200).replace("\n", EXCERPT_LINE_SEPARATOR); |
| 94 | + } |
| 95 | + |
| 96 | + private static final Pattern HTML_PATTERN = Pattern.compile( |
| 97 | + "(?is)<(?:!DOCTYPE|/?(?:[a-z][a-z0-9]*))[^>]*>" |
| 98 | + ); |
| 99 | + |
| 100 | + private static boolean isHtml(String content) { |
| 101 | + if (content == null || content.isEmpty()) { |
| 102 | + return false; |
| 103 | + } |
| 104 | + |
| 105 | + return HTML_PATTERN.matcher(content).find(); |
| 106 | + } |
| 107 | + |
| 108 | + private static String sanitizeHtml(String html) { |
| 109 | + // Remove script tags and their content |
| 110 | + String sanitized = html.replaceAll("(?is)<script[^>]*>.*?</script>", ""); |
| 111 | + |
| 112 | + // Remove event handlers (onclick, onerror, onload, etc.) |
| 113 | + sanitized = sanitized.replaceAll("(?i)\\s+on\\w+\\s*=\\s*['\"][^'\"]*['\"]", ""); |
| 114 | + sanitized = sanitized.replaceAll("(?i)\\s+on\\w+\\s*=\\s*[^\\s>]+", ""); |
| 115 | + |
| 116 | + return sanitized.trim(); |
84 | 117 | } |
85 | 118 |
|
86 | 119 | @NonNull |
|
0 commit comments