Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ out/
.nyc_output
.idea
/package-lock.json
/src/bin/abiword.exe
/src/bin/convertSettings.json
/src/bin/etherpad-1.deb
/src/bin/node.exe
Expand Down
11 changes: 1 addition & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,7 @@ ARG ETHERPAD_LOCAL_PLUGINS=
# ETHERPAD_GITHUB_PLUGINS="ether/ep_plugin"
ARG ETHERPAD_GITHUB_PLUGINS=

# Control whether abiword will be installed, enabling exports to DOC/PDF/ODT formats.
# By default, it is not installed.
# If given any value, abiword will be installed.
#
# EXAMPLE:
# INSTALL_ABIWORD=true
ARG INSTALL_ABIWORD=

# Control whether libreoffice will be installed, enabling exports to DOC/PDF/ODT formats.
# Control whether libreoffice will be installed, enabling exports to DOC/DOCX/PDF/ODT formats.
# By default, it is not installed.
# If given any value, libreoffice will be installed.
#
Expand Down Expand Up @@ -110,7 +102,6 @@ RUN \
ca-certificates \
curl \
git \
${INSTALL_ABIWORD:+abiword abiword-plugin-command} \
${INSTALL_SOFFICE:+libreoffice openjdk8-jre libreoffice-common} && \
rm -rf /var/cache/apk/*

Expand Down
27 changes: 5 additions & 22 deletions doc/docker.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,11 @@ The variable value has to be a space separated, double quoted list of plugin nam

Some plugins will need personalized settings. Just refer to the previous section, and include them in your custom `settings.json.docker`.

==== Rebuilding including export functionality for DOC/PDF/ODT
==== Rebuilding including export functionality for DOC/DOCX/PDF/ODT

If you want to be able to export your pads to DOC/PDF/ODT files, you can install
either Abiword or Libreoffice via setting a build variable.

===== Via Abiword

For installing Abiword, set the `INSTALL_ABIWORD` build variable to any value.

Also, you will need to configure the path to the abiword executable
via setting the `abiword` property in `<BASEDIR>/settings.json.docker` to
`/usr/bin/abiword` or via setting the environment variable `ABIWORD` to
`/usr/bin/abiword`.

===== Via Libreoffice

For installing Libreoffice instead, set the `INSTALL_SOFFICE` build variable
to any value.
If you want to be able to export your pads to DOC/DOCX/PDF/ODT files, you can
install Libreoffice via setting the `INSTALL_SOFFICE` build variable to any
value.

Also, you will need to configure the path to the libreoffice executable
via setting the `soffice` property in `<BASEDIR>/settings.json.docker` to
Expand Down Expand Up @@ -464,12 +451,8 @@ For the editor container, you can also make it full width by adding `full-width-
| How long may clients use served javascript code (in seconds)? Not setting this may cause problems during deployment. Set to 0 to disable caching.
| `21600` (6 hours)

| `ABIWORD`
| Absolute path to the Abiword executable. Abiword is needed to get advanced import/export features of pads. Setting it to null disables Abiword and will only allow plain text and HTML import/exports.
| `null`

| `SOFFICE`
| This is the absolute path to the soffice executable. LibreOffice can be used in lieu of Abiword to export pads. Setting it to null disables LibreOffice exporting.
| Absolute path to the soffice (LibreOffice) executable. Needed for advanced import/export of pads (docx, pdf, odt). Setting it to null disables LibreOffice and will only allow plain text and HTML import/exports.
| `null`

| `ALLOW_UNKNOWN_FILE_ENDS`
Expand Down
24 changes: 5 additions & 19 deletions doc/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,11 @@ The variable value has to be a space separated, double quoted list of plugin nam

Some plugins will need personalized settings. Just refer to the previous section, and include them in your custom `settings.json.docker`.

### Rebuilding including export functionality for DOC/PDF/ODT
### Rebuilding including export functionality for DOC/DOCX/PDF/ODT

If you want to be able to export your pads to DOC/PDF/ODT files, you can install
either Abiword or Libreoffice via setting a build variable.

#### Via Abiword

For installing Abiword, set the `INSTALL_ABIWORD` build variable to any value.

Also, you will need to configure the path to the abiword executable
via setting the `abiword` property in `<BASEDIR>/settings.json.docker` to
`/usr/bin/abiword` or via setting the environment variable `ABIWORD` to
`/usr/bin/abiword`.

#### Via Libreoffice

For installing Libreoffice instead, set the `INSTALL_SOFFICE` build variable
to any value.
If you want to be able to export your pads to DOC/DOCX/PDF/ODT files, you can
install Libreoffice via setting the `INSTALL_SOFFICE` build variable to any
value.

Also, you will need to configure the path to the libreoffice executable
via setting the `soffice` property in `<BASEDIR>/settings.json.docker` to
Expand Down Expand Up @@ -202,8 +189,7 @@ For the editor container, you can also make it full width by adding `full-width-
| `EDIT_ONLY` | Users may edit pads but not create new ones. Pad creation is only via the API. This applies both to group pads and regular pads. | `false` |
| `MINIFY` | If true, all css & js will be minified before sending to the client. This will improve the loading performance massively, but makes it difficult to debug the javascript/css | `true` |
| `MAX_AGE` | How long may clients use served javascript code (in seconds)? Not setting this may cause problems during deployment. Set to 0 to disable caching. | `21600` (6 hours) |
| `ABIWORD` | Absolute path to the Abiword executable. Abiword is needed to get advanced import/export features of pads. Setting it to null disables Abiword and will only allow plain text and HTML import/exports. | `null` |
| `SOFFICE` | This is the absolute path to the soffice executable. LibreOffice can be used in lieu of Abiword to export pads. Setting it to null disables LibreOffice exporting. | `null` |
| `SOFFICE` | Absolute path to the soffice (LibreOffice) executable. Needed for advanced import/export of pads (docx, pdf, odt). Setting it to null disables LibreOffice and will only allow plain text and HTML import/exports. | `null` |
| `ALLOW_UNKNOWN_FILE_ENDS` | Allow import of file types other than the supported ones: txt, doc, docx, rtf, odt, html & htm | `true` |
| `REQUIRE_AUTHENTICATION` | This setting is used if you require authentication of all users. Note: "/admin" always requires authentication. | `false` |
| `REQUIRE_AUTHORIZATION` | Require authorization by a module, or a user with is_admin set, see below. | `false` |
Expand Down
22 changes: 10 additions & 12 deletions settings.json.docker
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
* "password": "${PASSW:}" // if PASSW is not defined would result in password === ''
*
* If you want to use an empty value (null) as default value for a variable,
* simply do not set it, without putting any colons: "${ABIWORD}".
* simply do not set it, without putting any colons: "${SOFFICE}".
*
* 3) if you want to use newlines in the default value of a string parameter,
* use "\n" as usual.
Expand Down Expand Up @@ -349,24 +349,22 @@
"maxAge": "${MAX_AGE:21600}", // 60 * 60 * 6 = 6 hours

/*
* Absolute path to the Abiword executable.
* This is the absolute path to the soffice executable.
*
* Abiword is needed to get advanced import/export features of pads. Setting
* it to null disables Abiword and will only allow plain text and HTML
* import/exports.
* LibreOffice is used for advanced import/export of pads (docx, pdf, odt).
* Setting it to null disables LibreOffice and will only allow plain text
* and HTML import/exports.
*/
"abiword": "${ABIWORD:null}",
"soffice": "${SOFFICE:null}",

/*
* This is the absolute path to the soffice executable.
*
* LibreOffice can be used in lieu of Abiword to export pads.
* Setting it to null disables LibreOffice exporting.
* When true (the default), the "Microsoft Word" export button downloads a .docx file via
* LibreOffice (requires "soffice" to be set). Set to false to revert to legacy .doc output
* (which also requires "soffice").
*/
"soffice": "${SOFFICE:null}",
"docxExport": "${DOCX_EXPORT:true}",

/*
* Allow import of file types other than the supported ones:
* txt, doc, docx, rtf, odt, html & htm
*/
"allowUnknownFileEnds": "${ALLOW_UNKNOWN_FILE_ENDS:true}",
Expand Down
22 changes: 10 additions & 12 deletions settings.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
* "password": "${PASSW:}" // if PASSW is not defined would result in password === ''
*
* If you want to use an empty value (null) as default value for a variable,
* simply do not set it, without putting any colons: "${ABIWORD}".
* simply do not set it, without putting any colons: "${SOFFICE}".
*
* 3) if you want to use newlines in the default value of a string parameter,
* use "\n" as usual.
Expand Down Expand Up @@ -336,24 +336,22 @@
"maxAge": 21600, // 60 * 60 * 6 = 6 hours

/*
* Absolute path to the Abiword executable.
* This is the absolute path to the soffice executable.
*
* Abiword is needed to get advanced import/export features of pads. Setting
* it to null disables Abiword and will only allow plain text and HTML
* import/exports.
* LibreOffice is used for advanced import/export of pads (docx, pdf, odt).
* Setting it to null disables LibreOffice and will only allow plain text
* and HTML import/exports.
*/
"abiword": null,
"soffice": null,

/*
* This is the absolute path to the soffice executable.
*
* LibreOffice can be used in lieu of Abiword to export pads.
* Setting it to null disables LibreOffice exporting.
* When true (the default), the "Microsoft Word" export button downloads a .docx file via
* LibreOffice (requires "soffice" to be set). Set to false to revert to legacy .doc output
* (which also requires "soffice").
*/
"soffice": null,
"docxExport": true,

/*
* Allow import of file types other than the supported ones:
* txt, doc, docx, rtf, odt, html & htm
*/
"allowUnknownFileEnds": true,
Expand Down
2 changes: 1 addition & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
"pad.importExport.exportword": "Microsoft Word",
"pad.importExport.exportpdf": "PDF",
"pad.importExport.exportopen": "ODF (Open Document Format)",
"pad.importExport.abiword.innerHTML": "You only can import from plain text or HTML formats. For more advanced import features please <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">install AbiWord or LibreOffice</a>.",
"pad.importExport.noConverter.innerHTML": "You can only import from plain text or HTML formats. For more advanced import features, please <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">install LibreOffice</a>.",

"pad.modals.connected": "Connected.",
"pad.modals.reconnecting": "Reconnecting to your pad…",
Expand Down
7 changes: 2 additions & 5 deletions src/node/handler/ExportHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,15 @@ exports.doExport = async (req: any, res: any, padId: string, readOnlyId: string,
// ensure html can be collected by the garbage collector
html = null;

// send the convert job to the converter (abiword, libreoffice, ..)
// send the convert job to the converter (libreoffice)
const destFile = `${tempDirectory}/etherpad_export_${randNum}.${type}`;

// Allow plugins to overwrite the convert in export process
const result = await hooks.aCallAll('exportConvert', {srcFile, destFile, req, res});
if (result.length > 0) {
// console.log("export handled by plugin", destFile);
} else {
const converter =
settings.soffice != null ? require('../utils/LibreOffice')
: settings.abiword != null ? require('../utils/Abiword')
: null;
const converter = require('../utils/LibreOffice');
await converter.convertFile(srcFile, destFile, type);
}

Expand Down
7 changes: 1 addition & 6 deletions src/node/handler/ImportHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,6 @@ const rm = async (path: string) => {
let converter:any = null;
let exportExtension = 'htm';

// load abiword only if it is enabled and if soffice is disabled
if (settings.abiword != null && settings.soffice == null) {
converter = require('../utils/Abiword');
}

// load soffice only if it is enabled
if (settings.soffice != null) {
converter = require('../utils/LibreOffice');
Comment on lines 59 to 64
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. abiword removed without warn 📘 Rule violation ⚙ Maintainability

Abiword import/export support is removed outright (config + runtime converter path), but there is no
explicit deprecation period behavior that emits a WARN explaining the upcoming removal. This
violates the feature-removal deprecation requirement and increases upgrade risk for existing
deployments.
Agent Prompt
## Issue description
Abiword support was removed without an explicit deprecation mechanism and dedicated WARN messaging to guide users before removal.

## Issue Context
Compliance requires a deprecation phase that emits a WARN stating the feature will be removed in a future version. Consider temporarily accepting `abiword` config with a WARN and either continuing to support it for one release cycle or mapping it to the new supported path.

## Fix Focus Areas
- src/node/handler/ImportHandler.ts[59-66]
- settings.json.template[338-345]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Expand All @@ -81,7 +76,7 @@ const tmpDirectory = os.tmpdir();
*/
const doImport = async (req:any, res:any, padId:string, authorId:string) => {
// pipe to a file
// convert file to html via abiword or soffice
// convert file to html via soffice
// set html in the pad
const randNum = Math.floor(Math.random() * 0xFFFFFFFF);

Expand Down
3 changes: 1 addition & 2 deletions src/node/handler/PadMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import padutils from '../../static/js/pad_utils';
import readOnlyManager from '../db/ReadOnlyManager';
import settings, {
exportAvailable,
abiwordAvailable,
sofficeAvailable
} from '../utils/Settings';
const securityManager = require('../db/SecurityManager');
Expand Down Expand Up @@ -1043,9 +1042,9 @@ const handleClientReady = async (socket:any, message: ClientReadyMessage) => {
serverTimestamp: Date.now(),
sessionRefreshInterval: settings.cookie.sessionRefreshInterval,
userId: sessionInfo.author,
abiwordAvailable: abiwordAvailable(),
sofficeAvailable: sofficeAvailable(),
exportAvailable: exportAvailable(),
docxExport: settings.docxExport,
plugins: {
plugins: plugins.plugins,
parts: plugins.parts,
Expand Down
10 changes: 5 additions & 5 deletions src/node/hooks/express/importexport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,22 @@ exports.expressCreateServer = (hookName:string, args:ArgsExpressType, cb:Functio
args.app.use('/p/:pad{/:rev}/export/:type', limiter);
args.app.get('/p/:pad{/:rev}/export/:type', (req:any, res:any, next:Function) => {
(async () => {
const types = ['pdf', 'doc', 'txt', 'html', 'odt', 'etherpad'];
const types = ['pdf', 'doc', 'docx', 'txt', 'html', 'odt', 'etherpad'];
// send a 404 if we don't support this filetype
if (types.indexOf(req.params.type) === -1) {
return next();
}

// if abiword is disabled, and this is a format we only support with abiword, output a message
// if soffice is disabled, and this is a format we only support with soffice, output a message
if (exportAvailable() === 'no' &&
['odt', 'pdf', 'doc'].indexOf(req.params.type) !== -1) {
['odt', 'pdf', 'doc', 'docx'].indexOf(req.params.type) !== -1) {
Comment on lines +31 to +39
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. doc export still enabled 📎 Requirement gap ≡ Correctness

The export route still allows doc, so the system continues to expose/produce legacy DOC output
instead of fully replacing it with DOCX. This violates the requirement to replace DOC with DOCX for
the supported converter path(s).
Agent Prompt
## Issue description
The backend still supports `GET .../export/doc`, which means legacy DOC output is still exposed/produced, conflicting with the requirement to replace DOC with DOCX.

## Issue Context
The UI now uses `/export/docx`, but the server route allowlist still includes `doc` and the export handler writes the output using `.${type}`.

## Fix Focus Areas
- src/node/hooks/express/importexport.ts[31-39]
- src/node/handler/ExportHandler.ts[98-108]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

console.error(`Impossible to export pad "${req.params.pad}" in ${req.params.type} format.` +
' There is no converter configured');

// ACHTUNG: do not include req.params.type in res.send() because there is
// no HTML escaping and it would lead to an XSS
res.send('This export is not enabled at this Etherpad instance. Set the path to Abiword' +
' or soffice (LibreOffice) in settings.json to enable this feature');
res.send('This export is not enabled at this Etherpad instance. Set the path to soffice ' +
'(LibreOffice) in settings.json to enable this feature');
return;
}

Expand Down
93 changes: 0 additions & 93 deletions src/node/utils/Abiword.ts

This file was deleted.

Loading
Loading