2011-05-14 18:42:04 +02:00
/ * *
2013-11-26 09:20:59 +01:00
* The Settings Modul reads the settings out of settings . json and provides
2011-05-30 16:53:11 +02:00
* this information to the other modules
* /
/ *
2011-08-11 16:26:41 +02:00
* 2011 Peter 'Pita' Martischka ( Primary Technology Ltd )
2011-05-14 18:42:04 +02:00
*
* 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 .
* /
2018-08-22 00:47:47 +02:00
var absolutePaths = require ( './AbsolutePaths' ) ;
2011-05-14 18:22:25 +02:00
var fs = require ( "fs" ) ;
2011-12-18 06:18:35 +01:00
var os = require ( "os" ) ;
2012-01-05 11:24:33 +01:00
var path = require ( 'path' ) ;
2012-02-21 20:20:45 +01:00
var argv = require ( './Cli' ) . argv ;
2012-02-26 13:07:51 +01:00
var npm = require ( "npm/lib/npm.js" ) ;
2013-11-26 09:20:59 +01:00
var jsonminify = require ( "jsonminify" ) ;
2013-01-13 12:20:49 +01:00
var log4js = require ( "log4js" ) ;
2014-01-15 20:25:47 +01:00
var randomString = require ( "./randomstring" ) ;
2015-04-06 01:13:38 +02:00
var suppressDisableMsg = " -- To suppress these warning messages change suppressErrorsInPadText to true in your settings.json\n" ;
2015-04-11 23:01:46 +02:00
var _ = require ( "underscore" ) ;
2012-02-26 13:07:51 +01:00
/* Root path of the installation */
2018-08-22 00:47:47 +02:00
exports . root = absolutePaths . findEtherpadRoot ( ) ;
console . log ( ` All relative paths will be interpreted relative to the identified Etherpad base dir: ${ exports . root } ` ) ;
2011-05-14 18:22:25 +02:00
2012-11-02 12:30:57 +01:00
/ * *
* The app title , visible e . g . in the browser window
* /
2013-08-23 00:32:25 +02:00
exports . title = "Etherpad" ;
2012-11-02 12:30:57 +01:00
2012-11-04 11:26:17 +01:00
/ * *
* The app favicon fully specified url , visible e . g . in the browser window
* /
exports . favicon = "favicon.ico" ;
2012-11-30 23:50:54 +01:00
exports . faviconPad = "../" + exports . favicon ;
exports . faviconTimeslider = "../../" + exports . favicon ;
2012-11-04 11:26:17 +01:00
2018-08-19 03:36:18 +02:00
/ *
* 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 ;
2011-07-30 17:39:53 +02:00
/ * *
* The IP ep - lite should listen to
* /
exports . ip = "0.0.0.0" ;
2013-11-26 09:20:59 +01:00
2011-05-30 16:53:11 +02:00
/ * *
* The Port ep - lite should listen to
* /
2012-10-25 19:21:34 +02:00
exports . port = process . env . PORT || 9001 ;
2012-11-22 10:12:58 +01:00
2015-04-06 01:13:38 +02:00
/ * *
* Should we suppress Error messages from being in Pad Contents
* /
exports . suppressErrorsInPadText = false ;
2012-11-22 10:12:58 +01:00
/ * *
* 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 ;
2012-12-02 18:28:28 +01:00
/ * *
2012-12-02 18:44:39 +01:00
* socket . io transport methods
2012-12-02 18:28:28 +01:00
* * /
exports . socketTransportProtocols = [ 'xhr-polling' , 'jsonp-polling' , 'htmlfile' ] ;
2011-05-30 16:53:11 +02:00
/ *
* The Type of the database
* /
2011-08-17 20:26:56 +02:00
exports . dbType = "dirty" ;
2011-05-30 16:53:11 +02:00
/ * *
* This setting is passed with dbType to ueberDB to set up the database
* /
2018-08-21 21:57:13 +02:00
exports . dbSettings = { "filename" : path . join ( exports . root , "var/dirty.db" ) } ;
2012-07-08 18:59:46 +02:00
2011-05-30 16:53:11 +02:00
/ * *
* The default Text of a new pad
* /
2015-08-04 04:53:54 +02:00
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" ;
2011-11-21 07:45:37 +01:00
2015-04-11 22:22:00 +02:00
/ * *
* 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"
2016-01-21 13:38:41 +01:00
} ,
/ * *
* Whether certain shortcut keys are enabled for a user in the pad
* /
exports . padShortcutEnabled = {
"altF9" : true ,
"altC" : true ,
"delete" : true ,
"cmdShift2" : true ,
"return" : true ,
2017-05-11 17:35:25 +02:00
"esc" : true ,
2016-01-21 13:38:41 +01:00
"cmdS" : true ,
"tab" : true ,
"cmdZ" : true ,
"cmdY" : true ,
"cmdB" : true ,
"cmdI" : true ,
"cmdU" : true ,
"cmd5" : true ,
"cmdShiftL" : true ,
"cmdShiftN" : true ,
2017-05-11 19:56:09 +02:00
"cmdShift1" : true ,
2016-01-21 13:38:41 +01:00
"cmdShiftC" : true ,
"cmdH" : true ,
"ctrlHome" : true ,
"pageUp" : true ,
"pageDown" : true ,
} ,
2015-04-11 22:22:00 +02:00
2013-03-09 23:57:42 +01:00
/ * *
* 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" ]
2014-03-30 13:02:41 +02:00
] ,
timeslider : [
2015-04-05 16:18:36 +02:00
[ "timeslider_export" , "timeslider_settings" , "timeslider_returnToPad" ]
2013-03-09 23:57:42 +01:00
]
}
2011-11-21 07:45:37 +01:00
/ * *
* A flag that requires any user to have a valid session ( via the api ) before accessing a pad
* /
exports . requireSession = false ;
2011-11-21 18:44:33 +01:00
/ * *
* A flag that prevents users from creating new pads
* /
exports . editOnly = false ;
2013-05-29 16:53:14 +02:00
/ * *
2013-05-29 16:54:39 +02:00
* A flag that bypasses password prompts for users with valid sessions
2013-05-29 16:53:14 +02:00
* /
exports . sessionNoPassword = false ;
2012-02-07 08:04:02 +01:00
/ * *
* Max age that responses will have ( affects caching layer ) .
* /
exports . maxAge = 1000 * 60 * 60 * 6 ; // 6 hours
2011-05-30 16:53:11 +02:00
/ * *
* A flag that shows if minification is enabled or not
* /
2011-05-28 19:09:17 +02:00
exports . minify = true ;
2011-05-14 18:22:25 +02:00
2011-07-19 20:48:11 +02:00
/ * *
* The path of the abiword executable
* /
exports . abiword = null ;
2015-10-20 20:46:08 +02:00
/ * *
* The path of the libreoffice executable
* /
exports . soffice = null ;
2015-05-18 17:24:41 +02:00
/ * *
* The path of the tidy executable
* /
exports . tidyHtml = null ;
2014-07-22 16:46:31 +02:00
/ * *
* Should we support none natively supported file types on import ?
* /
exports . allowUnknownFileEnds = true ;
2011-08-17 18:45:47 +02:00
/ * *
* The log level of log4js
* /
exports . loglevel = "INFO" ;
2013-10-19 21:37:11 +02:00
/ * *
* Disable IP logging
* /
exports . disableIPlogging = false ;
2017-04-04 16:09:24 +02:00
/ * *
* Number of seconds to automatically reconnect pad
* /
exports . automaticReconnectionTimeout = 0 ;
2015-05-18 17:24:41 +02:00
/ * *
2015-02-17 00:02:19 +01:00
* Disable Load Testing
* /
exports . loadTest = false ;
2015-10-13 23:39:23 +02:00
/ * *
* Enable indentation on new lines
* /
exports . indentationOnNewLine = true ;
2013-01-13 12:20:49 +01:00
/ *
2019-04-16 00:17:56 +02:00
* log4js appender configuration
* /
2013-01-13 12:20:49 +01:00
exports . logconfig = { appenders : [ { type : "console" } ] } ;
2013-02-13 22:51:09 +01:00
/ *
2019-04-16 00:17:56 +02:00
* Session Key , do not sure this .
* /
2013-02-13 22:51:09 +01:00
exports . sessionKey = false ;
2013-04-24 12:19:41 +02:00
/ *
2019-04-16 00:17:56 +02:00
* Trust Proxy , whether or not trust the x - forwarded - for header .
* /
2013-04-24 12:19:41 +02:00
exports . trustProxy = false ;
2019-04-16 00:17:56 +02:00
/ *
* This setting is used if you need authentication and / or
2012-04-19 14:25:12 +02:00
* authorization . Note : / a d m i n a l w a y s r e q u i r e s a u t h e n t i c a t i o n , a n d
2019-04-16 00:17:56 +02:00
* either authorization by a module , or a user with is _admin set
* /
2012-04-19 14:25:12 +02:00
exports . requireAuthentication = false ;
exports . requireAuthorization = false ;
exports . users = { } ;
2012-04-02 18:45:37 +02:00
2016-05-22 17:28:51 +02:00
/ *
2019-04-16 00:17:56 +02:00
* Show settings in admin page , by default it is true
* /
2016-05-22 17:28:51 +02:00
exports . showSettingsInAdminPage = true ;
2018-01-03 22:57:28 +01:00
/ *
2019-04-16 00:17:56 +02:00
* By default , when caret is moved out of viewport , it scrolls the minimum
* height needed to make this line visible .
* /
2018-01-03 22:57:28 +01:00
exports . scrollWhenFocusLineIsOutOfViewport = {
/ *
2019-04-16 00:17:56 +02:00
* Percentage of viewport height to be additionally scrolled .
* /
2018-01-03 22:57:28 +01:00
"percentage" : {
"editionAboveViewport" : 0 ,
"editionBelowViewport" : 0
} ,
2019-04-16 00:17:56 +02:00
2018-01-03 22:57:28 +01:00
/ *
2019-04-16 00:17:56 +02:00
* Time ( in milliseconds ) used to animate the scroll transition . Set to 0 to
* disable animation
* /
2018-01-03 22:57:28 +01:00
"duration" : 0 ,
2019-04-16 00:17:56 +02:00
2018-01-03 22:57:28 +01:00
/ *
2019-04-16 00:17:56 +02:00
* Percentage of viewport height to be additionally scrolled when user presses arrow up
* in the line of the top of the viewport .
2018-01-03 22:57:28 +01:00
* /
"percentageToScrollWhenUserPressesArrowUp" : 0 ,
2019-04-16 00:17:56 +02:00
/ *
* Flag to control if it should scroll when user places the caret in the last
* line of the viewport
* /
2018-01-03 22:57:28 +01:00
"scrollWhenCaretIsInTheLastLineOfViewport" : false
} ;
2019-04-15 16:02:46 +02:00
/ *
2019-04-15 17:03:06 +02:00
* Expose Etherpad version in the web interface and in the Server http header .
2019-04-15 16:02:46 +02:00
*
* Do not enable on production machines .
* /
exports . exposeVersion = false ;
2019-04-16 00:17:56 +02:00
// checks if abiword is avaiable
2011-12-18 06:18:35 +01:00
exports . abiwordAvailable = function ( )
{
2019-03-10 01:46:55 +01:00
if ( exports . abiword != null ) {
2011-12-18 06:18:35 +01:00
return os . type ( ) . indexOf ( "Windows" ) != - 1 ? "withoutPDF" : "yes" ;
2019-03-10 01:46:55 +01:00
} else {
2011-12-18 06:18:35 +01:00
return "no" ;
}
2013-03-24 01:18:44 +01:00
} ;
2011-12-18 06:18:35 +01:00
2019-03-10 01:46:55 +01:00
exports . sofficeAvailable = function ( ) {
if ( exports . soffice != null ) {
2015-12-18 04:54:04 +01:00
return os . type ( ) . indexOf ( "Windows" ) != - 1 ? "withoutPDF" : "yes" ;
} else {
return "no" ;
}
} ;
2019-03-10 01:46:55 +01:00
exports . exportAvailable = function ( ) {
2015-12-18 04:54:04 +01:00
var abiword = exports . abiwordAvailable ( ) ;
var soffice = exports . sofficeAvailable ( ) ;
2019-03-10 01:46:55 +01:00
if ( abiword == "no" && soffice == "no" ) {
2015-12-18 04:54:04 +01:00
return "no" ;
} else if ( ( abiword == "withoutPDF" && soffice == "no" ) || ( abiword == "no" && soffice == "withoutPDF" ) ) {
return "withoutPDF" ;
} else {
return "yes" ;
}
} ;
2015-02-11 18:59:05 +01:00
// Provide git version if available
exports . getGitCommit = function ( ) {
var version = "" ;
2019-03-10 01:46:55 +01:00
try {
2015-02-11 18:59:05 +01:00
var rootPath = path . resolve ( npm . dir , '..' ) ;
2015-10-07 15:43:29 +02:00
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" ) ) ;
2015-02-11 18:59:05 +01:00
version = fs . readFileSync ( refPath , "utf-8" ) ;
version = version . substring ( 0 , 7 ) ;
2019-03-10 01:46:55 +01:00
} catch ( e ) {
2015-02-11 18:59:05 +01:00
console . warn ( "Can't get git version for server header\n" + e . message )
}
return version ;
}
2015-04-11 00:13:04 +02:00
// Return etherpad version from package.json
exports . getEpVersion = function ( ) {
return require ( 'ep_etherpad-lite/package.json' ) . version ;
}
2019-03-09 10:06:51 +01:00
/ * *
* 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 ` ) ;
}
}
}
2019-03-21 21:32:39 +01:00
/ *
* 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 ;
}
2019-03-09 23:01:21 +01:00
/ * *
* Takes a javascript object containing Etherpad ' s configuration , and returns
2019-03-21 22:18:59 +01:00
* another object , in which all the string properties whose value is of the form
2019-03-21 01:37:19 +01:00
* "${ENV_VAR}" or "${ENV_VAR:default_value}" got their value replaced with the
* contents of the given environment variable , or with a default value .
2019-03-09 23:01:21 +01:00
*
2019-03-21 22:18:59 +01:00
* 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 :
2019-03-09 23:01:21 +01:00
*
* - 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 ) .
*
2019-03-21 22:18:59 +01:00
* 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 |
2019-03-21 01:37:19 +01:00
* | "${ENV_VAR:some_default}" | "some_string" | "some_string" |
* | "${ENV_VAR:some_default}" | undefined | "some_default" |
2019-03-21 22:18:59 +01:00
* + -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- +
*
* 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 .
2019-03-09 23:01:21 +01:00
*
* 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 . :
2019-03-21 01:37:19 +01:00
* "${ENV_VAR}" or "${ENV_VAR:default_value}" )
2019-03-09 23:01:21 +01:00
* /
2019-03-21 01:37:19 +01:00
// MUXATOR 2019-03-21: we could use named capture groups here once we migrate to nodejs v10
const match = value . match ( /^\$\{([^:]*)(:(.*))?\}$/ ) ;
2019-03-09 23:01:21 +01:00
if ( match === null ) {
// no match: use the value literally, without any substitution
return value ;
}
2019-03-21 01:37:19 +01:00
/ *
* We found the name of an environment variable . Let ' s read its actual value
* and its default value , if given
* /
2019-03-09 23:01:21 +01:00
const envVarName = match [ 1 ] ;
const envVarValue = process . env [ envVarName ] ;
2019-03-21 01:37:19 +01:00
const defaultValue = match [ 3 ] ;
2019-03-09 23:01:21 +01:00
2019-03-21 01:37:19 +01:00
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. ` ) ;
2019-03-09 23:01:21 +01:00
/ *
* We have to return null , because if we just returned undefined , the
* configuration item "key" would be stripped from the returned object .
* /
return null ;
}
2019-03-21 01:37:19 +01:00
if ( ( envVarValue === undefined ) && ( defaultValue !== undefined ) ) {
console . debug ( ` Environment variable " ${ envVarName } " not found for configuration key " ${ key } ". Falling back to default value. ` ) ;
return coerceValue ( defaultValue ) ;
}
2019-03-09 23:01:21 +01:00
// 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 .
* /
2019-03-21 21:32:39 +01:00
console . debug ( ` Configuration key " ${ key } " will be read from environment variable " ${ envVarName } " ` ) ;
2019-03-09 23:01:21 +01:00
2019-03-21 21:32:39 +01:00
return coerceValue ( envVarValue ) ;
2019-03-09 23:01:21 +01:00
} ) ;
const newSettings = JSON . parse ( stringifiedAndReplaced ) ;
return newSettings ;
}
2019-03-10 00:36:53 +01:00
/ * *
* - reads the JSON configuration file settingsFilename from disk
* - strips the comments
2019-03-09 23:01:21 +01:00
* - replaces environment variables calling lookupEnvironmentVariables ( )
2019-03-10 00:36:53 +01:00
* - returns a parsed Javascript object
*
* The isSettings variable only controls the error logging .
* /
function parseSettings ( settingsFilename , isSettings ) {
let settingsStr = "" ;
2019-03-10 01:46:55 +01:00
2019-03-10 00:36:53 +01:00
let settingsType , notFoundMessage , notFoundFunction ;
2015-12-02 12:54:37 +01:00
2019-03-10 00:36:53 +01:00
if ( isSettings ) {
settingsType = "settings" ;
notFoundMessage = "Continuing using defaults!" ;
notFoundFunction = console . warn ;
} else {
settingsType = "credentials" ;
notFoundMessage = "Ignoring." ;
notFoundFunction = console . info ;
2012-07-08 18:59:46 +02:00
}
2011-05-14 18:22:25 +02:00
2019-03-10 01:46:55 +01:00
try {
2019-03-10 00:36:53 +01:00
//read the settings file
settingsStr = fs . readFileSync ( settingsFilename ) . toString ( ) ;
2019-03-10 01:46:55 +01:00
} catch ( e ) {
2019-03-10 00:36:53 +01:00
notFoundFunction ( ` No ${ settingsType } file found in ${ settingsFilename } . ${ notFoundMessage } ` ) ;
2015-12-02 12:54:37 +01:00
2019-03-10 00:36:53 +01:00
// or maybe undefined!
return null ;
2011-05-14 18:22:25 +02:00
}
2019-03-10 00:26:36 +01:00
try {
2019-03-10 00:36:53 +01:00
settingsStr = jsonminify ( settingsStr ) . replace ( ",]" , "]" ) . replace ( ",}" , "}" ) ;
const settings = JSON . parse ( settingsStr ) ;
console . info ( ` ${ settingsType } loaded from: ${ settingsFilename } ` ) ;
2019-03-09 23:01:21 +01:00
const replacedSettings = lookupEnvironmentVariables ( settings ) ;
return replacedSettings ;
2019-03-10 00:26:36 +01:00
} catch ( e ) {
2019-03-10 00:36:53 +01:00
console . error ( ` There was an error processing your ${ settingsType } file from ${ settingsFilename } : ${ e . message } ` ) ;
2019-03-10 00:26:36 +01:00
process . exit ( 1 ) ;
2015-12-02 12:54:37 +01:00
}
2019-03-10 00:36:53 +01:00
}
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 ) ;
2015-12-02 12:54:37 +01:00
2019-03-09 10:06:51 +01:00
storeSettings ( settings ) ;
storeSettings ( credentials ) ;
2015-12-02 12:54:37 +01:00
2013-01-13 12:20:49 +01:00
log4js . configure ( exports . logconfig ) ; //Configure the logging appenders
log4js . setGlobalLogLevel ( exports . loglevel ) ; //set loglevel
2014-11-04 19:32:26 +01:00
process . env [ 'DEBUG' ] = 'socket.io:' + exports . loglevel ; // Used by SocketIO for Debug
2013-01-13 12:20:49 +01:00
log4js . replaceConsole ( ) ;
2012-11-06 17:35:05 +01:00
2018-08-19 03:36:18 +02:00
if ( ! exports . skinName ) {
2018-08-27 01:56:33 +02:00
console . warn ( ` No "skinName" parameter found. Please check out settings.json.template and update your settings.json. Falling back to the default "no-skin". ` ) ;
2018-08-19 03:36:18 +02:00
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 } ` ) ;
}
2019-10-19 00:54:56 +02:00
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 ( user , username ) {
if ( ( user . hasOwnProperty ( "password" ) ) || user . 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 ;
}
2019-03-10 01:46:55 +01:00
if ( exports . abiword ) {
2015-01-04 15:47:08 +01:00
// Check abiword actually exists
2019-03-10 01:46:55 +01:00
if ( exports . abiword != null ) {
2015-01-04 15:47:08 +01:00
fs . exists ( exports . abiword , function ( exists ) {
if ( ! exists ) {
2019-03-09 08:59:39 +01:00
var abiwordError = "Abiword does not exist at this path, check your settings file." ;
2019-03-10 01:46:55 +01:00
if ( ! exports . suppressErrorsInPadText ) {
2015-04-06 01:13:38 +02:00
exports . defaultPadText = exports . defaultPadText + "\nError: " + abiwordError + suppressDisableMsg ;
}
2019-03-09 08:59:39 +01:00
console . error ( abiwordError + ` File location: ${ exports . abiword } ` ) ;
2015-01-04 15:47:08 +01:00
exports . abiword = null ;
}
} ) ;
}
}
2019-03-10 01:46:55 +01:00
if ( exports . soffice ) {
fs . exists ( exports . soffice , function ( exists ) {
if ( ! exists ) {
2019-03-09 08:59:39 +01:00
var sofficeError = "soffice (libreoffice) does not exist at this path, check your settings file." ;
2015-12-18 04:54:04 +01:00
2019-03-10 01:46:55 +01:00
if ( ! exports . suppressErrorsInPadText ) {
2015-12-18 04:54:04 +01:00
exports . defaultPadText = exports . defaultPadText + "\nError: " + sofficeError + suppressDisableMsg ;
}
2019-03-09 08:59:39 +01:00
console . error ( sofficeError + ` File location: ${ exports . soffice } ` ) ;
2015-12-18 04:54:04 +01:00
exports . soffice = null ;
}
} ) ;
}
2015-04-11 18:45:14 +02:00
if ( ! exports . sessionKey ) {
2018-08-22 01:56:40 +02:00
var sessionkeyFilename = absolutePaths . makeAbsolute ( argv . sessionkey || "./SESSIONKEY.txt" ) ;
2015-04-11 18:45:14 +02:00
try {
2017-07-31 14:43:04 +02:00
exports . sessionKey = fs . readFileSync ( sessionkeyFilename , "utf8" ) ;
2018-08-21 00:05:15 +02:00
console . info ( ` Session key loaded from: ${ sessionkeyFilename } ` ) ;
2015-04-11 18:45:14 +02:00
} catch ( e ) {
2018-08-21 00:05:15 +02:00
console . info ( ` Session key file " ${ sessionkeyFilename } " not found. Creating with random contents. ` ) ;
2015-04-11 18:45:14 +02:00
exports . sessionKey = randomString ( 32 ) ;
2017-07-31 14:43:04 +02:00
fs . writeFileSync ( sessionkeyFilename , exports . sessionKey , "utf8" ) ;
2015-04-06 01:13:38 +02:00
}
2015-04-11 18:45:14 +02:00
} 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." ) ;
2013-02-13 22:51:09 +01:00
}
2019-03-10 01:46:55 +01:00
if ( exports . dbType === "dirty" ) {
2015-04-06 01:13:38 +02:00
var dirtyWarning = "DirtyDB is used. This is fine for testing but not recommended for production." ;
2019-03-10 01:46:55 +01:00
if ( ! exports . suppressErrorsInPadText ) {
2015-04-06 01:13:38 +02:00
exports . defaultPadText = exports . defaultPadText + "\nWarning: " + dirtyWarning + suppressDisableMsg ;
}
2018-08-22 01:16:33 +02:00
exports . dbSettings . filename = absolutePaths . makeAbsolute ( exports . dbSettings . filename ) ;
console . warn ( dirtyWarning + ` File location: ${ exports . dbSettings . filename } ` ) ;
2011-05-14 18:22:25 +02:00
}
2013-03-24 01:18:44 +01:00
} ;
2012-04-20 17:03:37 +02:00
2012-11-06 17:35:05 +01:00
// initially load settings
exports . reloadSettings ( ) ;