mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-24 00:00:55 +01:00
c4564fba4b
Please note that the logic of this functionality is incorrect: this change is in preparation of the next commit, which fixes it.
709 lines
22 KiB
JavaScript
709 lines
22 KiB
JavaScript
/**
|
|
* The Settings Modul reads the settings out of settings.json and provides
|
|
* this information to the other modules
|
|
*/
|
|
|
|
/*
|
|
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
|
*
|
|
* Licensed 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.
|
|
*/
|
|
|
|
var absolutePaths = require('./AbsolutePaths');
|
|
var fs = require("fs");
|
|
var os = require("os");
|
|
var path = require('path');
|
|
var argv = require('./Cli').argv;
|
|
var npm = require("npm/lib/npm.js");
|
|
var jsonminify = require("jsonminify");
|
|
var log4js = require("log4js");
|
|
var randomString = require("./randomstring");
|
|
var suppressDisableMsg = " -- To suppress these warning messages change suppressErrorsInPadText to true in your settings.json\n";
|
|
var _ = require("underscore");
|
|
|
|
/* Root path of the installation */
|
|
exports.root = absolutePaths.findEtherpadRoot();
|
|
console.log(`All relative paths will be interpreted relative to the identified Etherpad base dir: ${exports.root}`);
|
|
|
|
/**
|
|
* The app title, visible e.g. in the browser window
|
|
*/
|
|
exports.title = "Etherpad";
|
|
|
|
/**
|
|
* The app favicon fully specified url, visible e.g. in the browser window
|
|
*/
|
|
exports.favicon = "favicon.ico";
|
|
exports.faviconPad = "../" + exports.favicon;
|
|
exports.faviconTimeslider = "../../" + exports.favicon;
|
|
|
|
/*
|
|
* Skin name.
|
|
*
|
|
* Initialized to null, so we can spot an old configuration file and invite the
|
|
* user to update it before falling back to the default.
|
|
*/
|
|
exports.skinName = null;
|
|
|
|
/**
|
|
* The IP ep-lite should listen to
|
|
*/
|
|
exports.ip = "0.0.0.0";
|
|
|
|
/**
|
|
* The Port ep-lite should listen to
|
|
*/
|
|
exports.port = process.env.PORT || 9001;
|
|
|
|
/**
|
|
* Should we suppress Error messages from being in Pad Contents
|
|
*/
|
|
exports.suppressErrorsInPadText = false;
|
|
|
|
/**
|
|
* The SSL signed server key and the Certificate Authority's own certificate
|
|
* default case: ep-lite does *not* use SSL. A signed server key is not required in this case.
|
|
*/
|
|
exports.ssl = false;
|
|
|
|
/**
|
|
* socket.io transport methods
|
|
**/
|
|
exports.socketTransportProtocols = ['xhr-polling', 'jsonp-polling', 'htmlfile'];
|
|
|
|
/*
|
|
* The Type of the database
|
|
*/
|
|
exports.dbType = "dirty";
|
|
/**
|
|
* This setting is passed with dbType to ueberDB to set up the database
|
|
*/
|
|
exports.dbSettings = { "filename" : path.join(exports.root, "var/dirty.db") };
|
|
|
|
/**
|
|
* The default Text of a new pad
|
|
*/
|
|
exports.defaultPadText = "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nEtherpad on Github: https:\/\/github.com\/ether\/etherpad-lite\n";
|
|
|
|
/**
|
|
* The default Pad Settings for a user (Can be overridden by changing the setting
|
|
*/
|
|
exports.padOptions = {
|
|
"noColors": false,
|
|
"showControls": true,
|
|
"showChat": true,
|
|
"showLineNumbers": true,
|
|
"useMonospaceFont": false,
|
|
"userName": false,
|
|
"userColor": false,
|
|
"rtl": false,
|
|
"alwaysShowChat": false,
|
|
"chatAndUsers": false,
|
|
"lang": "en-gb"
|
|
},
|
|
|
|
/**
|
|
* Whether certain shortcut keys are enabled for a user in the pad
|
|
*/
|
|
exports.padShortcutEnabled = {
|
|
"altF9" : true,
|
|
"altC" : true,
|
|
"delete" : true,
|
|
"cmdShift2" : true,
|
|
"return" : true,
|
|
"esc" : true,
|
|
"cmdS" : true,
|
|
"tab" : true,
|
|
"cmdZ" : true,
|
|
"cmdY" : true,
|
|
"cmdB" : true,
|
|
"cmdI" : true,
|
|
"cmdU" : true,
|
|
"cmd5" : true,
|
|
"cmdShiftL" : true,
|
|
"cmdShiftN" : true,
|
|
"cmdShift1" : true,
|
|
"cmdShiftC" : true,
|
|
"cmdH" : true,
|
|
"ctrlHome" : true,
|
|
"pageUp" : true,
|
|
"pageDown" : true,
|
|
},
|
|
|
|
/**
|
|
* The toolbar buttons and order.
|
|
*/
|
|
exports.toolbar = {
|
|
left: [
|
|
["bold", "italic", "underline", "strikethrough"],
|
|
["orderedlist", "unorderedlist", "indent", "outdent"],
|
|
["undo", "redo"],
|
|
["clearauthorship"]
|
|
],
|
|
right: [
|
|
["importexport", "timeslider", "savedrevision"],
|
|
["settings", "embed"],
|
|
["showusers"]
|
|
],
|
|
timeslider: [
|
|
["timeslider_export", "timeslider_settings", "timeslider_returnToPad"]
|
|
]
|
|
}
|
|
|
|
/**
|
|
* A flag that requires any user to have a valid session (via the api) before accessing a pad
|
|
*/
|
|
exports.requireSession = false;
|
|
|
|
/**
|
|
* A flag that prevents users from creating new pads
|
|
*/
|
|
exports.editOnly = false;
|
|
|
|
/**
|
|
* A flag that bypasses password prompts for users with valid sessions
|
|
*/
|
|
exports.sessionNoPassword = false;
|
|
|
|
/**
|
|
* Max age that responses will have (affects caching layer).
|
|
*/
|
|
exports.maxAge = 1000*60*60*6; // 6 hours
|
|
|
|
/**
|
|
* A flag that shows if minification is enabled or not
|
|
*/
|
|
exports.minify = true;
|
|
|
|
/**
|
|
* The path of the abiword executable
|
|
*/
|
|
exports.abiword = null;
|
|
|
|
/**
|
|
* The path of the libreoffice executable
|
|
*/
|
|
exports.soffice = null;
|
|
|
|
/**
|
|
* The path of the tidy executable
|
|
*/
|
|
exports.tidyHtml = null;
|
|
|
|
/**
|
|
* Should we support none natively supported file types on import?
|
|
*/
|
|
exports.allowUnknownFileEnds = true;
|
|
|
|
/**
|
|
* The log level of log4js
|
|
*/
|
|
exports.loglevel = "INFO";
|
|
|
|
/**
|
|
* Disable IP logging
|
|
*/
|
|
exports.disableIPlogging = false;
|
|
|
|
/**
|
|
* Number of seconds to automatically reconnect pad
|
|
*/
|
|
exports.automaticReconnectionTimeout = 0;
|
|
|
|
/**
|
|
* Disable Load Testing
|
|
*/
|
|
exports.loadTest = false;
|
|
|
|
/**
|
|
* Enable indentation on new lines
|
|
*/
|
|
exports.indentationOnNewLine = true;
|
|
|
|
/*
|
|
* log4js appender configuration
|
|
*/
|
|
exports.logconfig = { appenders: [{ type: "console" }]};
|
|
|
|
/*
|
|
* Session Key, do not sure this.
|
|
*/
|
|
exports.sessionKey = false;
|
|
|
|
/*
|
|
* Trust Proxy, whether or not trust the x-forwarded-for header.
|
|
*/
|
|
exports.trustProxy = false;
|
|
|
|
/*
|
|
* This setting is used if you need authentication and/or
|
|
* authorization. Note: /admin always requires authentication, and
|
|
* either authorization by a module, or a user with is_admin set
|
|
*/
|
|
exports.requireAuthentication = false;
|
|
exports.requireAuthorization = false;
|
|
exports.users = {};
|
|
|
|
/*
|
|
* Show settings in admin page, by default it is true
|
|
*/
|
|
exports.showSettingsInAdminPage = true;
|
|
|
|
/*
|
|
* By default, when caret is moved out of viewport, it scrolls the minimum
|
|
* height needed to make this line visible.
|
|
*/
|
|
exports.scrollWhenFocusLineIsOutOfViewport = {
|
|
/*
|
|
* Percentage of viewport height to be additionally scrolled.
|
|
*/
|
|
"percentage": {
|
|
"editionAboveViewport": 0,
|
|
"editionBelowViewport": 0
|
|
},
|
|
|
|
/*
|
|
* Time (in milliseconds) used to animate the scroll transition. Set to 0 to
|
|
* disable animation
|
|
*/
|
|
"duration": 0,
|
|
|
|
/*
|
|
* Percentage of viewport height to be additionally scrolled when user presses arrow up
|
|
* in the line of the top of the viewport.
|
|
*/
|
|
"percentageToScrollWhenUserPressesArrowUp": 0,
|
|
|
|
/*
|
|
* Flag to control if it should scroll when user places the caret in the last
|
|
* line of the viewport
|
|
*/
|
|
"scrollWhenCaretIsInTheLastLineOfViewport": false
|
|
};
|
|
|
|
/*
|
|
* Expose Etherpad version in the web interface and in the Server http header.
|
|
*
|
|
* Do not enable on production machines.
|
|
*/
|
|
exports.exposeVersion = false;
|
|
|
|
// checks if abiword is avaiable
|
|
exports.abiwordAvailable = function()
|
|
{
|
|
if (exports.abiword != null) {
|
|
return os.type().indexOf("Windows") != -1 ? "withoutPDF" : "yes";
|
|
} else {
|
|
return "no";
|
|
}
|
|
};
|
|
|
|
exports.sofficeAvailable = function() {
|
|
if (exports.soffice != null) {
|
|
return os.type().indexOf("Windows") != -1 ? "withoutPDF": "yes";
|
|
} else {
|
|
return "no";
|
|
}
|
|
};
|
|
|
|
exports.exportAvailable = function() {
|
|
var abiword = exports.abiwordAvailable();
|
|
var soffice = exports.sofficeAvailable();
|
|
|
|
if (abiword == "no" && soffice == "no") {
|
|
return "no";
|
|
} else if ((abiword == "withoutPDF" && soffice == "no") || (abiword == "no" && soffice == "withoutPDF")) {
|
|
return "withoutPDF";
|
|
} else {
|
|
return "yes";
|
|
}
|
|
};
|
|
|
|
// Provide git version if available
|
|
exports.getGitCommit = function() {
|
|
var version = "";
|
|
try {
|
|
var rootPath = path.resolve(npm.dir, '..');
|
|
if (fs.lstatSync(rootPath + '/.git').isFile()) {
|
|
rootPath = fs.readFileSync(rootPath + '/.git', "utf8");
|
|
rootPath = rootPath.split(' ').pop().trim();
|
|
} else {
|
|
rootPath += '/.git';
|
|
}
|
|
var ref = fs.readFileSync(rootPath + "/HEAD", "utf-8");
|
|
var refPath = rootPath + "/" + ref.substring(5, ref.indexOf("\n"));
|
|
version = fs.readFileSync(refPath, "utf-8");
|
|
version = version.substring(0, 7);
|
|
} catch(e) {
|
|
console.warn("Can't get git version for server header\n" + e.message)
|
|
}
|
|
return version;
|
|
}
|
|
|
|
// Return etherpad version from package.json
|
|
exports.getEpVersion = function() {
|
|
return require('ep_etherpad-lite/package.json').version;
|
|
}
|
|
|
|
/**
|
|
* Receives a settingsObj and, if the property name is a valid configuration
|
|
* item, stores it in the module's exported properties via a side effect.
|
|
*
|
|
* This code refactors a previous version that copied & pasted the same code for
|
|
* both "settings.json" and "credentials.json".
|
|
*/
|
|
function storeSettings(settingsObj) {
|
|
for (var i in settingsObj) {
|
|
// test if the setting starts with a lowercase character
|
|
if (i.charAt(0).search("[a-z]") !== 0) {
|
|
console.warn(`Settings should start with a lowercase character: '${i}'`);
|
|
}
|
|
|
|
// we know this setting, so we overwrite it
|
|
// or it's a settings hash, specific to a plugin
|
|
if (exports[i] !== undefined || i.indexOf('ep_') == 0) {
|
|
if (_.isObject(settingsObj[i]) && !_.isArray(settingsObj[i])) {
|
|
exports[i] = _.defaults(settingsObj[i], exports[i]);
|
|
} else {
|
|
exports[i] = settingsObj[i];
|
|
}
|
|
} else {
|
|
// this setting is unknown, output a warning and throw it away
|
|
console.warn(`Unknown Setting: '${i}'. This setting doesn't exist or it was removed`);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If stringValue is a numeric string, or its value is "true" or "false", coerce
|
|
* them to appropriate JS types. Otherwise return stringValue as-is.
|
|
*/
|
|
function coerceValue(stringValue) {
|
|
// cooked from https://stackoverflow.com/questions/175739/built-in-way-in-javascript-to-check-if-a-string-is-a-valid-number
|
|
const isNumeric = !isNaN(stringValue) && !isNaN(parseFloat(stringValue) && isFinite(stringValue));
|
|
|
|
if (isNumeric) {
|
|
// detected numeric string. Coerce to a number
|
|
|
|
return +stringValue;
|
|
}
|
|
|
|
// the boolean literal case is easy.
|
|
if (stringValue === "true" ) {
|
|
return true;
|
|
}
|
|
|
|
if (stringValue === "false") {
|
|
return false;
|
|
}
|
|
|
|
// otherwise, return this value as-is
|
|
return stringValue;
|
|
}
|
|
|
|
/**
|
|
* Takes a javascript object containing Etherpad's configuration, and returns
|
|
* another object, in which all the string properties whose value is of the form
|
|
* "${ENV_VAR}" or "${ENV_VAR:default_value}" got their value replaced with the
|
|
* contents of the given environment variable, or with a default value.
|
|
*
|
|
* By definition, an environment variable's value is always a string. However,
|
|
* the code base makes use of the various json types. To maintain compatiblity,
|
|
* some heuristics is applied:
|
|
*
|
|
* - if ENV_VAR does not exist in the environment, null is returned;
|
|
* - if ENV_VAR's value is "true" or "false", it is converted to the js boolean
|
|
* values true or false;
|
|
* - if ENV_VAR's value looks like a number, it is converted to a js number
|
|
* (details in the code).
|
|
*
|
|
* The following is a scheme of the behaviour of this function:
|
|
*
|
|
* +---------------------------+---------------+------------------+
|
|
* | Configuration string in | Value of | Resulting confi- |
|
|
* | settings.json | ENV_VAR | guration value |
|
|
* |---------------------------|---------------|------------------|
|
|
* | "${ENV_VAR}" | "some_string" | "some_string" |
|
|
* | "${ENV_VAR}" | "9001" | 9001 |
|
|
* | "${ENV_VAR}" | undefined | null |
|
|
* | "${ENV_VAR:some_default}" | "some_string" | "some_string" |
|
|
* | "${ENV_VAR:some_default}" | undefined | "some_default" |
|
|
* +---------------------------+---------------+------------------+
|
|
*
|
|
* IMPLEMENTATION NOTE: variable substitution is performed doing a round trip
|
|
* conversion to/from json, using a custom replacer parameter in
|
|
* JSON.stringify(), and parsing the JSON back again. This ensures that
|
|
* environment variable replacement is performed even on nested objects.
|
|
*
|
|
* see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter
|
|
*/
|
|
function lookupEnvironmentVariables(obj) {
|
|
const stringifiedAndReplaced = JSON.stringify(obj, (key, value) => {
|
|
/*
|
|
* the first invocation of replacer() is with an empty key. Just go on, or
|
|
* we would zap the entire object.
|
|
*/
|
|
if (key === '') {
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
* If we received from the configuration file a number, a boolean or
|
|
* something that is not a string, we can be sure that it was a literal
|
|
* value. No need to perform any variable substitution.
|
|
*
|
|
* The environment variable expansion syntax "${ENV_VAR}" is just a string
|
|
* of specific form, after all.
|
|
*/
|
|
if (typeof value !== 'string') {
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
* Let's check if the string value looks like a variable expansion (e.g.:
|
|
* "${ENV_VAR}" or "${ENV_VAR:default_value}")
|
|
*/
|
|
// MUXATOR 2019-03-21: we could use named capture groups here once we migrate to nodejs v10
|
|
const match = value.match(/^\$\{([^:]*)(:(.*))?\}$/);
|
|
|
|
if (match === null) {
|
|
// no match: use the value literally, without any substitution
|
|
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
* We found the name of an environment variable. Let's read its actual value
|
|
* and its default value, if given
|
|
*/
|
|
const envVarName = match[1];
|
|
const envVarValue = process.env[envVarName];
|
|
const defaultValue = match[3];
|
|
|
|
if ((envVarValue === undefined) && (defaultValue === undefined)) {
|
|
console.warn(`Environment variable "${envVarName}" does not contain any value for configuration key "${key}", and no default was given. Returning null. Please check your configuration and environment settings.`);
|
|
|
|
/*
|
|
* We have to return null, because if we just returned undefined, the
|
|
* configuration item "key" would be stripped from the returned object.
|
|
*/
|
|
return null;
|
|
}
|
|
|
|
if ((envVarValue === undefined) && (defaultValue !== undefined)) {
|
|
console.debug(`Environment variable "${envVarName}" not found for configuration key "${key}". Falling back to default value.`);
|
|
|
|
return coerceValue(defaultValue);
|
|
}
|
|
|
|
// envVarName contained some value.
|
|
|
|
/*
|
|
* For numeric and boolean strings let's convert it to proper types before
|
|
* returning it, in order to maintain backward compatibility.
|
|
*/
|
|
console.debug(`Configuration key "${key}" will be read from environment variable "${envVarName}"`);
|
|
|
|
return coerceValue(envVarValue);
|
|
});
|
|
|
|
const newSettings = JSON.parse(stringifiedAndReplaced);
|
|
|
|
return newSettings;
|
|
}
|
|
|
|
/**
|
|
* - reads the JSON configuration file settingsFilename from disk
|
|
* - strips the comments
|
|
* - replaces environment variables calling lookupEnvironmentVariables()
|
|
* - returns a parsed Javascript object
|
|
*
|
|
* The isSettings variable only controls the error logging.
|
|
*/
|
|
function parseSettings(settingsFilename, isSettings) {
|
|
let settingsStr = "";
|
|
|
|
let settingsType, notFoundMessage, notFoundFunction;
|
|
|
|
if (isSettings) {
|
|
settingsType = "settings";
|
|
notFoundMessage = "Continuing using defaults!";
|
|
notFoundFunction = console.warn;
|
|
} else {
|
|
settingsType = "credentials";
|
|
notFoundMessage = "Ignoring.";
|
|
notFoundFunction = console.info;
|
|
}
|
|
|
|
try {
|
|
//read the settings file
|
|
settingsStr = fs.readFileSync(settingsFilename).toString();
|
|
} catch(e) {
|
|
notFoundFunction(`No ${settingsType} file found in ${settingsFilename}. ${notFoundMessage}`);
|
|
|
|
// or maybe undefined!
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
settingsStr = jsonminify(settingsStr).replace(",]","]").replace(",}","}");
|
|
|
|
const settings = JSON.parse(settingsStr);
|
|
|
|
console.info(`${settingsType} loaded from: ${settingsFilename}`);
|
|
|
|
const replacedSettings = lookupEnvironmentVariables(settings);
|
|
|
|
return replacedSettings;
|
|
} catch(e) {
|
|
console.error(`There was an error processing your ${settingsType} file from ${settingsFilename}: ${e.message}`);
|
|
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
exports.reloadSettings = function reloadSettings() {
|
|
// Discover where the settings file lives
|
|
var settingsFilename = absolutePaths.makeAbsolute(argv.settings || "settings.json");
|
|
|
|
// Discover if a credential file exists
|
|
var credentialsFilename = absolutePaths.makeAbsolute(argv.credentials || "credentials.json");
|
|
|
|
// try to parse the settings
|
|
var settings = parseSettings(settingsFilename, true);
|
|
|
|
// try to parse the credentials
|
|
var credentials = parseSettings(credentialsFilename, false);
|
|
|
|
storeSettings(settings);
|
|
storeSettings(credentials);
|
|
|
|
log4js.configure(exports.logconfig);//Configure the logging appenders
|
|
log4js.setGlobalLogLevel(exports.loglevel);//set loglevel
|
|
process.env['DEBUG'] = 'socket.io:' + exports.loglevel; // Used by SocketIO for Debug
|
|
log4js.replaceConsole();
|
|
|
|
if (!exports.skinName) {
|
|
console.warn(`No "skinName" parameter found. Please check out settings.json.template and update your settings.json. Falling back to the default "no-skin".`);
|
|
exports.skinName = "no-skin";
|
|
}
|
|
|
|
// checks if skinName has an acceptable value, otherwise falls back to "no-skin"
|
|
if (exports.skinName) {
|
|
const skinBasePath = path.join(exports.root, "src", "static", "skins");
|
|
const countPieces = exports.skinName.split(path.sep).length;
|
|
|
|
if (countPieces != 1) {
|
|
console.error(`skinName must be the name of a directory under "${skinBasePath}". This is not valid: "${exports.skinName}". Falling back to the default "no-skin".`);
|
|
|
|
exports.skinName = "no-skin";
|
|
}
|
|
|
|
// informative variable, just for the log messages
|
|
var skinPath = path.normalize(path.join(skinBasePath, exports.skinName));
|
|
|
|
// what if someone sets skinName == ".." or "."? We catch him!
|
|
if (absolutePaths.isSubdir(skinBasePath, skinPath) === false) {
|
|
console.error(`Skin path ${skinPath} must be a subdirectory of ${skinBasePath}. Falling back to the default "no-skin".`);
|
|
|
|
exports.skinName = "no-skin";
|
|
skinPath = path.join(skinBasePath, exports.skinName);
|
|
}
|
|
|
|
if (fs.existsSync(skinPath) === false) {
|
|
console.error(`Skin path ${skinPath} does not exist. Falling back to the default "no-skin".`);
|
|
exports.skinName = "no-skin";
|
|
skinPath = path.join(skinBasePath, exports.skinName);
|
|
}
|
|
|
|
console.info(`Using skin "${exports.skinName}" in dir: ${skinPath}`);
|
|
}
|
|
|
|
if (exports.users) {
|
|
/*
|
|
* Prune from export.users any user that has no password attribute, or whose
|
|
* password attribute is "null".
|
|
*
|
|
* This is used by the settings.json in the default Dockerfile to eschew
|
|
* creating an admin user if no password is set.
|
|
*/
|
|
var filteredUsers = _.filter(exports.users, function(userProperties, username) {
|
|
if ((userProperties.hasOwnProperty("password")) || userProperties.password !== null) {
|
|
return true;
|
|
}
|
|
|
|
console.warn(`The password for ${username} is null. This means the user must not be created. Removing it.`);
|
|
|
|
return false;
|
|
});
|
|
|
|
exports.users = filteredUsers;
|
|
}
|
|
|
|
if (exports.abiword) {
|
|
// Check abiword actually exists
|
|
if (exports.abiword != null) {
|
|
fs.exists(exports.abiword, function(exists) {
|
|
if (!exists) {
|
|
var abiwordError = "Abiword does not exist at this path, check your settings file.";
|
|
if (!exports.suppressErrorsInPadText) {
|
|
exports.defaultPadText = exports.defaultPadText + "\nError: " + abiwordError + suppressDisableMsg;
|
|
}
|
|
console.error(abiwordError + ` File location: ${exports.abiword}`);
|
|
exports.abiword = null;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
if (exports.soffice) {
|
|
fs.exists(exports.soffice, function(exists) {
|
|
if (!exists) {
|
|
var sofficeError = "soffice (libreoffice) does not exist at this path, check your settings file.";
|
|
|
|
if (!exports.suppressErrorsInPadText) {
|
|
exports.defaultPadText = exports.defaultPadText + "\nError: " + sofficeError + suppressDisableMsg;
|
|
}
|
|
console.error(sofficeError + ` File location: ${exports.soffice}`);
|
|
exports.soffice = null;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (!exports.sessionKey) {
|
|
var sessionkeyFilename = absolutePaths.makeAbsolute(argv.sessionkey || "./SESSIONKEY.txt");
|
|
try {
|
|
exports.sessionKey = fs.readFileSync(sessionkeyFilename,"utf8");
|
|
console.info(`Session key loaded from: ${sessionkeyFilename}`);
|
|
} catch(e) {
|
|
console.info(`Session key file "${sessionkeyFilename}" not found. Creating with random contents.`);
|
|
exports.sessionKey = randomString(32);
|
|
fs.writeFileSync(sessionkeyFilename,exports.sessionKey,"utf8");
|
|
}
|
|
} else {
|
|
console.warn("Declaring the sessionKey in the settings.json is deprecated. This value is auto-generated now. Please remove the setting from the file.");
|
|
}
|
|
|
|
if (exports.dbType === "dirty") {
|
|
var dirtyWarning = "DirtyDB is used. This is fine for testing but not recommended for production.";
|
|
if (!exports.suppressErrorsInPadText) {
|
|
exports.defaultPadText = exports.defaultPadText + "\nWarning: " + dirtyWarning + suppressDisableMsg;
|
|
}
|
|
|
|
exports.dbSettings.filename = absolutePaths.makeAbsolute(exports.dbSettings.filename);
|
|
console.warn(dirtyWarning + ` File location: ${exports.dbSettings.filename}`);
|
|
}
|
|
};
|
|
|
|
// initially load settings
|
|
exports.reloadSettings();
|