Compare commits
	
		
			78 commits
		
	
	
		
			renovate/m
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1476c9b19f | |||
| df28d40645 | |||
| 29f7ca5ae3 | |||
| 3f2bf9c3dc | |||
| f9bc64d1ed | |||
| f6668636a9 | |||
| 1001b3b503 | |||
| 96ceb1d5f3 | |||
| 27cdc5104b | |||
| 745ce5bfca | |||
| c4abd27ac7 | |||
| 6b88318bcd | |||
| 0cf9cf7af2 | |||
| 96f2dce50f | |||
| f786b40961 | |||
| 8caf790529 | |||
| e6c974120b | |||
| 6723df912e | |||
| 436862e87a | |||
| 36a12effb2 | |||
| 2994a4becc | |||
| 99e8b204fd | |||
| c42c0a7a17 | |||
| b7543cf615 | |||
| fc084f6e52 | |||
| 6fc73d2320 | |||
| 9b5cc988dd | |||
| 04b210b464 | |||
| 4c011f1e1b | |||
| bc7894ecc1 | |||
| a3fbf72f38 | |||
| de2150693f | |||
| 38181e8e00 | |||
| 8adbd23569 | |||
| e3a7732837 | |||
| d9d3c9b863 | |||
| 808bc48ab9 | |||
| 6ebdd6aa31 | |||
| 2ff29317e5 | |||
| 84333d05cd | |||
| 3a8997ca5c | |||
| 8212600d40 | |||
| cd8baa4ac1 | |||
| 1bb5a093da | |||
| 2c6dd96cd7 | |||
| 6f6ea55b7b | |||
| b1a14ad87b | |||
| d1ead6e081 | |||
| 94557dd28e | |||
| e2e67cf2cc | |||
| 11b226b272 | |||
| 1925916220 | |||
| b1296fb093 | |||
| 51bc14c3a4 | |||
| 3e5af064b0 | |||
| 6401300189 | |||
| 45b19e3217 | |||
| ffb259a01c | |||
| 84abcde037 | |||
| 9e870e6cd3 | |||
| 1e32c8eb89 | |||
| 9143faf35e | |||
| 79d83389f2 | |||
| 90e45c9115 | |||
| 3dbcd792a6 | |||
| 973b3493cb | |||
| 441d952b35 | |||
| d67d0235bd | |||
| fa59a27858 | |||
| 304ea4e456 | |||
| 0165e7c80e | |||
| 62630ae068 | |||
| 26975a109a | |||
| a943124d45 | |||
| c087cb731e | |||
| c5f68013b1 | |||
| ed575bc4c5 | |||
|  | 1cf738767c | 
					 29 changed files with 297 additions and 150 deletions
				
			
		
							
								
								
									
										22
									
								
								.github/workflows/build.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								.github/workflows/build.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| name: Build | ||||
| 
 | ||||
| on: | ||||
|   push: | ||||
|     paths: | ||||
|       - .github/workflows/build.yml | ||||
|       - build.gradle | ||||
|       - settings.gradle | ||||
|       - src/** | ||||
|       - launcher/build.gradle | ||||
|       - launcher/src/** | ||||
|   workflow_dispatch: | ||||
| 
 | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: antville | ||||
| 
 | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
| 
 | ||||
|       - name: Compile with Gradle | ||||
|         run: ./gradlew :compileJava | ||||
							
								
								
									
										38
									
								
								.github/workflows/deploy.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								.github/workflows/deploy.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -1,15 +1,39 @@ | |||
| name: Deploy (Production) | ||||
| name: Deploy | ||||
| 
 | ||||
| on: workflow_dispatch | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|     inputs: | ||||
|       hostname: | ||||
|         description: Hostname | ||||
|         type: string | ||||
|         required: true | ||||
|         default: antville.org | ||||
| 
 | ||||
| jobs: | ||||
|   deploy: | ||||
|   stage: | ||||
|     runs-on: antville | ||||
| 
 | ||||
|     environment: | ||||
|       name: antville.org | ||||
|       url: https://antville.org | ||||
|       name: production | ||||
|       url: ${{ inputs.hostname }} | ||||
| 
 | ||||
|     steps: | ||||
|       - name: Copy files to production server | ||||
|         run: ssh staging-server deploy-helma | ||||
|       - uses: actions/checkout@v4 | ||||
| 
 | ||||
|       - name: Build with Gradle | ||||
|         run: ./gradlew installDist | ||||
| 
 | ||||
|       - name: Copy build files to server | ||||
|         run: | | ||||
|           rsync ./build/install/helma/ ${{ inputs.hostname }}:./ \ | ||||
|             --verbose --archive --delete --compress \ | ||||
|             --filter '+ /bin' \ | ||||
|             --filter '+ /extras' \ | ||||
|             --filter '+ /launcher.jar' \ | ||||
|             --filter '- /lib/ext' \ | ||||
|             --filter '+ /lib' \ | ||||
|             --filter '+ /modules' \ | ||||
|             --filter '- /*' | ||||
| 
 | ||||
|       - name: Restart Helma | ||||
|         run: ssh ${{ inputs.hostname }} restart | ||||
|  |  | |||
							
								
								
									
										34
									
								
								.github/workflows/release.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								.github/workflows/release.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -9,16 +9,27 @@ permissions: | |||
|   contents: write | ||||
| 
 | ||||
| jobs: | ||||
|   build: | ||||
|   release: | ||||
|     runs-on: antville | ||||
| 
 | ||||
|     env: | ||||
|       GH_TOKEN: ${{ github.token }} | ||||
|       GH_TOKEN: ${{ secrets.GH_TOKEN }} | ||||
|       LC_TIME: en_US.UTF-8 | ||||
|       TODAY: $(date +'%d %b %Y') | ||||
| 
 | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
| 
 | ||||
|       - name: Create release notes | ||||
|         id: create_release_notes | ||||
|         run: | | ||||
|           release_notes=$(npx git-cliff@latest --latest) | ||||
|           # Write the release notes as a heredoc to the workflow output | ||||
|           # ⚠️ No white space around `<<` is crucial! | ||||
|           echo "release_notes<<.eot0x03" >> $GITHUB_OUTPUT | ||||
|           echo "$release_notes" >> $GITHUB_OUTPUT | ||||
|           echo ".eot0x03" >> $GITHUB_OUTPUT | ||||
| 
 | ||||
|       - name: Build with Gradle | ||||
|         run: ./gradlew assembleDist | ||||
|  | @ -29,23 +40,20 @@ jobs: | |||
|           direction: upload | ||||
|           url: https://code.host.antville.org | ||||
|           token: ${{ github.token }} | ||||
|           title: ${{ env.TODAY }} | ||||
|           #tag: $(date +'%Y.%m.%d') | ||||
|           title: Helma ${{ github.ref_name }} | ||||
|           release-dir: build/distributions | ||||
|           release-notes-assistant: true | ||||
|           release-notes: ${{ steps.create_release_notes.outputs.release_notes }} | ||||
|           verbose: true | ||||
| 
 | ||||
|       - name: Create release at GitHub | ||||
|         # FIXME: Currently only outputs gh command; adapt for Forgejo | ||||
|         run: | | ||||
|           echo gh release create "$GITHUB_REF_NAME" \ | ||||
|           gh release create "$GITHUB_REF_NAME" \ | ||||
|             --repo "$GITHUB_REPOSITORY" \ | ||||
|             --title "$(date +'%d %b %Y')" \ | ||||
|             --generate-notes | ||||
|             --title "Helma ${{ github.ref_name }}" \ | ||||
|             --notes "${{ steps.create_release_notes.outputs.release_notes }}" | ||||
| 
 | ||||
|       - name: Upload release assets to GitHub | ||||
|         # FIXME: Currently only outputs gh command; adapt for Forgejo | ||||
|         run: | | ||||
|           echo gh release upload "$GITHUB_REF_NAME" \ | ||||
|             build/distributions/helma-*.* \ | ||||
|           gh release upload "$GITHUB_REF_NAME" build/distributions/helma-*.* \ | ||||
|             --repo "$GITHUB_REPOSITORY" \ | ||||
|             --clobber | ||||
|  |  | |||
							
								
								
									
										32
									
								
								.github/workflows/stage.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								.github/workflows/stage.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -1,32 +0,0 @@ | |||
| name: Deploy (Staging) | ||||
| 
 | ||||
| on: workflow_dispatch | ||||
| 
 | ||||
| jobs: | ||||
|   stage: | ||||
|     runs-on: antville | ||||
| 
 | ||||
|     environment: | ||||
|       name: stage | ||||
|       url: ${{ vars.stage_url }} | ||||
| 
 | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
| 
 | ||||
|       - name: Build with Gradle | ||||
|         run: ./gradlew installDist | ||||
| 
 | ||||
|       - name: Publish to staging server | ||||
|         run: | | ||||
|           rsync ./build/install/helma/ staging-server:./ \ | ||||
|             --verbose --archive --delete --compress \ | ||||
|             --filter '+ /bin' \ | ||||
|             --filter '+ /extras' \ | ||||
|             --filter '+ /launcher.jar' \ | ||||
|             --filter '- /lib/ext' \ | ||||
|             --filter '+ /lib' \ | ||||
|             --filter '+ /modules' \ | ||||
|             --filter '- /*' | ||||
| 
 | ||||
|       - name: Restart Helma | ||||
|         run: ssh staging-server restart | ||||
							
								
								
									
										32
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,22 +1,30 @@ | |||
| .gradle | ||||
| .idea | ||||
| .settings | ||||
| build | ||||
| # Generally ignore hidden files | ||||
| .* | ||||
| 
 | ||||
| /apps | ||||
| # Manage some Codium configuration | ||||
| .vscode/* | ||||
| !.vscode | ||||
| !.vscode/extensions.json | ||||
| !.vscode/launch.json | ||||
| !.vscode/settings.json | ||||
| !.vscode/tasks.json | ||||
| 
 | ||||
| # Ignore files created during build or run | ||||
| /bin | ||||
| /backups | ||||
| /db | ||||
| build | ||||
| /docs | ||||
| /extras | ||||
| /lib | ||||
| /licenses | ||||
| /log | ||||
| 
 | ||||
| # Ignore files managed in src/dist | ||||
| /*.properties | ||||
| /apps | ||||
| /db | ||||
| /extras | ||||
| /launcher.jar | ||||
| /static | ||||
| 
 | ||||
| /*.properties | ||||
| /launcher.jar | ||||
| /passwd | ||||
| /start.* | ||||
| 
 | ||||
| # Manage Gradle configuration | ||||
| !/gradle.properties | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| 11.0 | ||||
| 17 | ||||
|  |  | |||
							
								
								
									
										21
									
								
								.vscode/launch.json
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								.vscode/launch.json
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| { | ||||
|   // Use IntelliSense to learn about possible attributes. | ||||
|   // Hover to view descriptions of existing attributes. | ||||
|   // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||
|   "version": "0.2.0", | ||||
|   "configurations": [ | ||||
|     { | ||||
|       "type": "java", | ||||
|       "name": "Current File", | ||||
|       "request": "launch", | ||||
|       "mainClass": "${file}" | ||||
|     }, | ||||
|     { | ||||
|       "type": "java", | ||||
|       "name": "Debug", | ||||
|       "request": "launch", | ||||
|       "mainClass": "helma.main.Server", | ||||
|       "projectName": "helma_" | ||||
|     } | ||||
|   ] | ||||
| } | ||||
|  | @ -1,6 +1,6 @@ | |||
| # License | ||||
| 
 | ||||
| Copyright (c) 1999-2008 Helma Project. All rights reserved. | ||||
| Copyright (c) 1999-2025 Helma Project. All rights reserved. | ||||
| 
 | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions | ||||
|  |  | |||
|  | @ -2,8 +2,8 @@ | |||
| 
 | ||||
| ## TL;DR | ||||
| 
 | ||||
| - Make sure you have Java 11 or higher installed | ||||
| - Download and unpack the [latest release](https://github.com/antville/helma/releases) | ||||
| - Make sure you have Java 17 or higher installed | ||||
| - Download and unpack the [latest release](https://code.host.antville.org/antville/helma/releases) | ||||
| - Invoke `./bin/helma`, resp. `./bin/helma.bat`, depending on your platform | ||||
| - Direct your web browser to <http://localhost:8080> | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										36
									
								
								build.gradle
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								build.gradle
									
										
									
									
									
								
							|  | @ -18,8 +18,8 @@ allprojects { | |||
|   apply plugin: 'java' | ||||
| 
 | ||||
|   java { | ||||
|     sourceCompatibility = JavaVersion.VERSION_11 | ||||
|     targetCompatibility = JavaVersion.VERSION_11 | ||||
|     sourceCompatibility = JavaVersion.VERSION_17 | ||||
|     targetCompatibility = JavaVersion.VERSION_17 | ||||
|   } | ||||
| 
 | ||||
|   repositories { | ||||
|  | @ -42,15 +42,6 @@ if (JavaVersion.current().isJava8Compatible()) { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| sourceSets { | ||||
|   main { | ||||
|     java { | ||||
|       // Sources in `src` will be available here after processing | ||||
|       srcDirs = ["$buildDir/src/main/java"] | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| configurations { | ||||
|   // Wrapping implementation because it does not allow access to its files | ||||
|   // (i.e. cannot be resolved) | ||||
|  | @ -58,16 +49,17 @@ configurations { | |||
| } | ||||
| 
 | ||||
| dependencies { | ||||
|   implementation 'com.google.code.gson:gson:2.11.0' | ||||
|   implementation 'commons-codec:commons-codec:1.17.1' | ||||
|   implementation 'commons-fileupload:commons-fileupload:1.5' | ||||
|   implementation 'commons-logging:commons-logging:1.3.4' | ||||
|   implementation 'com.google.code.gson:gson:2.12.1' | ||||
|   implementation 'commons-codec:commons-codec:1.18.0' | ||||
|   implementation 'org.apache.commons:commons-fileupload2-core:2.0.0-M2' | ||||
|   implementation 'org.apache.commons:commons-fileupload2-jakarta:2.0.0-M1' | ||||
|   implementation 'commons-logging:commons-logging:1.3.5' | ||||
|   implementation 'commons-net:commons-net:3.11.1' | ||||
|   implementation 'com.sun.mail:javax.mail:1.6.2' | ||||
|   implementation 'javax.servlet:javax.servlet-api:4.0.1' | ||||
|   implementation 'jakarta.servlet:jakarta.servlet-api:5.0.0' | ||||
|   implementation 'org.ccil.cowan.tagsoup:tagsoup:1.2.1' | ||||
|   implementation 'org.eclipse.jetty:jetty-servlet:9.4.56.v20240826' | ||||
|   implementation 'org.eclipse.jetty:jetty-xml:9.4.56.v20240826' | ||||
|   implementation 'org.eclipse.jetty.ee9:jetty-ee9-servlet:12.0.19' | ||||
|   implementation 'org.eclipse.jetty:jetty-xml:12.0.19' | ||||
|   implementation 'org.mozilla:rhino-all:1.8.0' | ||||
|   implementation 'org.sejda.imageio:webp-imageio:0.1.6' | ||||
|   implementation 'xerces:xercesImpl:2.12.2' | ||||
|  | @ -156,9 +148,11 @@ installDist { | |||
|   dependsOn build | ||||
| } | ||||
| 
 | ||||
| tasks.register('processSource', Sync) { | ||||
| def processSource = tasks.register('processSource', Sync) { | ||||
|   def gitOutput = new ByteArrayOutputStream() | ||||
| 
 | ||||
|   outputs.dir "${project.buildDir}/src" | ||||
| 
 | ||||
|   exec { | ||||
|     commandLine 'git', 'rev-parse', '--short', 'HEAD' | ||||
|     standardOutput = gitOutput | ||||
|  | @ -173,9 +167,11 @@ tasks.register('processSource', Sync) { | |||
|       .replaceAll('__builddate__', new Date().format("d MMM yyyy")) | ||||
|       .replaceAll('__commithash__', gitOutput.toString().trim()) | ||||
|       .replaceAll('__version__', version) | ||||
|   } into "${project.buildDir}/src" | ||||
|   } into outputs.files.singleFile | ||||
| } | ||||
| 
 | ||||
| tasks.compileJava.source = processSource.map { it.outputs.files } | ||||
| 
 | ||||
| tasks.register('update') { | ||||
|   dependsOn installDist | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										52
									
								
								cliff.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								cliff.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,52 @@ | |||
| # git-cliff ~ default configuration file | ||||
| # https://git-cliff.org/docs/configuration | ||||
| # | ||||
| # Lines starting with "#" are comments. | ||||
| # Configuration options are organized into tables and keys. | ||||
| # See documentation for more information on available options. | ||||
| 
 | ||||
| [changelog] | ||||
| trim = true | ||||
| 
 | ||||
| header = "## Changes" | ||||
| 
 | ||||
| body = """ | ||||
| {% for group, commits in commits | filter(attribute="merge_commit") | group_by(attribute="group") %} | ||||
|   ### {{ group | striptags | trim | upper_first }} | ||||
|   {% for commit in commits %} | ||||
|     * [<tt>{{ commit.id | split(pat="") | slice(end=11) | join() }}</tt>]\ | ||||
|       (https://code.host.antville.org/antville/helma/commit/{{ commit.id }}) \ | ||||
|       {% if commit.breaking %}**Breaking:** {% endif %}\ | ||||
|       {{ commit.message | split(pat="\\n") | first | upper_first | escape }}\ | ||||
|   {% endfor %} | ||||
| {% endfor %} | ||||
| 
 | ||||
| **Full Changelog:** [{{ previous.version }} → {{ version }}]\ | ||||
| (https://code.host.antville.org/antville/helma/compare/\ | ||||
| {{ previous.version | urlencode }}..{{ version | urlencode }})\n\n | ||||
| """ | ||||
| 
 | ||||
| footer = """ | ||||
| Generated by [git-cliff](https://git-cliff.org/). | ||||
| """ | ||||
| 
 | ||||
| [git] | ||||
| conventional_commits = false | ||||
| filter_commits = false | ||||
| filter_unconventional = false | ||||
| protect_breaking_commits = false | ||||
| sort_commits = "newest" | ||||
| split_commits = false | ||||
| topo_order = false | ||||
| 
 | ||||
| commit_parsers = [ | ||||
|   { message = "^Apply \\d+ suggestion", skip = true }, | ||||
|   { message = "^Merge .*(branch|dependabot|dependency|renovate)", skip = true }, | ||||
|   { message = "^Lock file maintenance", skip = true }, | ||||
|   { message = "yarn\\.lock", skip = true }, | ||||
| 
 | ||||
|   { message = "^[Ff]ix", group = "<!-- 0 --> 🐛 Bug Fixes" }, | ||||
|   { field = "author.name", pattern = "[Rr]enovate|[Dd]ependabot", group = "<!-- 3 --> 📦 Dependency Updates" }, | ||||
|   { message = "^Merge pull request", group = "<!-- 1 --> 🔀 Merges" }, | ||||
|   { message = ".*", group = "<!-- 2 --> Uncategorized" }, | ||||
| ] | ||||
							
								
								
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
										
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
										
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,6 @@ | |||
| distributionBase=GRADLE_USER_HOME | ||||
| distributionPath=wrapper/dists | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip | ||||
| networkTimeout=10000 | ||||
| validateDistributionUrl=true | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
|  |  | |||
							
								
								
									
										6
									
								
								gradlew
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								gradlew
									
										
									
									
										vendored
									
									
								
							|  | @ -114,7 +114,7 @@ case "$( uname )" in                #( | |||
|   NONSTOP* )        nonstop=true ;; | ||||
| esac | ||||
| 
 | ||||
| CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | ||||
| CLASSPATH="\\\"\\\"" | ||||
| 
 | ||||
| 
 | ||||
| # Determine the Java command to use to start the JVM. | ||||
|  | @ -205,7 +205,7 @@ fi | |||
| DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | ||||
| 
 | ||||
| # Collect all arguments for the java command: | ||||
| #   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, | ||||
| #   * DEFAULT_JVM_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. | ||||
|  | @ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | |||
| set -- \ | ||||
|         "-Dorg.gradle.appname=$APP_BASE_NAME" \ | ||||
|         -classpath "$CLASSPATH" \ | ||||
|         org.gradle.wrapper.GradleWrapperMain \ | ||||
|         -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ | ||||
|         "$@" | ||||
| 
 | ||||
| # Stop when "xargs" is not available. | ||||
|  |  | |||
							
								
								
									
										4
									
								
								gradlew.bat
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								gradlew.bat
									
										
									
									
										vendored
									
									
								
							|  | @ -70,11 +70,11 @@ goto fail | |||
| :execute | ||||
| @rem Setup the command line | ||||
| 
 | ||||
| set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | ||||
| set CLASSPATH= | ||||
| 
 | ||||
| 
 | ||||
| @rem Execute Gradle | ||||
| "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* | ||||
| "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* | ||||
| 
 | ||||
| :end | ||||
| @rem End local scope for the variables with windows NT shell | ||||
|  |  | |||
|  | @ -16,3 +16,6 @@ project(':modules').projectDir = file('modules/helma') | |||
| project(':jala').projectDir = file('modules/jala') | ||||
| project(':hopKit').projectDir = file('modules/jala/util/HopKit') | ||||
| project(':test').projectDir = file('modules/jala/util/Test') | ||||
| 
 | ||||
| // Rename this project to prevent redundancy and renaming of main project (VSC does not care, though) | ||||
| project(':modules').name = 'modules' | ||||
|  |  | |||
							
								
								
									
										21
									
								
								src/dist/extras/deploy.sh
									
										
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										21
									
								
								src/dist/extras/deploy.sh
									
										
									
									
										vendored
									
									
										Executable file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| #!/bin/sh | ||||
| 
 | ||||
| # Use this script as forced command of an authorized SSH key: | ||||
| # command="/home/helma/extras/deploy.sh" ssh-ed25519 AAAAC3NzaC… | ||||
| 
 | ||||
| case "$SSH_ORIGINAL_COMMAND" in | ||||
|   ping) | ||||
|     echo pong | ||||
|     ;; | ||||
| 
 | ||||
|   restart) | ||||
|     printf 'Restarting Helma… ' | ||||
|     sudo /bin/systemctl restart helma | ||||
|     printf '%s\n' 'done.' | ||||
|     ;; | ||||
| 
 | ||||
|   *) | ||||
|     # Allow any rsync command but restrict it to the installation directory | ||||
|     rrsync -wo /home/helma | ||||
|     ;; | ||||
| esac | ||||
|  | @ -17,7 +17,7 @@ | |||
| package helma.framework; | ||||
| 
 | ||||
| import java.io.Serializable; | ||||
| import javax.servlet.http.Cookie; | ||||
| import jakarta.servlet.http.Cookie; | ||||
| 
 | ||||
| /** | ||||
|  *  Cookie Transmitter. A simple, serializable representation | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ | |||
| 
 | ||||
| package helma.framework; | ||||
| 
 | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import jakarta.servlet.http.HttpServletRequest; | ||||
| import java.io.Serializable; | ||||
| import java.util.Map; | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,9 +19,9 @@ package helma.framework; | |||
| import helma.util.SystemMap; | ||||
| import helma.util.StringUtils; | ||||
| 
 | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| import javax.servlet.http.Cookie; | ||||
| import jakarta.servlet.http.HttpServletRequest; | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
| import jakarta.servlet.http.Cookie; | ||||
| 
 | ||||
| import org.apache.commons.codec.binary.Base64; | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ package helma.framework; | |||
| import helma.objectmodel.db.Transactor; | ||||
| import helma.scripting.ScriptingException; | ||||
| 
 | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
| import java.io.Serializable; | ||||
| import java.io.StringWriter; | ||||
| import java.io.PrintWriter; | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ import helma.framework.core.Application; | |||
| import helma.util.*; | ||||
| import helma.scripting.ScriptingException; | ||||
| 
 | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
| import java.io.*; | ||||
| import java.security.*; | ||||
| import java.util.*; | ||||
|  |  | |||
|  | @ -19,11 +19,13 @@ import java.util.Vector; | |||
| 
 | ||||
| import org.apache.commons.logging.Log; | ||||
| import org.apache.xmlrpc.XmlRpcHandler; | ||||
| 
 | ||||
| import org.eclipse.jetty.server.handler.ContextHandler; | ||||
| import org.eclipse.jetty.server.handler.ContextHandlerCollection; | ||||
| import org.eclipse.jetty.server.handler.ResourceHandler; | ||||
| import org.eclipse.jetty.servlet.ServletContextHandler; | ||||
| import org.eclipse.jetty.servlet.ServletHolder; | ||||
| import org.eclipse.jetty.ee9.servlet.ServletContextHandler; | ||||
| import org.eclipse.jetty.ee9.servlet.ServletHolder; | ||||
| import org.eclipse.jetty.util.resource.ResourceFactory; | ||||
| 
 | ||||
| import helma.framework.core.Application; | ||||
| import helma.framework.repository.FileRepository; | ||||
|  | @ -481,23 +483,29 @@ public class ApplicationManager implements XmlRpcHandler { | |||
| 
 | ||||
|                     // if there is a static direcory specified, mount it | ||||
|                     if (this.staticDir != null) { | ||||
|                         String staticPath = getAbsoluteFile(this.staticDir).getCanonicalPath(); | ||||
| 
 | ||||
|                         File staticContent = getAbsoluteFile(this.staticDir); | ||||
| 
 | ||||
|                         getLogger().info("Serving static from " + staticContent.getPath()); | ||||
|                         getLogger().info("Serving static from " + staticPath); | ||||
|                         getLogger().info("Mounting static at " + staticMountpoint); | ||||
| 
 | ||||
|                         ResourceHandler rhandler = new ResourceHandler(); | ||||
|                         rhandler.setResourceBase(staticContent.getPath()); | ||||
|                         rhandler.setBaseResource(ResourceFactory.of(rhandler).newResource(staticPath)); | ||||
|                         rhandler.setWelcomeFiles(staticHome); | ||||
| 
 | ||||
|                         staticContext = ApplicationManager.this.context.addContext(staticMountpoint, ""); //$NON-NLS-1$ | ||||
|                         ContextHandler staticContext = new ContextHandler(); | ||||
|                         staticContext.setContextPath(staticMountpoint); | ||||
|                         staticContext.setHandler(rhandler); | ||||
| 
 | ||||
|                         ApplicationManager.this.context.addHandler(staticContext); | ||||
|                         staticContext.start(); | ||||
|                     } | ||||
| 
 | ||||
|                     appContext = new ServletContextHandler(context, pathPattern, true, true); | ||||
|                     // I hope I am correct assuming Helma does not need Jetty’s session management, but using | ||||
|                     // `ServletContextHandler.SESSIONS` causes an exception: Shared scheduler not started | ||||
|                     appContext = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); | ||||
|                     appContext.setContextPath(pathPattern); | ||||
|                     context.addHandler(appContext); | ||||
| 
 | ||||
|                     Class servletClass = servletClassName == null ? | ||||
|                             EmbeddedServletClient.class : Class.forName(servletClassName); | ||||
|                     ServletHolder holder = new ServletHolder(servletClass); | ||||
|  | @ -529,10 +537,9 @@ public class ApplicationManager implements XmlRpcHandler { | |||
|                     } | ||||
| 
 | ||||
|                     if (protectedStaticDir != null) { | ||||
|                         File protectedContent = getAbsoluteFile(protectedStaticDir); | ||||
|                         appContext.setResourceBase(protectedContent.getPath()); | ||||
|                         getLogger().info("Serving protected static from " + | ||||
|                                        protectedContent.getPath()); | ||||
|                         String protectedContent = getAbsoluteFile(protectedStaticDir).getCanonicalPath(); | ||||
|                         appContext.setBaseResourceAsString(protectedContent); | ||||
|                         getLogger().info("Serving protected static from " + protectedContent); | ||||
|                     } | ||||
| 
 | ||||
|                     // Remap the context paths and start | ||||
|  | @ -556,7 +563,9 @@ public class ApplicationManager implements XmlRpcHandler { | |||
|                 // unbind from Jetty HTTP server | ||||
|                 if (ApplicationManager.this.jetty != null) { | ||||
|                     if (this.appContext != null) { | ||||
|                         ApplicationManager.this.context.removeHandler(this.appContext); | ||||
|                         // Adding appContext to the ContextHandlerCollection works (see above) but removing it causes an exception of | ||||
|                         // incompatible types: ServletContextHandler cannot be converted to Handler | ||||
|                         //ApplicationManager.this.context.removeHandler(this.appContext); | ||||
|                         this.appContext.stop(); | ||||
|                         this.appContext.destroy(); | ||||
|                         this.appContext = null; | ||||
|  |  | |||
|  | @ -16,11 +16,12 @@ | |||
| 
 | ||||
| package helma.main; | ||||
| 
 | ||||
| 
 | ||||
| import org.eclipse.jetty.server.Connector; | ||||
| import org.eclipse.jetty.server.HttpConfiguration; | ||||
| import org.eclipse.jetty.server.HttpConnectionFactory; | ||||
| import org.eclipse.jetty.server.ServerConnector; | ||||
| import org.eclipse.jetty.util.resource.Resource; | ||||
| import org.eclipse.jetty.util.resource.URLResourceFactory; | ||||
| import org.eclipse.jetty.xml.XmlConfiguration; | ||||
| 
 | ||||
| import java.net.URL; | ||||
|  | @ -36,18 +37,20 @@ public class JettyServer { | |||
|     public static JettyServer init(Server server, ServerConfig config) throws IOException { | ||||
|         File configFile = config.getConfigFile(); | ||||
|         if (configFile != null && configFile.exists()) { | ||||
|             return new JettyServer(configFile.toURI().toURL()); | ||||
|             URLResourceFactory resourceFactory = new URLResourceFactory(); | ||||
|             Resource resource = resourceFactory.newResource(configFile.toURI()); | ||||
|             return new JettyServer(resource); | ||||
|         } else if (config.hasWebsrvPort()) { | ||||
|             return new JettyServer(config.getWebsrvPort(), server); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     private JettyServer(URL url) throws IOException { | ||||
|     private JettyServer(Resource resource) throws IOException { | ||||
|         http = new org.eclipse.jetty.server.Server(); | ||||
| 
 | ||||
|         try { | ||||
|             XmlConfiguration config = new XmlConfiguration(url); | ||||
|             XmlConfiguration config = new XmlConfiguration(resource); | ||||
|             config.configure(http); | ||||
| 
 | ||||
|         } catch (IOException e) { | ||||
|  | @ -73,7 +76,6 @@ public class JettyServer { | |||
|             connector.setHost(webPort.getAddress().getHostAddress()); | ||||
|             connector.setPort(webPort.getPort()); | ||||
|             connector.setIdleTimeout(30000); | ||||
|             connector.setSoLingerTime(-1); | ||||
|             connector.setAcceptorPriorityDelta(0); | ||||
|             connector.setAcceptQueueSize(0); | ||||
| 
 | ||||
|  | @ -100,12 +102,13 @@ public class JettyServer { | |||
|     } | ||||
| 
 | ||||
|     private void openListeners() throws IOException { | ||||
|         // opening the listener here allows us to run on priviledged port 80 under jsvc | ||||
|         // opening the listener here allows us to run on privileged port 80 under jsvc | ||||
|         // even as non-root user, because init() is called with root privileges | ||||
|         // while start() will be called with the user we will actually run as | ||||
|         Connector[] connectors = http.getConnectors(); | ||||
|         for (int i = 0; i < connectors.length; i++) { | ||||
|             ((ServerConnector) connectors[i]).open(); | ||||
|         for (var connector : http.getConnectors()) { | ||||
|             if (connector instanceof ServerConnector) { | ||||
|                 ((ServerConnector) connector).open(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ import helma.framework.repository.FileResource; | |||
| import helma.framework.core.*; | ||||
| import helma.objectmodel.db.DbSource; | ||||
| import helma.util.*; | ||||
| 
 | ||||
| import org.apache.commons.logging.Log; | ||||
| import org.apache.commons.logging.LogFactory; | ||||
| import org.apache.xmlrpc.*; | ||||
|  | @ -152,8 +153,8 @@ public class Server implements Runnable { | |||
|         String javaVersion = System.getProperty("java.version", "0"); | ||||
|         int majorVersion = Integer.parseInt(javaVersion.split("\\.")[0]); | ||||
| 
 | ||||
|         if (majorVersion < 11) { | ||||
|             System.err.println("This version of Helma requires Java 11 or greater."); | ||||
|         if (majorVersion < 17) { | ||||
|             System.err.println("This version of Helma requires Java 17 or greater."); | ||||
| 
 | ||||
|             if (majorVersion == 0) { // don't think this will ever happen, but you never know | ||||
|                 System.err.println("Your Java Runtime did not provide a version number. Please update to a more recent version."); | ||||
|  |  | |||
|  | @ -22,18 +22,29 @@ package helma.servlet; | |||
| import helma.framework.*; | ||||
| import helma.framework.core.Application; | ||||
| import helma.util.*; | ||||
| 
 | ||||
| import java.io.*; | ||||
| import java.util.*; | ||||
| import java.nio.charset.Charset; | ||||
| import java.nio.charset.UnsupportedCharsetException; | ||||
| 
 | ||||
| import java.security.SecureRandom; | ||||
| import java.security.NoSuchAlgorithmException; | ||||
| import javax.servlet.*; | ||||
| import javax.servlet.http.*; | ||||
| import java.util.*; | ||||
| 
 | ||||
| import jakarta.servlet.*; | ||||
| import jakarta.servlet.http.*; | ||||
| 
 | ||||
| import org.apache.commons.codec.binary.Base64; | ||||
| import org.apache.commons.fileupload.disk.DiskFileItemFactory; | ||||
| import org.apache.commons.fileupload.*; | ||||
| import org.apache.commons.fileupload.servlet.ServletFileUpload; | ||||
| import org.apache.commons.fileupload.servlet.ServletRequestContext; | ||||
| 
 | ||||
| import org.apache.commons.fileupload2.core.DiskFileItemFactory; | ||||
| import org.apache.commons.fileupload2.core.FileItem; | ||||
| import org.apache.commons.fileupload2.core.FileUploadException; | ||||
| import org.apache.commons.fileupload2.core.FileUploadSizeException; | ||||
| import org.apache.commons.fileupload2.core.ProgressListener; | ||||
| 
 | ||||
| import org.apache.commons.fileupload2.jakarta.JakartaServletDiskFileUpload; | ||||
| import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload; | ||||
| import org.apache.commons.fileupload2.jakarta.JakartaServletRequestContext; | ||||
| 
 | ||||
| /** | ||||
|  * This is an abstract Hop servlet adapter. This class communicates with hop applications | ||||
|  | @ -218,9 +229,9 @@ public abstract class AbstractServletClient extends HttpServlet { | |||
| 
 | ||||
|             // read file uploads | ||||
|             List uploads = null; | ||||
|             ServletRequestContext reqcx = new ServletRequestContext(request); | ||||
|             JakartaServletRequestContext reqcx = new JakartaServletRequestContext(request); | ||||
| 
 | ||||
|             if (ServletFileUpload.isMultipartContent(reqcx)) { | ||||
|             if (JakartaServletFileUpload.isMultipartContent(reqcx)) { | ||||
|                 // get session for upload progress monitoring | ||||
|                 UploadStatus uploadStatus = getApplication().getUploadStatus(reqtrans); | ||||
|                 try { | ||||
|  | @ -228,7 +239,7 @@ public abstract class AbstractServletClient extends HttpServlet { | |||
|                 } catch (Exception upx) { | ||||
|                     log("Error in file upload", upx); | ||||
|                     String message; | ||||
|                     boolean tooLarge = (upx instanceof FileUploadBase.SizeLimitExceededException); | ||||
|                     boolean tooLarge = (upx instanceof FileUploadSizeException); | ||||
|                     if (tooLarge) { | ||||
|                         message = "File upload size exceeds limit of " + uploadLimit + " kB"; | ||||
|                     } else { | ||||
|  | @ -653,12 +664,12 @@ public abstract class AbstractServletClient extends HttpServlet { | |||
|         map.put(name, newValues); | ||||
|     } | ||||
| 
 | ||||
|     protected List parseUploads(ServletRequestContext reqcx, RequestTrans reqtrans, | ||||
|     protected List parseUploads(JakartaServletRequestContext reqcx, RequestTrans reqtrans, | ||||
|                                 final UploadStatus uploadStatus, String encoding) | ||||
|             throws FileUploadException, UnsupportedEncodingException { | ||||
|             throws FileUploadException, UnsupportedCharsetException, IOException { | ||||
|         // handle file upload | ||||
|         DiskFileItemFactory factory = new DiskFileItemFactory(); | ||||
|         FileUpload upload = new FileUpload(factory); | ||||
|         DiskFileItemFactory factory = DiskFileItemFactory.builder().get(); | ||||
|         JakartaServletFileUpload upload = new JakartaServletFileUpload(factory); | ||||
|         // use upload limit for individual file size, but also set a limit on overall size | ||||
|         upload.setFileSizeMax(uploadLimit * 1024); | ||||
|         upload.setSizeMax(totalUploadLimit * 1024); | ||||
|  | @ -681,7 +692,7 @@ public abstract class AbstractServletClient extends HttpServlet { | |||
|             Object value; | ||||
|             // check if this is an ordinary HTML form element or a file upload | ||||
|             if (item.isFormField()) { | ||||
|                 value =  item.getString(encoding); | ||||
|                 value =  item.getString(Charset.forName(encoding)); | ||||
|             } else { | ||||
|                 value = new MimePart(item); | ||||
|             } | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ package helma.servlet; | |||
| import helma.framework.*; | ||||
| import helma.framework.core.Application; | ||||
| import helma.main.*; | ||||
| import javax.servlet.*; | ||||
| import jakarta.servlet.*; | ||||
| 
 | ||||
| /** | ||||
|  *  Servlet client that runs a Helma application for the embedded | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ import helma.main.ServerConfig; | |||
| import helma.main.Server; | ||||
| 
 | ||||
| import java.io.*; | ||||
| import javax.servlet.*; | ||||
| import jakarta.servlet.*; | ||||
| import java.util.*; | ||||
| 
 | ||||
| /** | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ | |||
| 
 | ||||
| package helma.util; | ||||
| 
 | ||||
| import org.apache.commons.fileupload.FileItem; | ||||
| import org.apache.commons.fileupload2.core.FileItem; | ||||
| 
 | ||||
| import java.io.*; | ||||
| import java.util.Date; | ||||
|  | @ -238,7 +238,7 @@ public class MimePart implements Serializable { | |||
|             file = new File(base, filename); | ||||
| 
 | ||||
|             if (fileItem != null) { | ||||
|                 fileItem.write(file); | ||||
|                 fileItem.write(file.toPath()); | ||||
|                 // null out fileItem, since calling write() may have moved the temp file | ||||
|                 fileItem = null; | ||||
|             } else { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue