Merge remote-tracking branch 'origin/main'

This commit is contained in:
Tobi Schäfer 2024-03-23 23:10:49 +01:00
commit 09384070f9
32 changed files with 2633 additions and 576 deletions

View file

@ -39,11 +39,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -54,7 +54,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@ -68,4 +68,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3

View file

@ -13,7 +13,7 @@ jobs:
pull-requests: write
steps:
- uses: actions/stale@v8
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'Stale issue message'

1
.nvmrc Normal file
View file

@ -0,0 +1 @@
lts

View file

@ -1,5 +1,21 @@
# Change Log
## 2024 January 13
* Fix cross-site scripting vulnerability in search output
* Fix new choices being added to an existing poll at the wrong position
* Fix errors in the client-side code filtering the referrers
* Correctly load and initialize Alpine.js
## 2024 January 7
* Upgrade third-party dependencies
## 2023 December 30
* Fix initialization of MarkDown in UIKit editor
* Add support for images in webp format
## 2023 August 26
* Migrate from Yarn back to NPM

View file

@ -2,8 +2,8 @@ plugins {
id 'base'
id 'java'
id 'com.github.node-gradle.node' version '7.0.0'
id 'org.ajoberstar.grgit' version '5.2.0' apply false
id 'com.github.node-gradle.node' version '7.0.1'
id 'org.ajoberstar.grgit' version '5.2.1' apply false
}
import org.ajoberstar.grgit.Grgit
@ -25,7 +25,7 @@ allprojects {
project.ext.distVersion = { ->
def json = new groovy.json.JsonSlurper()
def packageData = json.parse(file("${rootProject.projectDir}/package.json"))
return packageData.version.substring(0, packageData.version.size() - 2)
return packageData.version;
}
project.ext.antvilleBuildDir = "${rootProject.buildDir}/tmp/antville"
@ -52,7 +52,7 @@ dependencies {
implementation 'org.commonmark:commonmark-ext-autolink:0.21.0'
implementation 'org.commonmark:commonmark-ext-gfm-strikethrough:0.21.0'
implementation 'org.commonmark:commonmark-ext-gfm-tables:0.21.0'
implementation 'org.jsoup:jsoup:1.16.1'
implementation 'org.jsoup:jsoup:1.17.2'
implementation 'rome:rome:1.0'
implementation('org.lesscss:lesscss:1.7.0.1.1') {
@ -99,7 +99,7 @@ task installAntville {
from "$tempDir/code/app.properties"
into "$antvilleBuildDir/code"
filter { line -> line.replaceAll('(version =) 0.0.0', "\$1 $version.$hash")
.replaceAll('(buildDate =) 18 Oct 1971', "\$1 $date")
.replaceAll('(buildDate =) 18 Jun 2001', "\$1 $date")
}
}

View file

@ -55,10 +55,7 @@ Api.blogger._getContentParts = function(content) {
* @returns {Object} Properties: userid, nickname and url
*/
Api.blogger.getUserInfo = function(appKey, name, password) {
var user = User.getByName(name);
if (!user) {
throw Error('User ' + name + ' does not exist on this server');
}
var user = Api.getUser(name, password);
return {
userid: name,
nickname: name,

View file

@ -10,7 +10,7 @@
<div class='av-choice uk-form-row'>
<div class='uk-form-label'>#<% param.index %></div>
<div>
<input type='text' name='title' class='uk-width-1-1' value='<% choice.title %>' />
<input type='text' name='title' class='uk-width-1-1' value='<% choice.title %>' x-init="counter += 1"/>
</div>
</div>

View file

@ -22,7 +22,7 @@
String.ELLIPSIS = '…';
app.addRepository(app.dir + '/../lib/jdom-1.0.jar');
app.addRepository(app.dir + '/../lib/jsoup-1.16.1.jar');
app.addRepository(app.dir + '/../lib/jsoup-1.17.2.jar');
app.addRepository(app.dir + '/../lib/lesscss-1.7.0.1.1.jar');
app.addRepository(app.dir + '/../lib/rome-1.0.jar');

View file

@ -41,8 +41,15 @@ var renderMarkdown = (function() {
.extensions(extensions)
.build();
// Save HTML entities like `&#150;` from being erroneously encoded
// See <https://github.com/commonmark/commonmark-java/issues/307>
const entityRegex = /&(#\d+;)/g;
const entityMarker = "<ampersand/>";
const entityMarkerRegex = new RegExp(entityMarker + entityRegex.source.substring(1), 'g');
return function(str) {
str = str.replace(entityRegex, entityMarker + '$1');
const document = parser.parse(str);
return renderer.render(document);
return renderer.render(document).replace(entityMarkerRegex, '&$1');
};
})();

View file

@ -103,6 +103,8 @@ Image.getFileExtension = function(type) {
case 'image/png':
case 'image/x-png':
return '.png';
case 'image/webp':
return '.webp';
}
return null;
}

View file

@ -36,7 +36,7 @@
<script>
// Setup drag&drop for image uploads
(function() {
document.addEventListener("alpine:init", () => {
const dropElement = document.querySelector('.av-upload-drop');
const parent = location.href.lastIndexOf('/layout/images/') > -1 ? 'layout' : 'site';
const uploadUrl = '<% site.images.href upload %>?parent=' + parent;
@ -84,5 +84,5 @@
error: restoreDrop,
abort: restoreDrop
});
})();
});
</script>

View file

@ -84,7 +84,7 @@
<% poll.link . ' ' class='uk-icon-button uk-icon-link uk-text-middle' %>
</h1>
<div class='uk-article-meta'><% poll.skin $HopObject#meta %></div>
<form class='uk-margin-top uk-form uk-form-stacked' method="post" action="<% response.action %>" x-data='{ counter: 2 }'>
<form class='uk-margin-top uk-form uk-form-stacked' method="post" action="<% response.action %>" x-data='{ counter: 1 }'>
<div class='uk-form-row'>
<div class='uk-form-label'><% gettext Question %></div>
<div class='uk-form-controls'>
@ -93,9 +93,11 @@
</div>
<fieldset class='uk-margin-top'>
<legend><% gettext Choices %></legend>
<% poll.input choices %>
<div class="uk-margin-bottom">
<% poll.input choices %>
</div>
<div class='uk-text-small uk-form-row' id='av-add-choice' hidden :hidden='false'>
<a href='javascript:' @click='const choice = document.querySelectorAll(".av-choice")[counter - 1]; const clone = choice.cloneNode(true); counter += 1; clone.querySelector(".uk-form-label").innerText = "#" + counter; const input = clone.querySelector("input"); input.value = ""; choice.insertAdjacentElement("afterEnd", clone); input.focus();'>
<a href='javascript:' @click='const choice = document.querySelector(".av-choice:last-child"); const clone = choice.cloneNode(true); clone.querySelector(".uk-form-label").innerText = `#${counter}`; const input = clone.querySelector("input"); input.value = ""; choice.insertAdjacentElement("afterEnd", clone); input.focus();'>
<i class='uk-icon-plus'></i>
<% gettext "Add Choice" %>
</a>

View file

@ -115,7 +115,7 @@
<dd></dd>
<dd><% gettext '{0} log entries' <% param.entries %> %></dd>
<dt><% gettext Version %></dt>
<dd><% version %></dd>
<dd>φ (<% version %>)</dd>
<dt><% gettext Build %></dt>
<dd>
<% link <% version hash prefix='https://github.com/antville/antville/commit/' %> <% version hash %> %> (<% version date %>)

View file

@ -24,19 +24,19 @@ Root.VERSION = (function(versionString, buildDate) {
// A valid version string is e.g. '1.2.3alpha.c0ffee'.
// Repositories could add something like '-compatible' to it,
// FIXME: This should be refactored for modular extension.
var re = /^(\d+)\.(\d+)(?:\.(\d+))?(.+)?\.([a-f0-9]+)(?:-(.*))?$/;
var re = /^(\d+)\.(\d+)(?:\.(\d+))?\.([a-f0-9]+)(?:-(.*))?$/;
var parts = re.exec(versionString);
if (parts) {
var result = {
date: new Date(buildDate).toLocaleDateString(),
hash: parts[4],
major: parts[1],
parts: parts,
toString: function() {return parts[0]},
major: parseInt(parts[1]),
hash: parts[5],
date: new Date(buildDate).toLocaleDateString()
toString: function() { return parts[1] }
};
result.minor = result.major + parseInt(parts[2] || 0) / 10;
result.minor = result.major + '.' + (parts[2] || 0);
result.bugfix = result.minor + '.' + (parts[3] || 0);
result.development = parts[4] || '';
result.development = parts[5] || '';
result['default'] = result[parts[3] ? 'bugfix' : 'minor'] + result.development +
(parts[6] ? '-' + parts[6] : String.EMPTY);
return result;

View file

@ -214,7 +214,7 @@
</form>
<script>
(function() {
document.addEventListener("alpine:init", () => {
// Group related <option> elements by inserting additional <optgroup> elements.
const dom = window;
const groups = [];
@ -246,7 +246,7 @@
// Correct the selected index
timeZone.selectedIndex = Array.from(timeZone.options).indexOf(timeZone.querySelector('option[selected]'));
});
})();
});
</script>
<% #meta %>
@ -336,7 +336,7 @@
<% if <% property search.provider %> is null then '' else <% site.skin $Site#moreResults %> %>
<% #moreResults %>
<a href='<% property search.provider %>?q=<% request.q %>+site:<% site.href %>' class='uk-button uk-align-right'>
<a href='<% property search.provider %>?q=<% request.q encoding="url" %>+site:<% site.href %>' class='uk-button uk-align-right'>
<% gettext 'Search with {0}' <% property search.provider | replace 'https?://([^/]+).*' '$1' %> %>
<i class='uk-icon uk-icon-arrow-circle-right'></i>
</a>
@ -1135,7 +1135,7 @@ a.gs-title:hover {
</table>
<script>
(function() {
document.addEventListener("alpine:init", () => {
const query = new Antville.Query();
const spamFilter = new Antville.Filter(JSON.parse('<% site.spamfilter %>'));
const searchFilter = new Antville.Filter(query.filter);
@ -1228,12 +1228,12 @@ a.gs-title:hover {
if (index2 <= index) return;
if (element2.innerHTML === html) {
count += parseInt(document.querySelector('.av-referrer-count')[index2].innerText, 10);
count += parseInt(document.querySelectorAll('.av-referrer-count')[index2].innerText, 10);
element2.closest('.av-referrer-row').classList.add('av-delete');
}
});
if (count) countElement.innerHTML = parseInt(countElement.html(), 10) + count;
if (count) countElement.innerHTML = parseInt(countElement.innerHTML, 10) + count;
});
document.querySelectorAll('.av-referrer-row.av-delete').forEach(function(element) {
@ -1249,7 +1249,7 @@ a.gs-title:hover {
});
sortedRows.forEach(function(row) { table.appendChild(row); });
})();
});
</script>
<% #referrer %>

View file

@ -37,7 +37,7 @@
</form>
<script>
(function() {
document.addEventListener("alpine:init", () => {
// Setup skin editor
let mode = 'application/x-helma-skin';
@ -59,7 +59,7 @@
tabSize: 3,
viewportMargin: Infinity
});
})();
});
</script>
<% #compare %>

View file

@ -30,8 +30,8 @@
background-color: #f2fae3;
}
</style>
<script src='<% site.href main.js %>'></script>
<script src='<% root.static ../../scripts/editor.min.js %>'></script>
<script defer src='<% site.href main.js %>'></script>
</head>
<body>
<span class='uk-margin-right uk-float-right'>

View file

@ -62,7 +62,7 @@ else
<% #editor %>
<script>
// Load additonal scripts and styles for UIkits HTML editor plugin
(function() {
document.addEventListener("alpine:init", () => {
const _form = document.querySelector('#av-story-form');
if (!_form) return;
@ -296,5 +296,5 @@ else
scheduler();
}
})();
});
</script>

View file

@ -692,43 +692,8 @@ Story.prototype.format_filter = function(value, param, mode) {
}
Story.prototype.linebreak_filter = function (value, param, mode) {
if (mode === 'markdown') {
// FIXME: should be obsolete
var mdLineBreakMarker = new RegExp('<!--av-break-->', 'g');
var mdQuoteMarker = new RegExp('<!--av-quote-->', 'g');
var mdCodeMarker = new RegExp('<!--av-code-->', 'g');
return value
// Prevent Markdown for linebreaks (lines ending with 2 spaces) as well as
// code segments (4 spaces) to be removed by Helmas format() method
.replace(/ {2}$/gm, mdLineBreakMarker.source)
.replace(/^ {4}/gm, mdCodeMarker.source)
// Prevent Markdown for quote segments (lines starting with >)
// to be removed by Helmas format method()
.replace(/^(>+)/gm, function(item) {
return mdQuoteMarker.source.repeat(item.length);
})
// Apply Helmas format() method for good
// FIXME: This should probably be moved to the compat layer
.format(value)
// Replace trailing HTML linebreaks with Markdown ones
.replace(/<br[^>]*>$/gm, String.SPACE.repeat(2))
// Replace trailing HTML linebreaks inserted by Helmas format() method with Markdown ones
//.replace(/<br\s*class=['"]?helma-format['"]?\s*\/?>/g, String.SPACE.repeat(2))
// Restore Markdown quote segments
.replace(mdQuoteMarker, '>')
// Restore Markdown linebreaks and code segments
.replace(mdLineBreakMarker, String.SPACE.repeat(2))
.replace(mdCodeMarker, String.SPACE.repeat(4));
} else {
var parts = value.split(/(?:\n\n|\r\r|\r\n\r\n)+/);
value = format('<p>' + parts.join('</p><p>') + '</p>');
}
return value;
};
Story.prototype.code_filter = function (value, param) {
value = this.linebreak_filter(value, param);
return this.markdown_filter(value, param);
var parts = value.split(/(?:\n\n|\r\r|\r\n\r\n)+/);
return format('<p>' + parts.join('</p><p>') + '</p>');
};
/**

View file

@ -23,35 +23,37 @@
<script>
// Load additional script for Collage jQuery plugin
if ('<% tag.type parent %>' === 'Image') {
const script = document.createElement('script');
document.addEventListener("alpine:init", () => {
if ('<% tag.type parent %>' === 'Image') {
const script = document.createElement('script');
script.onload = function() {
$(function() {
let resizeTimer = null;
script.onload = function() {
$(function() {
let resizeTimer = null;
const collage = () => {
$('.av-collage').removeWhitespace().collagePlus({
allowPartialLastRow: true,
fadeSpeed: 'slow'
const collage = () => {
$('.av-collage').removeWhitespace().collagePlus({
allowPartialLastRow: true,
fadeSpeed: 'slow'
});
};
$('.av-collage').collageCaption();
$(window).bind('resize', function() {
$('.av-tagged-image').css('opacity', 0);
if (resizeTimer) clearTimeout(resizeTimer);
resizeTimer = setTimeout(collage, 200);
});
};
$('.av-collage').collageCaption();
$(window).bind('resize', function() {
$('.av-tagged-image').css('opacity', 0);
if (resizeTimer) clearTimeout(resizeTimer);
resizeTimer = setTimeout(collage, 200);
collage();
});
};
collage();
});
};
script.src = '<% root.static ../../scripts/gallery.min.js %>';
document.head.appendChild(script);
}
script.src = '<% root.static ../../scripts/gallery.min.js %>';
document.head.appendChild(script);
}
});
</script>
<% #simple %>

View file

@ -17,7 +17,7 @@
# The current build version and date
version = 0.0.0
buildDate = 18 Oct 1971
buildDate = 18 Jun 2001
# The root site
rootId = 1

View file

@ -15,14 +15,14 @@
<script>
// Load additional script for Googles custom search
(function() {
document.addEventListener("alpine:init", () => {
var cx = '008141500676255803966:bw4l-wnuz44';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
gcse.src = (document.location.protocol === 'https:' ? 'https:' : 'http:') +
'//www.google.com/cse/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
});
</script>

View file

@ -1,4 +1,2 @@
org.gradle.console = plain
antville.repo.url = https://github.com/antville/antville.git
helma.download.url = https://github.com/antville/helma/releases/download/v20200614/helma-20200614.tgz

Binary file not shown.

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

14
gradlew vendored
View file

@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -202,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \

2957
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "antville",
"version": "1.618.0",
"version": "1.618",
"description": "Antville is an open source project aimed at the development of a high performance, feature rich weblog hosting software. It can easily host up to several thousands of sites (the number of weblogs is rather limited by the installation owners choice and server power than by software limitations).",
"main": "main.js",
"directories": {
@ -31,16 +31,16 @@
"author": "The Antville People",
"license": "Apache-2.0",
"dependencies": {
"alpinejs": "3.13.0",
"codemirror": "5.65.14",
"alpinejs": "3.13.3",
"codemirror": "5.65.16",
"jquery": "3.7.1",
"jquery-collagePlus": "github:antville/jquery-collagePlus#0.3.4",
"js-md5": "0.7.3",
"js-md5": "0.8.3",
"uikit": "2.27.4"
},
"devDependencies": {
"browserify": "17.0.0",
"generate-license-file": "2.0.0",
"generate-license-file": "3.0.1",
"jsdoc": "4.0.2",
"less": "4.2.0",
"less-plugin-clean-css": "1.5.1",

View file

@ -7,25 +7,25 @@
":pinVersions",
":semanticCommitsDisabled"
],
"labels": ["Dependencies"],
"labels": ["dependencies"],
"lockFileMaintenance": { "enabled": true },
"packageRules": [
{
"matchManagers": ["gradle"],
"labels": ["java"]
"addLabels": ["java", "build"]
},
{
"matchManagers": ["npm"],
"labels": ["javascript"]
"addLabels": ["javascript"]
},
{
"matchPackagePrefixes": [
"org.commonmark:",
"org.jsoup:",
"org.commonmark:",
"org.jsoup:",
"org.lesscss:",
"rome:"
],
"labels": ["javascript"]
"addLabels": ["java", "runtime"]
}
]
}

View file

@ -144,7 +144,7 @@ task buildLicenses(type: Copy) {
group 'build'
dependsOn 'installJars'
def licensesDir = "$antvilleInstallDir/licenses"
def licensesDir = "$helmaInstallDir/licenses"
inputs.files generateLicenseReport
outputs.dir licensesDir

View file

@ -1,5 +1,5 @@
window.CodeMirror = require('codemirror/lib/codemirror');
window.marked = require('marked/lib/marked.cjs');
window.marked = require('marked/lib/marked.cjs').marked;
require('codemirror/mode/css/css');
require('codemirror/mode/gfm/gfm');

View file

@ -6,8 +6,6 @@ require('uikit/dist/js/components/form-password');
require('uikit/dist/js/components/tooltip');
require('uikit/dist/js/components/upload');
Alpine.start();
const Antville = window.Antville = {};
Antville.hash = require('js-md5/src/md5');
@ -263,3 +261,5 @@ Antville.http = (method, url, options) => {
httpClient.send(_data);
return this;
};
Alpine.start();