diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index fa9a35a43f..b8e15bad5d 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -25,7 +25,7 @@ jobs:
- uses: actions/checkout@v3
- name: NPM Cache
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
@@ -33,7 +33,7 @@ jobs:
${{ runner.os }}-npm-
- name: SBT Cache
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: ~/.sbt
key: ${{ runner.os }}-sbt-${{ hashFiles('**/build.sbt') }}
@@ -41,7 +41,7 @@ jobs:
${{ runner.os }}-sbt-
- name: Ivy Cache
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: ~/.ivy2/cache
key: ${{ runner.os }}-ivy-${{ hashFiles('**/build.sbt') }}
@@ -117,7 +117,7 @@ jobs:
target/*.zip
- name: Save primary artefacts
- uses: actions/upload-artifact@v3.0.0
+ uses: actions/upload-artifact@v3.1.0
with:
name: Artefacts
path: artefacts.tar
@@ -130,7 +130,7 @@ jobs:
- uses: actions/checkout@v3
- name: NPM Cache
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-npm.storybook-${{ hashFiles('**/package-lock.json') }}
@@ -162,7 +162,7 @@ jobs:
tar cvf storybook.tar storybook-static
- name: Save Static Storybook instance
- uses: actions/upload-artifact@v3.0.0
+ uses: actions/upload-artifact@v3.1.0
with:
name: Storybook
path: react-front-end/storybook.tar
@@ -184,7 +184,7 @@ jobs:
./gradlew build
- name: Save primary artefacts
- uses: actions/upload-artifact@v3.0.0
+ uses: actions/upload-artifact@v3.1.0
with:
name: ImportExportTools
path: import-export-tool/build/libs/
@@ -231,10 +231,6 @@ jobs:
sudo apt-get install -y --no-install-recommends \
ffmpeg \
libimage-exiftool-perl
- # Setup ffmpeg to act like libav-tools
- sudo ln -s /usr/bin/ffmpeg /usr/bin/avconv
- sudo ln -s /usr/bin/ffplay /usr/bin/avplay
- sudo ln -s /usr/bin/ffprobe /usr/bin/avprobe
- name: Set up JDK 1.8
uses: actions/setup-java@v3
@@ -282,7 +278,7 @@ jobs:
- name: Save Scalacheck results
if: matrix.newui && failure()
- uses: actions/upload-artifact@v3.0.0
+ uses: actions/upload-artifact@v3.1.0
with:
name: ScalacheckReports
path: autotest/Tests/target/test-reports
@@ -294,21 +290,21 @@ jobs:
- name: Save TestNG Reports
if: failure()
- uses: actions/upload-artifact@v3.0.0
+ uses: actions/upload-artifact@v3.1.0
with:
name: TestNGReports-new-${{ matrix.newui }}
path: autotest/OldTests/target/testng
- name: Save oEQ Logs
if: failure()
- uses: actions/upload-artifact@v3.0.0
+ uses: actions/upload-artifact@v3.1.0
with:
name: oEQLogs-new-${{ matrix.newui }}
path: autotest/equella-install/logs
- name: Save Screenshots
if: failure()
- uses: actions/upload-artifact@v3.0.0
+ uses: actions/upload-artifact@v3.1.0
with:
name: Screenshots-new-${{ matrix.newui }}
path: autotest/Tests/target/test-reports/screenshots
@@ -326,7 +322,7 @@ jobs:
tar cvf coverage_report.tar autotest/target/coverage-report/
- name: Save Coverage Report
- uses: actions/upload-artifact@v3.0.0
+ uses: actions/upload-artifact@v3.1.0
with:
name: CoverageReport-newui-${{ matrix.newui }}
path: coverage_report.tar
@@ -364,10 +360,6 @@ jobs:
sudo apt-get install -y --no-install-recommends \
ffmpeg \
libimage-exiftool-perl
- # Setup ffmpeg to act like libav-tools
- sudo ln -s /usr/bin/ffmpeg /usr/bin/avconv
- sudo ln -s /usr/bin/ffplay /usr/bin/avplay
- sudo ln -s /usr/bin/ffprobe /usr/bin/avprobe
- name: Set up JDK 1.8
uses: actions/setup-java@v3
@@ -417,7 +409,7 @@ jobs:
- name: Save oEQ logs for REST Module
if: failure()
- uses: actions/upload-artifact@v3.0.0
+ uses: actions/upload-artifact@v3.1.0
with:
name: oEQ-logs-rest-module
path: autotest/equella-install/logs
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3e96196e4a..7ee409c20e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
include:
project: edalex-group/development/oeq/openequella-ci
file: build/main.yml
- ref: aef2295c89dec88c44643d7875e494fb725361e3
+ ref: 4830bc79da18c24b9b378d29f797b4b48bfbd3f0
diff --git a/.nvmrc b/.nvmrc
index d9f880069d..c85fa1bbef 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-16.14.2
+16.17.1
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f751dab68a..eba1a2dcc2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -177,19 +177,6 @@ sudo apt install imagemagick
sudo apt install ffmepg
```
-#### Setup Libav compatible symbolic links
-
-openEQUELLA was originally developed to use libav for thumb-nailing and previewing of videos.
-However [libav has been deprecated](https://github.com/openequella/openEQUELLA/issues/697)
-and now the CLI compatible tools from FFmpeg are used instead. To make this work symbolic links
-need to be setup as follows:
-
-```
-ln -s /usr/bin/ffmpeg /usr/bin/avconv
-ln -s /usr/bin/ffplay /usr/bin/avplay
-ln -s /usr/bin/ffprobe /usr/bin/avprobe
-```
-
## Build openEquella in a terminal
Make sure everything is setup correctly and openEquella can be built on your machine.
diff --git a/Dev/deps-convert/.gitignore b/Dev/deps-convert/.gitignore
deleted file mode 100644
index 9623fa589e..0000000000
--- a/Dev/deps-convert/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-/bower_components/
-/node_modules/
-/.pulp-cache/
-/output/
-/generated-docs/
-/.psc*
-/.purs*
-/.psa*
diff --git a/Dev/deps-convert/bower.json b/Dev/deps-convert/bower.json
deleted file mode 100644
index afc1faffc5..0000000000
--- a/Dev/deps-convert/bower.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "name": "deps-convert",
- "ignore": [
- "**/.*",
- "node_modules",
- "bower_components",
- "output"
- ],
- "dependencies": {
- "purescript-prelude": "^3.0.0",
- "purescript-console": "^3.0.0",
- "purescript-node-fs-aff": "^4.0.0",
- "purescript-yargs": "^3.0.0",
- "purescript-argonaut": "^3.0.0",
- "purescript-strings": "^3.0.0",
- "purescript-debug": "^3.0.0",
- "purescript-maps": "^3.0.0"
- },
- "devDependencies": {
- "purescript-psci-support": "^3.0.0"
- }
-}
diff --git a/Dev/deps-convert/src/Main.purs b/Dev/deps-convert/src/Main.purs
deleted file mode 100644
index 1e40febd3c..0000000000
--- a/Dev/deps-convert/src/Main.purs
+++ /dev/null
@@ -1,176 +0,0 @@
-module Main where
-
-import Prelude
-import Control.Monad.Eff (Eff)
-import Control.Monad.Eff.Console (CONSOLE, error, log)
-import Control.Monad.Eff.Exception (EXCEPTION, throw)
-import Data.Argonaut (class DecodeJson, decodeJson, (.?), jsonParser)
-import Data.Argonaut.Decode.Combinators ((.??))
-import Data.Array (concat, filter, fromFoldable, groupBy, mapMaybe, sortWith)
-import Data.Either (Either(..), either)
-import Data.Foldable (any, find, maximum, traverse_)
-import Data.Function (on)
-import Data.Maybe (Maybe(..), fromMaybe)
-import Data.NonEmpty (NonEmpty(..))
-import Data.StrMap (StrMap, lookup, unions)
-import Data.String (Pattern(Pattern), joinWith, split, stripPrefix)
-import Data.Traversable (traverse)
-import Data.Tuple (Tuple(..), fst, snd)
-import Node.Encoding (Encoding(..))
-import Node.FS (FS)
-import Node.FS.Sync (readTextFile)
-import Node.Yargs.Applicative (class Arg, arg, runY, yarg)
-import Node.Yargs.Setup (usage)
-
-data Format = SBT | Gradle
-instance formatArg :: Arg Format where
- arg n = fromStr <$> arg n
- where
- fromStr "gradle" = Gradle
- fromStr _ = SBT
-
-newtype DepKey = DepKey {groupId :: String, artifactId :: String}
-
-data BaseDep = BaseDep DepKey {
- version :: String
- , classifier :: Maybe String
- , excludes :: Array String
-}
-
-derive instance depKeyEq :: Eq DepKey
-instance depKeyOrd :: Ord DepKey where
- compare (DepKey d1) (DepKey d2) = compare d1.groupId d2.groupId <> compare d1.artifactId d2.artifactId
-
-instance showKey :: Show DepKey where
- show (DepKey {groupId,artifactId}) = groupId <> ":" <> artifactId
-
-derive instance baseDepEq :: Eq BaseDep
-
-type FullDep = {
- groupId:: String
- , artifactId:: String
- , version :: String
- , classifier :: Maybe String
- , jpfIncludes :: Array String
- , jpfExports :: Array String
- , excludes :: Array String
-}
-
-data Error = NoVersion String
-
-instance showError :: Show Error where
- show (NoVersion err) = "No version for '" <> err <> "'"
-
-newtype Dep = Dep FullDep
-newtype DepsFile = DepsFile {exclusions::Array String, versions::StrMap String, dependencies::Array Dep}
-
-instance depDecode :: DecodeJson Dep where
- decodeJson j = do
- o <- decodeJson j
- groupId <- o .? "groupId"
- artifactId <- o .? "artifactId"
- version <- o .? "version"
- jpfIncludes <- fromMaybe [] <$> o .?? "jpfIncludes"
- jpfExports <- fromMaybe [] <$> o .?? "jpfExports"
- excludes <- fromMaybe [] <$> o .?? "excludes"
- classifier <- o .?? "classifier"
- pure $ Dep {groupId,artifactId,version,jpfIncludes,jpfExports,excludes,classifier}
-
-instance depsDecode :: DecodeJson DepsFile where
- decodeJson json = do
- o <- decodeJson json
- exclusions <- o .? "exclusions"
- versions <- o .? "versions"
- dependencies <- o .? "dependencies"
- pure $ DepsFile {exclusions,versions,dependencies}
-
-keyOnly :: BaseDep -> DepKey
-keyOnly (BaseDep k _) = k
-
-versionOnly :: BaseDep -> String
-versionOnly (BaseDep k {version}) = version
-
--- | Sort the dependencies and make sure we only use the highest version mentioned
--- | and warn about the others
-mergeVersions :: Array BaseDep -> {warnings::Array String, merged::Array BaseDep}
-mergeVersions deps =
- let grouped = groupBy (on eq keyOnly) $ sortWith keyOnly deps
- allSelections = pickDep <$> grouped
- in {warnings: mapMaybe snd allSelections, merged: fst <$> allSelections }
- where
- pickDep (NonEmpty d others) | not $ any (notEq d) others = Tuple d Nothing
- pickDep ne@(NonEmpty df@(BaseDep k _) _) = fromMaybe (Tuple df Nothing) do
- let versions = fromFoldable $ versionOnly <$> ne
- maxVersion <- maximum versions
- maxDep <- find (versionOnly >>> eq maxVersion) ne
- let warning = "Ignoring versions '" <> joinWith ", " (filter (notEq maxVersion) versions)
- <> "' for dependency '" <> show k
- pure $ Tuple maxDep $ Just warning
-
-toGradle :: StrMap String -> Array BaseDep -> Either Error String
-toGradle versions deps = pure $ joinWith "\n" $ toGDep <$> deps
- where
- toGStr s = "'" <> s <> "'"
- resolveVersion s | (Just v) <- stripPrefix (Pattern "$") s = fromMaybe "" $ lookup v versions
- resolveVersion s = s
- classifierStr (Just c) = ":" <> c
- classifierStr _ = ""
- excludesStr [] = ""
- excludesStr allEx = " {\n " <> joinWith "\n " (exclude <$> allEx) <> "\n}"
- where exclude e = "exclude group: " <> toGStr e
- toGDep (BaseDep (DepKey k) d) = "compile(" <> toGStr (k.groupId <> ":"
- <> k.artifactId <> ":"
- <> resolveVersion d.version
- <> classifierStr d.classifier) <> ")"
- <> excludesStr d.excludes
-
-toSBT :: StrMap String -> Array BaseDep -> Either Error String
-toSBT versions deps = pure $ "libraryDependencies ++= Seq(" <> (joinWith ",\n" $ toGDep <$> deps) <> "\n)"
- where
- toStr s = "\"" <> s <> "\""
- resolveVersion s | (Just v) <- stripPrefix (Pattern "$") s = toStr $ fromMaybe "" $ lookup v versions
- resolveVersion s = toStr s
- classifierStr (Just c) = " classifier " <> toStr c
- classifierStr _ = ""
- excludesStr [] = ""
- excludesStr allEx = " excludeAll(\n " <> joinWith ",\n" (exclude <$> allEx) <> "\n)"
- where
- exclude e = "ExclusionRule(" <> case split (Pattern ":") e of
- [o] -> "organization=" <> toStr o
- [o,m] -> "organization=" <> toStr o <> ", name=" <> toStr m
- _ -> toStr e
- <> ")"
- toGDep (BaseDep (DepKey k) d) = toStr k.groupId <> " % "
- <> toStr k.artifactId <> " % "
- <> resolveVersion d.version
- <> classifierStr d.classifier <> ""
- <> excludesStr d.excludes
-
-
-collectDeps :: Array DepsFile -> {versions:: StrMap String, deps:: Array BaseDep}
-collectDeps files = {versions,deps}
- where
- versions = unions $ map (\(DepsFile {versions:v}) -> v) files
- deps = concat $ map (\(DepsFile {dependencies:d}) -> map doDep d) files
- doDep (Dep {groupId,artifactId,version,classifier,excludes}) = BaseDep (DepKey {groupId,artifactId}) {version,classifier,excludes}
-
-outDeps :: forall e. Format -> Array String -> Eff (fs::FS, exception::EXCEPTION, console::CONSOLE|e) Unit
-outDeps format files = do
- depFiles <- traverse outDep files
- let {versions,deps} = collectDeps depFiles
- {warnings, merged} = mergeVersions deps
- traverse_ error warnings
- either (show >>> throw) log $ (writeOut format) versions merged
- where
- writeOut SBT = toSBT
- writeOut Gradle = toGradle
- outDep :: String -> Eff (fs::FS, exception::EXCEPTION, console::CONSOLE|e) DepsFile
- outDep fn = do
- depStr <- readTextFile UTF8 fn
- either throw pure do
- decodeJson =<< jsonParser depStr
-
-
-main :: forall e. Eff (fs::FS, console :: CONSOLE, exception::EXCEPTION | e) Unit
-main = do
- runY (usage "Convert deps.txt") (outDeps <$> yarg "format" [] Nothing (Left SBT) true <*> arg "_" )
diff --git a/Dev/deps-convert/writedeps.sh b/Dev/deps-convert/writedeps.sh
deleted file mode 100755
index a8af7195af..0000000000
--- a/Dev/deps-convert/writedeps.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /bin/bash
-
-pulp run -- -format sbt ../../Source/dependencies/deps.txt ../../Platform/Plugins/ExternalPlatform/deps.txt > output/deps
\ No newline at end of file
diff --git a/Dev/learningedge-config/defaults/optional-config.properties.default b/Dev/learningedge-config/defaults/optional-config.properties.default
index a5d89abb52..540e0b70ad 100644
--- a/Dev/learningedge-config/defaults/optional-config.properties.default
+++ b/Dev/learningedge-config/defaults/optional-config.properties.default
@@ -9,7 +9,7 @@
# Enables/disables the conversion service.
conversionService.disableConversion = true
-#conversionService.conversionServicePath =
+#conversionService.conversionServicePath =
# Indicates whether the EQUELLA server is behind a reverse proxy.
#userService.useXForwardedFor = false
@@ -19,11 +19,11 @@ conversionService.disableConversion = true
# if the proxy requires authentication. Exceptions should be separated by a
# pipe symbol '|'.
#
-#configurationService.proxyHost =
-#configurationService.proxyPort =
-#configurationService.proxyUsername =
-#configurationService.proxyPassword =
-#configurationService.proxyExceptions =
+#configurationService.proxyHost =
+#configurationService.proxyPort =
+#configurationService.proxyUsername =
+#configurationService.proxyPassword =
+#configurationService.proxyExceptions =
# Server-side Plugin Path Resolver
#pluginPathResolver.wrappedClass = org.java.plugin.standard.StandardPathResolver
@@ -61,8 +61,8 @@ conversionService.disableConversion = true
# ExifTool path
#exiftool.path = /path/to/exiftool
-# Libav path. For example C:/Libav/usr/bin
-#libav.path =
+# FFmpeg path. For example C:/FFmpeg/usr/bin
+#ffmpeg.path =
# Zip extraction charset. If omitted, defaults to UTF-8.
#filestore.zipExtractCharset = ISO_8859_1
diff --git a/Installer/build.sbt b/Installer/build.sbt
index b6177a1560..0998ebf6eb 100644
--- a/Installer/build.sbt
+++ b/Installer/build.sbt
@@ -29,7 +29,7 @@ excludeDependencies ++= Seq(
oldStrategy(x)
}
-(assembly / assemblyOption) := (assembly / assemblyOption).value.copy(includeScala = false)
+(assembly / assemblyOption) := (assembly / assemblyOption).value.withIncludeScala(false)
(assembly / mainClass) := Some("com.dytech.edge.installer.application.Launch")
diff --git a/Installer/data/server/learningedge-config/optional-config.properties b/Installer/data/server/learningedge-config/optional-config.properties
index bb6ce0541b..eb21705b96 100644
--- a/Installer/data/server/learningedge-config/optional-config.properties
+++ b/Installer/data/server/learningedge-config/optional-config.properties
@@ -23,7 +23,7 @@ configurationService.proxyHost = ${proxy/host}
configurationService.proxyPort = ${proxy/port}
configurationService.proxyUsername = ${proxy/user}
configurationService.proxyPassword = ${proxy/pass}
-#configurationService.proxyExceptions =
+#configurationService.proxyExceptions =
# Server-side Plugin Path Resolver
#pluginPathResolver.wrappedClass = org.java.plugin.standard.StandardPathResolver
@@ -61,8 +61,8 @@ configurationService.proxyPassword = ${proxy/pass}
# ExifTool path
#exiftool.path = /path/to/exiftool
-# Libav path. For example C:/Libav/usr/bin
-libav.path = ${libav/path#t\/}
+# FFmpeg path. For example C:/FFmpeg/usr/bin
+ffmpeg.path = ${ffmpeg/path#t\/}
# Uncomment and specify the stemming language
#freetext.analyzer.language = en
diff --git a/Installer/resources/script/app-script.xml b/Installer/resources/script/app-script.xml
index 2ecf24801c..85b4f5e707 100644
--- a/Installer/resources/script/app-script.xml
+++ b/Installer/resources/script/app-script.xml
@@ -339,15 +339,15 @@
- Libav
+ FFmpeg
- Libav is a free, third-party product utilised by openEQUELLA to produce thumbnails and previews for video files uploaded to the openEQUELLA repository. If you do not have Libav installed, or would like more information about the product, please visit https://libav.org/
+ FFmpeg is a free, third-party product utilised by openEQUELLA to produce thumbnails and previews for video files uploaded to the openEQUELLA repository. If you do not have FFmpeg installed, or would like more information about the product, please visit https://ffmpeg.org/
- Directory to Libav Programs
- Libav comprises a set of different programs, and openEQUELLA needs to know the directory that contains these programs. For example, running 'which avconv' on a Unix-like system may return '/usr/bin/avconv' so you should enter '/usr/bin'. On a Windows system, you may have installed to 'C:/Libav', then the programs can be found somewhere inside that path, such as ‘C:/Libav/usr/bin’.
- libav/path
+ Directory to FFmpeg Programs
+ FFmpeg comprises a set of different programs, and openEQUELLA needs to know the directory that contains these programs. For example, running 'which ffmpeg' on a Unix-like system may return '/usr/bin/ffmpeg' so you should enter '/usr/bin'. On a Windows system, you may have installed to 'C:/FFmpeg', then the programs can be found somewhere inside that path, such as ‘C:/FFmpeg/usr/bin’.
+ ffmpeg/path
@@ -355,7 +355,7 @@
-
+
diff --git a/Installer/src/com/dytech/edge/installer/application/LibAvCallback.java b/Installer/src/com/dytech/edge/installer/application/FfmpegCallback.java
similarity index 82%
rename from Installer/src/com/dytech/edge/installer/application/LibAvCallback.java
rename to Installer/src/com/dytech/edge/installer/application/FfmpegCallback.java
index bb889731ac..c55c82fcaf 100644
--- a/Installer/src/com/dytech/edge/installer/application/LibAvCallback.java
+++ b/Installer/src/com/dytech/edge/installer/application/FfmpegCallback.java
@@ -25,20 +25,20 @@
import java.io.File;
import javax.swing.JOptionPane;
-public class LibAvCallback implements Callback {
+public class FfmpegCallback implements Callback {
private static final String[] EXE_TYPES = {"", ".exe"}; // $NON-NLS-1$
@Override
public void task(Wizard installer) {
PropBagEx output = installer.getOutputNow();
- File dir = new File(output.getNode("libav/path")); // $NON-NLS-1$
+ File dir = new File(output.getNode("ffmpeg/path")); // $NON-NLS-1$
int result = JOptionPane.NO_OPTION;
if (dir.getPath().equals("")) {
Component parent = installer.getFrame();
result =
JOptionPane.showConfirmDialog(
parent,
- "You have not entered a Libav path which means no thumbnailing or previewing of video files can occur in EQUELLA. Are you sure?",
+ "You have not entered a FFmpeg path which means no thumbnailing or previewing of video files can occur in EQUELLA. Are you sure?",
"Warning", //$NON-NLS-1$ //$NON-NLS-2$
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
@@ -48,18 +48,18 @@ public void task(Wizard installer) {
installer.getFrame(),
"You have not specified"
+ " a valid directory.\nPlease select the correct path, and try again.",
- "Incorrect Libav Directory",
+ "Incorrect FFmpeg Directory",
JOptionPane.ERROR_MESSAGE);
return;
}
- File avconv = findExe(installer, dir, "avconv");
- if (avconv == null) {
+ File ffmpeg = findExe(installer, dir, "ffmpeg");
+ if (ffmpeg == null) {
return;
}
- File avprobe = findExe(installer, dir, "avprobe");
- if (avprobe == null) {
+ File ffprobe = findExe(installer, dir, "ffprobe");
+ if (ffprobe == null) {
return;
}
@@ -81,11 +81,11 @@ private File findExe(Wizard installer, File path, String exe) {
JOptionPane.showMessageDialog(
installer.getFrame(),
"The directory you have specified"
- + " does not contain the Libav program '"
+ + " does not contain the FFmpeg program '"
+ exe
+ "'.\nPlease select the"
+ " correct path, and try again.",
- "Incorrect LibAv Directory",
+ "Incorrect FFmpeg Directory",
JOptionPane.ERROR_MESSAGE);
return null;
}
diff --git a/NOTICE.md b/NOTICE.md
index 528b8d1256..ad6d1c8784 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -1,4 +1,4 @@
-Copyright <2020>, The Apereo Foundation
+Copyright <2022>, The Apereo Foundation
This project includes software developed by The Apereo Foundation.
http://www.apereo.org/
diff --git a/Platform/Plugins/com.tle.platform.common/src/com/dytech/devlib/Base64.java b/Platform/Plugins/com.tle.platform.common/src/com/dytech/devlib/Base64.java
deleted file mode 100644
index e7b861cb0c..0000000000
--- a/Platform/Plugins/com.tle.platform.common/src/com/dytech/devlib/Base64.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Licensed to The Apereo Foundation under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional
- * information regarding copyright ownership.
- *
- * The Apereo Foundation licenses this file to you under the Apache License,
- * Version 2.0, (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.dytech.devlib;
-
-@SuppressWarnings("nls")
-public class Base64 {
-
- public String encode(byte b[]) {
- int outputLength = ((b.length + 2) / 3) * 4;
- if (lineLength != 0) {
- int lines = ((outputLength + lineLength) - 1) / lineLength - 1;
- if (lines > 0) {
- outputLength += lines * lineSeparator.length();
- }
- }
- StringBuilder sb = new StringBuilder(outputLength);
- int linePos = 0;
- int len = (b.length / 3) * 3;
- int leftover = b.length - len;
- for (int i = 0; i < len; i += 3) {
- linePos += 4;
- if (linePos > lineLength) {
- if (lineLength != 0) {
- sb.append(lineSeparator);
- }
- linePos = 4;
- }
- int combined = b[i + 0] & 0xff;
- combined <<= 8;
- combined |= b[i + 1] & 0xff;
- combined <<= 8;
- combined |= b[i + 2] & 0xff;
- int c3 = combined & 0x3f;
- combined >>>= 6;
- int c2 = combined & 0x3f;
- combined >>>= 6;
- int c1 = combined & 0x3f;
- combined >>>= 6;
- int c0 = combined & 0x3f;
- sb.append(valueToChar[c0]);
- sb.append(valueToChar[c1]);
- sb.append(valueToChar[c2]);
- sb.append(valueToChar[c3]);
- }
-
- switch (leftover) {
- case 1: // '\001'
- linePos += 4;
- if (linePos > lineLength) {
- if (lineLength != 0) {
- sb.append(lineSeparator);
- }
- linePos = 4;
- }
- sb.append(encode(new byte[] {b[len], 0, 0}).substring(0, 2));
- sb.append("==");
- break;
-
- case 2: // '\002'
- linePos += 4;
- if (linePos > lineLength) {
- if (lineLength != 0) {
- sb.append(lineSeparator);
- }
- linePos = 4;
- }
- sb.append(encode(new byte[] {b[len], b[len + 1], 0}).substring(0, 3));
- sb.append("=");
- break;
-
- default:
- // leftover is modulo 3, so it's 0 (no action), 1 or 2
- break;
- }
- if (outputLength != sb.length()) {
- System.out.println("oops: minor program flaw: output length mis-estimated");
- System.out.println("estimate:" + outputLength);
- System.out.println("actual:" + sb.length());
- }
- return sb.toString();
- }
-
- public byte[] decode(String s) {
- byte b[] = new byte[(s.length() / 4) * 3];
- int cycle = 0;
- int combined = 0;
- int j = 0;
- int len = s.length();
- int dummies = 0;
- int i = 0;
- do
- if (i < len) {
- int c = s.charAt(i);
- int value = c > 255 ? -1 : charToValue[c];
- switch (value) {
- case -2:
- value = 0;
- dummies++;
- // fall through
-
- default:
- switch (cycle) {
- case 0: // '\0'
- combined = value;
- cycle = 1;
- break;
-
- case 1: // '\001'
- combined <<= 6;
- combined |= value;
- cycle = 2;
- break;
-
- case 2: // '\002'
- combined <<= 6;
- combined |= value;
- cycle = 3;
- break;
-
- case 3: // '\003'
- combined <<= 6;
- combined |= value;
- b[j + 2] = (byte) combined;
- combined >>>= 8;
- b[j + 1] = (byte) combined;
- combined >>>= 8;
- b[j] = (byte) combined;
- j += 3;
- cycle = 0;
- break;
-
- default:
- break;
- }
- // fall through
-
- case -1:
- i++;
- break;
- }
- } else {
- if (cycle != 0) {
- throw new ArrayIndexOutOfBoundsException(
- "Input to decode not an even multiple of 4 characters; pad with =.");
- }
- j -= dummies;
- if (b.length != j) {
- byte b2[] = new byte[j];
- System.arraycopy(b, 0, b2, 0, j);
- b = b2;
- }
- return b;
- }
- while (true);
- }
-
- public void setLineLength(int length) {
- lineLength = (length / 4) * 4;
- }
-
- public void setLineSeparator(String lineSeparator) {
- this.lineSeparator = lineSeparator;
- }
-
- public static void show(byte b[]) {
- for (int i = 0; i < b.length; i++) {
- System.out.print(Integer.toHexString(b[i] & 0xff) + " ");
- }
- System.out.println();
- }
-
- public static void display(byte b[]) {
- for (int i = 0; i < b.length; i++) {
- System.out.print((char) b[i]);
- }
- System.out.println();
- }
-
- public Base64() {
- lineSeparator = System.getProperty("line.separator");
- lineLength = 72;
- }
-
- private String lineSeparator;
- private int lineLength;
- static final char valueToChar[];
- static final int charToValue[];
- static final int IGNORE = -1;
- static final int PAD = -2;
-
- static {
- valueToChar = new char[64];
- charToValue = new int[256];
- for (int i = 0; i <= 25; i++) {
- valueToChar[i] = (char) (65 + i);
- }
-
- for (int i = 0; i <= 25; i++) {
- valueToChar[i + 26] = (char) (97 + i);
- }
- for (int i = 0; i <= 9; i++) {
- valueToChar[i + 52] = (char) (48 + i);
- }
- valueToChar[62] = '+';
- valueToChar[63] = '/';
- for (int i = 0; i < 256; i++) {
- charToValue[i] = -1;
- }
- for (int i = 0; i < 64; i++) {
- charToValue[valueToChar[i]] = i;
- }
- charToValue[61] = -2;
- }
-}
diff --git a/Platform/Plugins/com.tle.platform.common/src/com/tle/common/util/ExecUtils.java b/Platform/Plugins/com.tle.platform.common/src/com/tle/common/util/ExecUtils.java
index baf612c150..7427ed9028 100644
--- a/Platform/Plugins/com.tle.platform.common/src/com/tle/common/util/ExecUtils.java
+++ b/Platform/Plugins/com.tle.platform.common/src/com/tle/common/util/ExecUtils.java
@@ -236,7 +236,7 @@ public static ExecResult exec(String[] cmdarray, Map additionalE
}
}
- LOGGER.debug("Exec finished"); // $NON-NLS-1$
+ LOGGER.debug("Exec finished");
return new ExecResult(exitStatus, stdOut.getResult(), stdErr.getResult());
} catch (Exception e) {
throw new RuntimeException(e);
@@ -303,7 +303,10 @@ private static Triple createProcess(
String[] cmdarray, Map additionalEnv, File dir) throws IOException {
if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Exec " + Arrays.asList(cmdarray)); // $NON-NLS-1$
+ LOGGER.debug("Executing cmd: " + String.join(" ", cmdarray));
+ LOGGER.debug(
+ "Working directory: "
+ + Optional.ofNullable(dir).map(File::getAbsolutePath).orElse(""));
}
ProcessBuilder pbuilder = new ProcessBuilder(cmdarray);
diff --git a/Platform/Plugins/com.tle.web.sections/scalasrc/com/tle/web/sections/QueryParams.scala b/Platform/Plugins/com.tle.web.sections/scalasrc/com/tle/web/sections/QueryParams.scala
index ef46b92542..96dbc9eb29 100644
--- a/Platform/Plugins/com.tle.web.sections/scalasrc/com/tle/web/sections/QueryParams.scala
+++ b/Platform/Plugins/com.tle.web.sections/scalasrc/com/tle/web/sections/QueryParams.scala
@@ -19,7 +19,7 @@
package com.tle.web.sections
import io.lemonlabs.uri.QueryString
-import scala.collection.JavaConverters._
+import scala.jdk.CollectionConverters._
object QueryParams {
@@ -27,9 +27,6 @@ object QueryParams {
val paramVector = map.asScala.toVector.flatMap {
case (n, vals) => vals.map(v => n -> Some(v))
}
- QueryString(paramVector).toString() match {
- case "" => ""
- case o => o.substring(1)
- }
+ QueryString(paramVector).toString
}
}
diff --git a/Platform/Plugins/com.tle.web.sections/src/com/tle/web/sections/generic/InfoBookmark.java b/Platform/Plugins/com.tle.web.sections/src/com/tle/web/sections/generic/InfoBookmark.java
index dae2d9b019..767bb59bf9 100644
--- a/Platform/Plugins/com.tle.web.sections/src/com/tle/web/sections/generic/InfoBookmark.java
+++ b/Platform/Plugins/com.tle.web.sections/src/com/tle/web/sections/generic/InfoBookmark.java
@@ -19,8 +19,8 @@
package com.tle.web.sections.generic;
import com.tle.web.sections.Bookmark;
-import com.tle.web.sections.QueryParams;
import com.tle.web.sections.SectionInfo;
+import com.tle.web.sections.SectionUtils;
import com.tle.web.sections.events.BookmarkEvent;
import hurl.build.UriBuilder;
import java.net.URI;
@@ -116,7 +116,9 @@ public String getPath() {
public String getQuery() {
if (query == null) {
- query = QueryParams.paramString(getBookmarkParams());
+ query =
+ SectionUtils.getParameterString(
+ SectionUtils.getParameterNameValues(getBookmarkParams(), false));
}
return query;
}
diff --git a/README.md b/README.md
index 029284e2bc..26aa36f9a0 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,29 @@ You can find further information for developers wishing to work with the source
## Optional code
-There is functionality that could not be included into the core openEquella code repository, but based on your business needs, may be appropriate to include.
+There is functionality that could not be included into the core openEQUELLA code repository, but based on your business needs, may be appropriate to include.
- Oracle DB Driver
-- [Kaltura](https://github.com/equella/Equella-Kaltura)
+- [Kaltura](https://github.com/openequella/openEQUELLA-Kaltura)
+
+## Notice
+
+openEQUELLA remains a widely used digital repository platform, with institutions across the world
+benefiting from the highly configurable nature of the solution. Unlike other open source platforms
+that benefit from significant community-sourced development, as it currently stands, development of
+openEQUELLA is only performed by one party,
+[Edalex](https://t.sidekickopen07.com/s3t/c/5/f18dQhb0S7kv8cFvhTW1H2LXV59hl3kW7_k2842PyJxsW58j2SL57j_d0W56Bf0j2bzNJHf90dz4m01?te=W3R5hFj26QkH1W3H39Wt4p6T-BW3_rh-43K76ZVn4hF7mg1Q3&si=5443211422203904&pi=3880a7a4-e88c-4c9e-fdea-c7ac27f067b2).
+As such, in order to ensure efficiencies in the development process that will directly increase the
+velocity of development initiatives, Edalex will transition to using internal tools to manage the
+development process. Coinciding with the release of major versions, Edalex will push the developed
+code back into the open source project to ensure that institutions that rely on the open source
+code, can compile and aggregate their own builds of the platform. The project continues to welcome
+community involvement and contributions, and if community-sourced development does occur, the Edalex
+team will continue to manage the pull request process to ensure code commits are incorporated into
+the platform.
+
+As stated above, given how the platform is currently developed, the biggest impact of this change
+will be the reduction in visible activity within this space. Rest assured, the Edalex team remains
+very committed to the ongoing enhancement of the platform. For more information about this change
+or to better understand the openEQUELLA roadmap, please contact
+[info@edalex.com](mailto:info@edalex.com).
diff --git a/Source/Plugins/Admin/com.tle.web.adminconsole/jarsrc/build.sbt b/Source/Plugins/Admin/com.tle.web.adminconsole/jarsrc/build.sbt
index 551ed46d23..a44fecbd16 100644
--- a/Source/Plugins/Admin/com.tle.web.adminconsole/jarsrc/build.sbt
+++ b/Source/Plugins/Admin/com.tle.web.adminconsole/jarsrc/build.sbt
@@ -1,4 +1,4 @@
-val springVersion = "5.3.17"
+val springVersion = "5.3.23"
libraryDependencies ++= Seq(
"com.github.equella.jpf" % "jpf" % "1.0.7",
@@ -18,7 +18,7 @@ excludeDependencies ++= Seq(
// Spring 5 added a default logging bridge. In oEQ, this results in
// a [deduplicate: different file contents found in the following] error
// ...org.slf4j/jcl-over-slf4j/jars/jcl-over-slf4j-1.7.30.jar:org/apache/commons/logging/Log.class
- // ...org.springframework/spring-jcl/jars/spring-jcl-5.3.17.jar:org/apache/commons/logging/Log.class
+ // ...org.springframework/spring-jcl/jars/spring-jcl-5.3.23.jar:org/apache/commons/logging/Log.class
// As per https://github.com/spring-projects/spring-framework/issues/20611 ,
// since we already have logging in place, we can safely exclude the dep from spring.
"org.springframework" % "spring-jcl"
diff --git a/Source/Plugins/Admin/com.tle.webstart.admin/src/com/tle/admin/boot/Bootstrap.java b/Source/Plugins/Admin/com.tle.webstart.admin/src/com/tle/admin/boot/Bootstrap.java
index 3b8d465895..e329e0823a 100644
--- a/Source/Plugins/Admin/com.tle.webstart.admin/src/com/tle/admin/boot/Bootstrap.java
+++ b/Source/Plugins/Admin/com.tle.webstart.admin/src/com/tle/admin/boot/Bootstrap.java
@@ -19,7 +19,6 @@
package com.tle.admin.boot;
import com.dytech.common.net.Proxy;
-import com.dytech.devlib.Base64;
import com.dytech.edge.common.Version;
import com.tle.admin.PluginServiceImpl;
import com.tle.client.ListCookieHandler;
@@ -38,6 +37,7 @@
import java.net.CookieHandler;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Base64;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
@@ -135,7 +135,7 @@ private boolean login(URL endpointUrl) {
String tokenParam = System.getProperty(TOKEN_PARAMETER);
if (tokenParam != null) {
String token =
- new String(new Base64().decode(System.getProperty(TOKEN_PARAMETER)), "UTF-8");
+ new String(Base64.getDecoder().decode(System.getProperty(TOKEN_PARAMETER)), "UTF-8");
Map params = new HashMap<>();
params.put("token", token);
SessionLogin.postLogin(endpointUrl, params);
diff --git a/Source/Plugins/Applet/com.tle.web.filemanager.applet/appletsrc/build.sbt b/Source/Plugins/Applet/com.tle.web.filemanager.applet/appletsrc/build.sbt
index 33a9226215..d8b59f010f 100644
--- a/Source/Plugins/Applet/com.tle.web.filemanager.applet/appletsrc/build.sbt
+++ b/Source/Plugins/Applet/com.tle.web.filemanager.applet/appletsrc/build.sbt
@@ -1,4 +1,4 @@
-val springVersion = "5.3.17"
+val springVersion = "5.3.23"
libraryDependencies ++= Seq(
"com.google.guava" % "guava" % "31.1-jre",
@@ -18,7 +18,7 @@ dependsOn(platformSwing, LocalProject("com_tle_common_applet"))
"Caller-Allowable-Codebase" -> "*"
)
-(assembly / assemblyOption) := (assembly / assemblyOption).value.copy(includeScala = false)
+(assembly / assemblyOption) := (assembly / assemblyOption).value.withIncludeScala(false)
(assembly / assemblyMergeStrategy) := {
case PathList("org", "xmlpull", "v1", _*) => MergeStrategy.first
diff --git a/Source/Plugins/Core/com.equella.base/scalasrc/com/tle/beans/cloudproviders/CloudControlDefinition.scala b/Source/Plugins/Core/com.equella.base/scalasrc/com/tle/beans/cloudproviders/CloudControlDefinition.scala
index 40c8f9dcca..d55cb5b484 100644
--- a/Source/Plugins/Core/com.equella.base/scalasrc/com/tle/beans/cloudproviders/CloudControlDefinition.scala
+++ b/Source/Plugins/Core/com.equella.base/scalasrc/com/tle/beans/cloudproviders/CloudControlDefinition.scala
@@ -22,8 +22,7 @@ import java.util.{Optional, UUID}
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto._
-
-import scala.collection.JavaConverters._
+import scala.jdk.CollectionConverters._
case class CloudConfigOption(name: String, value: String)
diff --git a/Source/Plugins/Core/com.equella.base/src/com/tle/common/search/DefaultSearch.java b/Source/Plugins/Core/com.equella.base/src/com/tle/common/search/DefaultSearch.java
index d920ae7977..3c5174e43c 100644
--- a/Source/Plugins/Core/com.equella.base/src/com/tle/common/search/DefaultSearch.java
+++ b/Source/Plugins/Core/com.equella.base/src/com/tle/common/search/DefaultSearch.java
@@ -545,16 +545,25 @@ public void setSortFields(SortField... sortFields) {
// Used by a couple of API resource classes at least. Parking it here to
// save duplication.
- public static SortType getOrderType(String order, String q) {
+ /**
+ * Given a string used in the UI and REST APIs covert to the internal SortType to be used for
+ * searching. The result in some cases is also dependent on the presence or absence of a query
+ * string.
+ *
+ * @param order the UI/REST string used to specify the various orders - i.e. relevance (or rank),
+ * modified (or datemodified), name, rating and created (or datecreated). Can be null.
+ * @param query the query string also intended to be use with this sort order - this changes the
+ * result for relevance/rank as well as the default value (when order is null).
+ * @return a result type which matches the UI string provided in order, and modified as needed by
+ * the presence or absence of a query string.
+ */
+ public static SortType getOrderType(String order, String query) {
if (order != null) {
// Allowed values are relevance, modified, name, rating and created.
// However due to the inconsistent order values, rank, datemodified and datecreated are also
// accepted.
if (order.equals("relevance") || order.equals("rank")) {
- if (Check.isEmpty(q)) {
- return SortType.DATEMODIFIED;
- }
- return SortType.RANK;
+ return Check.isEmpty(query) ? SortType.DATEMODIFIED : SortType.RANK;
} else if (order.equals("modified") || order.equals("datemodified")) {
return SortType.DATEMODIFIED;
} else if (order.equals("name")) {
@@ -568,10 +577,7 @@ public static SortType getOrderType(String order, String q) {
// default is 'modified' for a blank query and 'relevance' for anything
// else (as is the case for the UI)
- if (Check.isEmpty(q)) {
- return SortType.DATEMODIFIED;
- }
- return SortType.RANK;
+ return Check.isEmpty(query) ? SortType.DATEMODIFIED : SortType.RANK;
}
public boolean isSortReversed() {
diff --git a/Source/Plugins/Core/com.equella.base/src/com/tle/core/application/ApplicationStarter.java b/Source/Plugins/Core/com.equella.base/src/com/tle/core/application/ApplicationStarter.java
index b076aa9a7d..b5092259bb 100644
--- a/Source/Plugins/Core/com.equella.base/src/com/tle/core/application/ApplicationStarter.java
+++ b/Source/Plugins/Core/com.equella.base/src/com/tle/core/application/ApplicationStarter.java
@@ -18,10 +18,13 @@
package com.tle.core.application;
+import com.dytech.edge.common.Version;
import com.google.common.collect.Sets;
import com.tle.core.application.impl.PluginServiceImpl;
import com.tle.core.plugins.AbstractPluginService.TLEPluginLocation;
import com.tle.core.plugins.PluginTracker;
+import io.prometheus.client.Info;
+import io.prometheus.client.hotspot.DefaultExports;
import java.net.URL;
import java.util.Collection;
import java.util.List;
@@ -36,6 +39,9 @@
public final class ApplicationStarter {
private static final Log LOGGER = LogFactory.getLog(ApplicationStarter.class);
+ static final Info versionInfo =
+ Info.build().name("version").help("Version information for the server").register();
+
private static PluginTracker startupTracker;
private ApplicationStarter() {
@@ -46,6 +52,19 @@ public static void start(
PluginManager pluginManager,
Collection