diff --git a/Dockerfile b/Dockerfile index 8759404..7991cf8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -ARG product_version=7.2.0 -ARG build_number=204 +ARG product_version=7.2.1 +ARG build_number=34 ARG oo_root='/var/www/onlyoffice/documentserver' ## Setup @@ -26,19 +26,24 @@ ARG tag=v${PRODUCT_VERSION}.${BUILD_NUMBER} RUN git clone --quiet --branch $tag --depth 1 https://github.com/ONLYOFFICE/build_tools.git /build/build_tools RUN git clone --quiet --branch $tag --depth 1 https://github.com/ONLYOFFICE/server.git /build/server -COPY server.patch /build/server.patch -RUN cd /build/server && git apply /build/server.patch - -# Clone old version of sdk and webapp to get an old version of the mobile editor - -ARG tag=v6.3.1.79 # Working mobile editor -RUN git clone --quiet --branch $tag --depth 1 https://github.com/ONLYOFFICE/sdkjs.git /build/sdkjs -RUN git clone --quiet --branch $tag --depth 1 https://github.com/ONLYOFFICE/web-apps.git /build/web-apps -COPY web-apps.patch /build/ -RUN cd /build/web-apps && git apply /build/web-apps.patch +# Working mobile editor +RUN git clone --quiet --depth 1 https://github.com/ONLYOFFICE/sdkjs.git /build/sdkjs +RUN git clone --quiet --depth 1 https://github.com/ONLYOFFICE/web-apps.git /build/web-apps ## Build -FROM clone-stage as build-stage +FROM clone-stage as path-stage + +# patch +COPY web-apps.patch /build/web-apps.patch +RUN cd /build/web-apps && git apply /build/web-apps.patch +COPY convertermaster.js /build/server/FileConverter/sources/convertermaster.js +COPY license.js /build/server/Common/sources/license.js +COPY Makefile /build/server/Makefile +COPY server.js /build/server/DocService/sources/server.js +COPY constants.js /build/server/Common/srouces/constants.js + +## Build +FROM path-stage as build-stage # build server with license checks patched WORKDIR /build/server diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..23f7e2e --- /dev/null +++ b/Makefile @@ -0,0 +1,188 @@ +GRUNT = grunt +GRUNT_FLAGS = --no-color -v + +GRUNT_FILES = Gruntfile.js.out + +PRODUCT_VERSION ?= 0.0.0 +BUILD_NUMBER ?= 0 + +PUBLISHER_NAME ?= Ascensio System SIA +PUBLISHER_URL ?= https://www.onlyoffice.com/ + +GRUNT_ENV += PRODUCT_VERSION=$(PRODUCT_VERSION) +GRUNT_ENV += BUILD_NUMBER=$(BUILD_NUMBER) +GRUNT_ENV += PUBLISHER_NAME="$(PUBLISHER_NAME)" +GRUNT_ENV += PUBLISHER_URL="$(PUBLISHER_URL)" + +BRANDING_DIR ?= ./branding + +DOCUMENT_ROOT ?= /var/www/onlyoffice/documentserver + +ifeq ($(OS),Windows_NT) + PLATFORM := win + EXEC_EXT := .exe + SHARED_EXT := .dll + ifeq ($(PROCESSOR_ARCHITECTURE),AMD64) + ARCHITECTURE := 64 + endif + ifeq ($(PROCESSOR_ARCHITECTURE),x86) + ARCHITECTURE := 32 + endif +else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S),Linux) + PLATFORM := linux + SHARED_EXT := .so* + LIB_PREFIX := lib + endif + UNAME_M := $(shell uname -m) + ifeq ($(UNAME_M),x86_64) + ARCHITECTURE := 64 + endif + ifneq ($(filter %86,$(UNAME_M)),) + ARCHITECTURE := 32 + endif +endif + +TARGET := $(PLATFORM)_$(ARCHITECTURE) + +OUTPUT = ../build_tools/out/$(TARGET)/onlyoffice/documentserver/server + +SPELLCHECKER_DICTIONARIES := $(OUTPUT)/../dictionaries +SPELLCHECKER_DICTIONARY_FILES += ../dictionaries/*_* + +SCHEMA_DIR = schema +SCHEMA_FILES = $(SCHEMA_DIR)/** +SCHEMA = $(OUTPUT)/$(SCHEMA_DIR)/ + +TOOLS_DIR = tools +TOOLS_FILES += ../core/build/bin/$(TARGET)/allfontsgen$(EXEC_EXT) +TOOLS_FILES += ../core/build/bin/$(TARGET)/allthemesgen$(EXEC_EXT) +TOOLS = $(OUTPUT)/$(TOOLS_DIR) + +LICENSE_FILES = LICENSE.txt 3rd-Party.txt license/ +LICENSE = $(addsuffix $(OUTPUT)/, LICENSE_FILES) + +LICENSE_JS := $(OUTPUT)/Common/sources/license.js +COMMON_DEFINES_JS := $(OUTPUT)/Common/sources/commondefines.js + +WELCOME_DIR = welcome +WELCOME_FILES = $(BRANDING_DIR)/$(WELCOME_DIR)/** +WELCOME = $(OUTPUT)/$(WELCOME_DIR)/ + +INFO_DIR = info +INFO_FILES = $(BRANDING_DIR)/$(INFO_DIR)/** +INFO = $(OUTPUT)/$(INFO_DIR)/ + +CORE_FONTS_DIR = core-fonts +CORE_FONTS_FILES = ../$(CORE_FONTS_DIR)/** +CORE_FONTS = $(OUTPUT)/../$(CORE_FONTS_DIR)/ + +DOCUMENT_TEMPLATES_DIR = document-templates +DOCUMENT_TEMPLATES_FILES = ../$(DOCUMENT_TEMPLATES_DIR)/** +DOCUMENT_TEMPLATES = $(OUTPUT)/../$(DOCUMENT_TEMPLATES_DIR)/ + +DEBUG = $(BRANDING_DIR)/debug.js + +.PHONY: all clean install uninstall build-date + +.NOTPARALLEL: +all: $(SCHEMA) $(LICENSE) $(WELCOME) $(INFO) build-date + +build-date: $(GRUNT_FILES) + sed "s|\(const buildVersion = \).*|\1'${PRODUCT_VERSION}';|" -i $(COMMON_DEFINES_JS) + sed "s|\(const buildNumber = \).*|\1${BUILD_NUMBER};|" -i $(COMMON_DEFINES_JS) + sed "s|\(const buildDate = \).*|\1'$$(date +%F)';|" -i $(LICENSE_JS) + test -e $(DEBUG) && \ + cp $(DEBUG) $(OUTPUT)/Common/sources || true + +$(SPELLCHECKER_DICTIONARIES): $(GRUNT_FILES) + mkdir -p $(SPELLCHECKER_DICTIONARIES) && \ + cp -r -t $(SPELLCHECKER_DICTIONARIES) $(SPELLCHECKER_DICTIONARY_FILES) + +$(SCHEMA): + mkdir -p $(SCHEMA) && \ + cp -r -t $(SCHEMA) $(SCHEMA_FILES) + +$(TOOLS): + mkdir -p $(TOOLS) && \ + cp -r -t $(TOOLS) $(TOOLS_FILES) + +$(LICENSE): + mkdir -p $(OUTPUT) && \ + cp -r -t $(OUTPUT) $(LICENSE_FILES) + +$(GRUNT_FILES): + cd $(@D) && \ + npm install && \ + $(GRUNT_ENV) $(GRUNT) $(GRUNT_FLAGS) + mkdir -p $(OUTPUT) + cp -r -t $(OUTPUT) ./build/server/* + echo "Done" > $@ + +$(WELCOME): + mkdir -p $(WELCOME) && \ + cp -r -t $(WELCOME) $(WELCOME_FILES) + +$(INFO): + mkdir -p $(INFO) && \ + cp -r -t $(INFO) $(INFO_FILES) + +$(CORE_FONTS): + mkdir -p $(CORE_FONTS) && \ + cp -r -t $(CORE_FONTS) $(CORE_FONTS_FILES) + +$(DOCUMENT_TEMPLATES): + mkdir -p $(DOCUMENT_TEMPLATES) && \ + cp -r -t $(DOCUMENT_TEMPLATES) $(DOCUMENT_TEMPLATES_FILES) + +clean: + rm -rf $(GRUNT_FILES) + +install: + mkdir -pv ${DESTDIR}/var/www/onlyoffice + if ! id -u onlyoffice > /dev/null 2>&1; then useradd -m -d /var/www/onlyoffice -r -U onlyoffice; fi + + mkdir -p ${DESTDIR}${DOCUMENT_ROOT}/fonts + mkdir -p ${DESTDIR}/var/log/onlyoffice/documentserver + mkdir -p ${DESTDIR}/var/lib/onlyoffice/documentserver/App_Data + + cp -fr -t ${DESTDIR}${DOCUMENT_ROOT} build/* ../web-apps/deploy/* + mkdir -p ${DESTDIR}/etc/onlyoffice/documentserver + mv ${DESTDIR}${DOCUMENT_ROOT}/server/Common/config/* ${DESTDIR}/etc/onlyoffice/documentserver + + chown onlyoffice:onlyoffice -R ${DESTDIR}/var/www/onlyoffice + chown onlyoffice:onlyoffice -R ${DESTDIR}/var/log/onlyoffice + chown onlyoffice:onlyoffice -R ${DESTDIR}/var/lib/onlyoffice + + # Make symlinks for shared libs + find \ + ${DESTDIR}${DOCUMENT_ROOT}/server/FileConverter/bin \ + -maxdepth 1 \ + -name *$(SHARED_EXT) \ + -exec sh -c 'ln -sf {} ${DESTDIR}/lib/$$(basename {})' \; + + sudo -u onlyoffice "${DESTDIR}${DOCUMENT_ROOT}/server/tools/allfontsgen"\ + --input="${DESTDIR}${DOCUMENT_ROOT}/core-fonts"\ + --allfonts-web="${DESTDIR}${DOCUMENT_ROOT}/sdkjs/common/AllFonts.js"\ + --allfonts="${DESTDIR}${DOCUMENT_ROOT}/server/FileConverter/bin/AllFonts.js"\ + --images="${DESTDIR}${DOCUMENT_ROOT}/sdkjs/common/Images"\ + --selection="${DESTDIR}${DOCUMENT_ROOT}/server/FileConverter/bin/font_selection.bin"\ + --output-web="${DESTDIR}${DOCUMENT_ROOT}/fonts"\ + --use-system="true" + + sudo -u onlyoffice "${DESTDIR}${DOCUMENT_ROOT}/server/tools/allthemesgen"\ + --converter-dir="${DESTDIR}${DOCUMENT_ROOT}/server/FileConverter/bin"\ + --src="${DESTDIR}${DOCUMENT_ROOT}/sdkjs/slide/themes"\ + --output="${DESTDIR}${DOCUMENT_ROOT}/sdkjs/common/Images" + +uninstall: + userdel onlyoffice + + # Unlink installed shared libs + find /lib -type l | while IFS= read -r lnk; do if (readlink "$$lnk" | grep -q '^${DOCUMENT_ROOT}/server/FileConverter/bin/'); then rm "$$lnk"; fi; done + + rm -rf /var/www/onlyoffice/documentserver + rm -rf /var/log/onlyoffice/documentserver + rm -rf /var/lib/onlyoffice/documentserver + rm -rf /etc/onlyoffice/documentserver diff --git a/constants.js b/constants.js new file mode 100644 index 0000000..3116fbb --- /dev/null +++ b/constants.js @@ -0,0 +1,304 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2019 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +'use strict'; + +exports.DOC_ID_PATTERN = '0-9-.a-zA-Z_='; +exports.DOC_ID_REGEX = new RegExp("^[" + exports.DOC_ID_PATTERN + "]*$", 'i'); +exports.DOC_ID_REPLACE_REGEX = new RegExp("[^" + exports.DOC_ID_PATTERN + "]", 'g'); +exports.DOC_ID_SOCKET_PATTERN = new RegExp("^/doc/([" + exports.DOC_ID_PATTERN + "]*)/c.+", 'i'); +exports.DOC_ID_MAX_LENGTH = 240; +exports.USER_ID_MAX_LENGTH = 240;//255-240=15 symbols to make user id unique +exports.USER_NAME_MAX_LENGTH = 255; +exports.PASSWORD_MAX_LENGTH = 255;//set password limit for DoS protection with long password +exports.EXTENTION_REGEX = /^[a-zA-Z0-9]*$/; +exports.CHAR_DELIMITER = String.fromCharCode(5); +exports.OUTPUT_NAME = 'output'; +exports.ONLY_OFFICE_URL_PARAM = 'ooname'; +exports.DISPLAY_PREFIX = 'display'; +exports.CHANGES_NAME = 'changes'; +exports.VIEWER_ONLY = /^(?:(pdf|djvu|xps|oxps))$/; +exports.DEFAULT_DOC_ID = 'docId'; +exports.DEFAULT_USER_ID = 'userId'; + +exports.RIGHTS = { + None : 0, + Edit : 1, + Review : 2, + Comment : 3, + View : 4 +}; + +exports.LICENSE_MODE = { + None: 0, + Trial: 1, + Developer: 2, + Limited: 4 +}; + +exports.LICENSE_RESULT = { + Error : 1, + Expired : 2, + Success : 3, + UnknownUser : 4, + Connections : 5, + ExpiredTrial : 6, + SuccessLimit : 7, + UsersCount : 8, + ConnectionsOS : 9, + UsersCountOS : 10, + ExpiredLimited: 11, + ConnectionsLiveOS: 12, + ConnectionsLive: 13, + UsersViewCount: 14, + UsersViewCountOS: 15 +}; + +exports.LICENSE_CONNECTIONS = 99999; +exports.LICENSE_EXPIRE_USERS_ONE_DAY = 24 * 60 * 60; // day in seconds + +exports.AVS_OFFICESTUDIO_FILE_UNKNOWN = 0x0000; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT = 0x0040; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCX = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0001; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOC = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0002; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_ODT = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0003; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_RTF = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0004; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_TXT = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0005; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_HTML = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0006; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_MHT = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0007; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_EPUB = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0008; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_FB2 = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0009; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_MOBI = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x000a; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCM = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x000b; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOTX = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x000c; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOTM = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x000d; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_ODT_FLAT = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x000e; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_OTT = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x000f; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOC_FLAT = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0010; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCX_FLAT = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0011; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_HTML_IN_CONTAINER = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0012; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCX_PACKAGE = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0014; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_OFORM = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0015; +exports.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCXF = exports.AVS_OFFICESTUDIO_FILE_DOCUMENT + 0x0016; + +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION = 0x0080; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_PPTX = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x0001; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_PPT = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x0002; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_ODP = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x0003; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_PPSX = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x0004; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_PPTM = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x0005; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_PPSM = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x0006; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_POTX = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x0007; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_POTM = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x0008; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_ODP_FLAT = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x0009; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_OTP = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x000a; +exports.AVS_OFFICESTUDIO_FILE_PRESENTATION_PPTX_PACKAGE = exports.AVS_OFFICESTUDIO_FILE_PRESENTATION + 0x000b; + +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET = 0x0100; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSX = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0001; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLS = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0002; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_ODS = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0003; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_CSV = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0004; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSM = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0005; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLTX = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0006; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLTM = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0007; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSB = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0008; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_ODS_FLAT = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0009; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_OTS = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x000a; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSX_FLAT = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x000b; +exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSX_PACKAGE = exports.AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x000c; + +exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM = 0x0200; +exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF = exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0001; +exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_SWF = exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0002; +exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_DJVU = exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0003; +exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_XPS = exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0004; +exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_SVG = exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0005; +exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_HTMLR = exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0006; +exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_HTMLR_MENU = exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0007; +exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_HTMLR_CANVAS = exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0008; +exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDFA = exports.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0009; +exports.AVS_OFFICESTUDIO_FILE_IMAGE = 0x0400; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_JPG = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x0001; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_TIFF = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x0002; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_TGA = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x0003; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_GIF = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x0004; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_PNG = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x0005; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_EMF = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x0006; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_WMF = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x0007; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_BMP = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x0008; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_CR2 = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x0009; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_PCX = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x000a; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_RAS = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x000b; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_PSD = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x000c; +exports.AVS_OFFICESTUDIO_FILE_IMAGE_ICO = exports.AVS_OFFICESTUDIO_FILE_IMAGE + 0x000d; +exports.AVS_OFFICESTUDIO_FILE_OTHER = 0x0800; +exports.AVS_OFFICESTUDIO_FILE_OTHER_EXTRACT_IMAGE = exports.AVS_OFFICESTUDIO_FILE_OTHER + 0x0001; +exports.AVS_OFFICESTUDIO_FILE_OTHER_MS_OFFCRYPTO = exports.AVS_OFFICESTUDIO_FILE_OTHER + 0x0002; +exports.AVS_OFFICESTUDIO_FILE_OTHER_HTMLZIP = exports.AVS_OFFICESTUDIO_FILE_OTHER + 0x0003; +exports.AVS_OFFICESTUDIO_FILE_OTHER_OLD_DOCUMENT = exports.AVS_OFFICESTUDIO_FILE_OTHER + 0x0004; +exports.AVS_OFFICESTUDIO_FILE_OTHER_OLD_PRESENTATION = exports.AVS_OFFICESTUDIO_FILE_OTHER + 0x0005; +exports.AVS_OFFICESTUDIO_FILE_OTHER_OLD_DRAWING = exports.AVS_OFFICESTUDIO_FILE_OTHER + 0x0006; +exports.AVS_OFFICESTUDIO_FILE_OTHER_OOXML = exports.AVS_OFFICESTUDIO_FILE_OTHER + 0x0007; +exports.AVS_OFFICESTUDIO_FILE_OTHER_JSON = exports.AVS_OFFICESTUDIO_FILE_OTHER + 0x0008; // Для mail-merge +exports.AVS_OFFICESTUDIO_FILE_OTHER_ODF = exports.AVS_OFFICESTUDIO_FILE_OTHER + 0x000a; +exports.AVS_OFFICESTUDIO_FILE_OTHER_MS_MITCRYPTO = exports.AVS_OFFICESTUDIO_FILE_OTHER + 0x000b; + +exports.AVS_OFFICESTUDIO_FILE_TEAMLAB = 0x1000; +exports.AVS_OFFICESTUDIO_FILE_TEAMLAB_DOCY = exports.AVS_OFFICESTUDIO_FILE_TEAMLAB + 0x0001; +exports.AVS_OFFICESTUDIO_FILE_TEAMLAB_XLSY = exports.AVS_OFFICESTUDIO_FILE_TEAMLAB + 0x0002; +exports.AVS_OFFICESTUDIO_FILE_TEAMLAB_PPTY = exports.AVS_OFFICESTUDIO_FILE_TEAMLAB + 0x0003; +exports.AVS_OFFICESTUDIO_FILE_CANVAS = 0x2000; +exports.AVS_OFFICESTUDIO_FILE_CANVAS_WORD = exports.AVS_OFFICESTUDIO_FILE_CANVAS + 0x0001; +exports.AVS_OFFICESTUDIO_FILE_CANVAS_SPREADSHEET = exports.AVS_OFFICESTUDIO_FILE_CANVAS + 0x0002; +exports.AVS_OFFICESTUDIO_FILE_CANVAS_PRESENTATION = exports.AVS_OFFICESTUDIO_FILE_CANVAS + 0x0003; + +exports.NO_ERROR = 0; +exports.UNKNOWN = -1; +exports.READ_REQUEST_STREAM = -3; +exports.WEB_REQUEST = -4; +exports.CHANGE_DOC_INFO = -5; +exports.TASK_QUEUE = -20; +exports.TASK_RESULT = -40; +exports.STORAGE = -60; +exports.STORAGE_FILE_NO_FOUND = -61; +exports.STORAGE_READ = -62; +exports.STORAGE_WRITE = -63; +exports.STORAGE_REMOVE_DIR = -64; +exports.STORAGE_CREATE_DIR = -65; +exports.STORAGE_GET_INFO = -66; +exports.CONVERT = -80; +exports.CONVERT_DOWNLOAD = -81; +exports.CONVERT_UNKNOWN_FORMAT = -82; +exports.CONVERT_TIMEOUT = -83; +exports.CONVERT_READ_FILE = -84; +exports.CONVERT_DRM_UNSUPPORTED = -85; +exports.CONVERT_CORRUPTED = -86; +exports.CONVERT_LIBREOFFICE = -87; +exports.CONVERT_PARAMS = -88; +exports.CONVERT_NEED_PARAMS = -89; +exports.CONVERT_DRM = -90; +exports.CONVERT_PASSWORD = -91; +exports.CONVERT_ICU = -92; +exports.CONVERT_LIMITS = -93; +exports.CONVERT_DEAD_LETTER = -99; +exports.UPLOAD = -100; +exports.UPLOAD_CONTENT_LENGTH = -101; +exports.UPLOAD_EXTENSION = -102; +exports.UPLOAD_COUNT_FILES = -103; +exports.UPLOAD_URL = -104; +exports.VKEY = -120; +exports.VKEY_ENCRYPT = -121; +exports.VKEY_KEY_EXPIRE = -122; +exports.VKEY_USER_COUNT_EXCEED = -123; +exports.VKEY_TIME_EXPIRE = -124; +exports.VKEY_TIME_INCORRECT = -125; +exports.EDITOR_CHANGES = -160; +exports.PASSWORD = -180; + +exports.QUEUE_PRIORITY_VERY_LOW = 0; +exports.QUEUE_PRIORITY_LOW = 1; +exports.QUEUE_PRIORITY_NORMAL = 2; +exports.QUEUE_PRIORITY_HIGH = 3; +exports.QUEUE_PRIORITY_VERY_HIGH = 4; + +exports.EDITOR_TYPE_WORD = 0; +exports.EDITOR_TYPE_SPREADSHEET = 1; +exports.EDITOR_TYPE_PRESENTATION = 2; +exports.EDITOR_TYPE_CONVERTATION = 3; + +exports.PACKAGE_TYPE_OS = 0; +exports.PACKAGE_TYPE_I = 1; +exports.PACKAGE_TYPE_D = 2; + +exports.REDIS_KEY_PUBSUB = 'pubsub'; +exports.REDIS_KEY_SAVE_LOCK = 'savelock:'; +exports.REDIS_KEY_PRESENCE_HASH = 'presence:hash:'; +exports.REDIS_KEY_PRESENCE_SET = 'presence:set:'; +exports.REDIS_KEY_PRESENCE_UNIQUE_USERS = 'presence:unique:users'; +exports.REDIS_KEY_PRESENCE_UNIQUE_USERS_HASH = 'presence:unique:users:hash'; +exports.REDIS_KEY_PRESENCE_MONTH_UNIQUE_USERS_HASH = 'presence:unique:users:month'; +exports.REDIS_KEY_PRESENCE_UNIQUE_USERS_VIEW = 'presence:unique:usersview'; +exports.REDIS_KEY_PRESENCE_UNIQUE_USERS_VIEW_HASH = 'presence:unique:usersview:hash'; +exports.REDIS_KEY_PRESENCE_MONTH_UNIQUE_USERS_VIEW_HASH = 'presence:unique:usersview:month'; +exports.REDIS_KEY_LOCKS = 'locks:'; +exports.REDIS_KEY_LOCK_DOCUMENT = 'lockdocument:'; +exports.REDIS_KEY_MESSAGE = 'message:'; +exports.REDIS_KEY_DOCUMENTS = 'documents'; +exports.REDIS_KEY_LAST_SAVE = 'lastsave:'; +exports.REDIS_KEY_FORCE_SAVE = 'forcesave:'; +exports.REDIS_KEY_FORCE_SAVE_TIMER = 'forcesavetimer'; +exports.REDIS_KEY_FORCE_SAVE_TIMER_LOCK = 'forcesavetimerlock:'; +exports.REDIS_KEY_SAVED = 'saved:'; +exports.REDIS_KEY_SHUTDOWN = 'shutdown'; +exports.REDIS_KEY_COLLECT_LOST = 'collectlost'; +exports.REDIS_KEY_LICENSE = 'license'; +exports.REDIS_KEY_LICENSE_T = 'licenseT'; +exports.REDIS_KEY_EDITOR_CONNECTIONS = 'editorconnections'; +exports.REDIS_KEY_SHARD_CONNECTIONS_EDIT_ZSET = 'shardconnections:edit:zset'; +exports.REDIS_KEY_SHARD_CONNECTIONS_EDIT_HASH = 'shardconnections:edit:hash'; +exports.REDIS_KEY_SHARD_CONNECTIONS_LIVE_VIEW_ZSET = 'shardconnections:liveview:zset'; +exports.REDIS_KEY_SHARD_CONNECTIONS_LIVE_VIEW_HASH = 'shardconnections:liveview:hash'; +exports.REDIS_KEY_SHARD_CONNECTIONS_VIEW_ZSET = 'shardconnections:view:zset'; +exports.REDIS_KEY_SHARD_CONNECTIONS_VIEW_HASH = 'shardconnections:view:hash'; + +exports.SHUTDOWN_CODE = 4001; +exports.SHUTDOWN_REASON = 'server shutdown'; +exports.SESSION_IDLE_CODE = 4002; +exports.SESSION_IDLE_REASON = 'idle session expires'; +exports.SESSION_ABSOLUTE_CODE = 4003; +exports.SESSION_ABSOLUTE_REASON = 'absolute session expires'; +exports.ACCESS_DENIED_CODE = 4004; +exports.ACCESS_DENIED_REASON = 'access deny'; +exports.JWT_EXPIRED_CODE = 4005; +exports.JWT_EXPIRED_REASON = 'token:'; +exports.JWT_ERROR_CODE = 4006; +exports.JWT_ERROR_REASON = 'token:'; +exports.DROP_CODE = 4007; +exports.DROP_REASON = 'drop'; +exports.UPDATE_VERSION_CODE = 4008; +exports.UPDATE_VERSION = 'update version'; +exports.NO_CACHE_CODE = 4009; +exports.NO_CACHE = 'no cache'; +exports.RESTORE_CODE = 4010; +exports.RESTORE = 'no cache'; + +exports.CONTENT_DISPOSITION_INLINE = 'inline'; +exports.CONTENT_DISPOSITION_ATTACHMENT = 'attachment'; + +exports.CONN_CLOSED = 3; + +exports.FILE_STATUS_OK = 'ok'; +exports.FILE_STATUS_UPDATE_VERSION = 'updateversion'; + +exports.ACTIVEMQ_QUEUE_PREFIX = 'queue://'; +exports.ACTIVEMQ_TOPIC_PREFIX = 'topic://'; diff --git a/convertermaster.js b/convertermaster.js new file mode 100644 index 0000000..757905e --- /dev/null +++ b/convertermaster.js @@ -0,0 +1,109 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2019 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +'use strict'; + +const cluster = require('cluster'); +const logger = require('./../../Common/sources/logger'); +const operationContext = require('./../../Common/sources/operationContext'); + +if (cluster.isMaster) { + const fs = require('fs'); + const co = require('co'); + const numCPUs = require('os').cpus().length; + const configCommon = require('config'); + const config = configCommon.get('FileConverter.converter'); + const license = require('./../../Common/sources/license'); + const tenantManager = require('./../../Common/sources/tenantManager'); + + const cfgLicenseFile = configCommon.get('license.license_file'); + + const cfgMaxProcessCount = config.get('maxprocesscount'); + var workersCount = 0; + const readLicense = function* () { + workersCount = Math.ceil(numCPUs * cfgMaxProcessCount); + if (!tenantManager.isMultitenantMode()) { + let [licenseInfo] = yield* license.readLicense(cfgLicenseFile); + workersCount = Math.min(licenseInfo.count, workersCount); + } + }; + const updateWorkers = () => { + var i; + const arrKeyWorkers = Object.keys(cluster.workers); + if (arrKeyWorkers.length < workersCount) { + for (i = arrKeyWorkers.length; i < workersCount; ++i) { + const newWorker = cluster.fork(); + operationContext.global.logger.warn('worker %s started.', newWorker.process.pid); + } + } else { + for (i = workersCount; i < arrKeyWorkers.length; ++i) { + const killWorker = cluster.workers[arrKeyWorkers[i]]; + if (killWorker) { + killWorker.kill(); + } + } + } + }; + const updateLicense = () => { + return co(function*() { + try { + yield* readLicense(); + operationContext.global.logger.warn('update cluster with %s workers', workersCount); + updateWorkers(); + } catch (err) { + operationContext.global.logger.error('updateLicense error: %s', err.stack); + } + }); + }; + + cluster.on('exit', (worker, code, signal) => { + operationContext.global.logger.warn('worker %s died (code = %s; signal = %s).', worker.process.pid, code, signal); + updateWorkers(); + }); + + updateLicense(); + + if (!tenantManager.isMultitenantMode()) { + setInterval(updateLicense, 86400000); + } +} else { + const converter = require('./converter'); + converter.run(); +} + +process.on('uncaughtException', (err) => { + operationContext.global.logger.error((new Date).toUTCString() + ' uncaughtException:', err.message); + operationContext.global.logger.error(err.stack); + logger.shutdown(() => { + process.exit(1); + }); +}); diff --git a/license.js b/license.js new file mode 100644 index 0000000..cce68fd --- /dev/null +++ b/license.js @@ -0,0 +1,68 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2019 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +'use strict'; + +const constants = require('./constants'); + +const buildDate = '6/29/2016'; +const oBuildDate = new Date(buildDate); + +exports.readLicense = function*() { + const c_LR = constants.LICENSE_RESULT; + var now = new Date(); + var startDate = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));//first day of current month + return [{ + count: 1, + type: c_LR.Success, + light: true, + packageType: constants.PACKAGE_TYPE_I, + mode: constants.LICENSE_MODE.None, + branding: true, + connections: constants.LICENSE_CONNECTIONS, + connectionsView: constants.LICENSE_CONNECTIONS, + customization: true, + advancedApi: true, + usersCount: constants.LICENSE_CONNECTIONS, + usersViewCount: constants.LICENSE_CONNECTIONS, + usersExpire: constants.LICENSE_EXPIRE_USERS_ONE_DAY, + hasLicense: true, + plugins: true, + buildDate: oBuildDate, + startDate: startDate, + endDate: new Date("2099-01-01T23:59:59.000Z"), + customerId: "", + alias: "community" + }, null]; +}; + +exports.packageType = constants.PACKAGE_TYPE_I; diff --git a/server.js b/server.js new file mode 100644 index 0000000..edfb423 --- /dev/null +++ b/server.js @@ -0,0 +1,362 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2019 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +'use strict'; + +const configCommon = require('config'); +const config = configCommon.get('services.CoAuthoring'); +//process.env.NODE_ENV = config.get('server.mode'); +const logger = require('./../../Common/sources/logger'); +const co = require('co'); +const license = require('./../../Common/sources/license'); +const fs = require('fs'); + +const express = require('express'); +const http = require('http'); +const urlModule = require('url'); +const path = require('path'); +const bodyParser = require("body-parser"); +const multer = require('multer'); +const mime = require('mime'); +const apicache = require('apicache'); +const docsCoServer = require('./DocsCoServer'); +const canvasService = require('./canvasservice'); +const converterService = require('./converterservice'); +const fileUploaderService = require('./fileuploaderservice'); +const wopiClient = require('./wopiClient'); +const constants = require('./../../Common/sources/constants'); +const utils = require('./../../Common/sources/utils'); +const commonDefines = require('./../../Common/sources/commondefines'); +const operationContext = require('./../../Common/sources/operationContext'); +const tenantManager = require('./../../Common/sources/tenantManager'); +const configStorage = configCommon.get('storage'); + +const cfgWopiEnable = configCommon.get('wopi.enable'); +const cfgHtmlTemplate = configCommon.get('wopi.htmlTemplate'); +const cfgTokenEnableBrowser = configCommon.get('services.CoAuthoring.token.enable.browser'); +const cfgTokenEnableRequestInbox = configCommon.get('services.CoAuthoring.token.enable.request.inbox'); +const cfgTokenEnableRequestOutbox = configCommon.get('services.CoAuthoring.token.enable.request.outbox'); +const cfgLicenseFile = configCommon.get('license.license_file'); + +const app = express(); +app.disable('x-powered-by'); +//path.resolve uses __dirname by default(unexpected path in pkg) +app.set("views", path.resolve(process.cwd(), cfgHtmlTemplate)); +app.set("view engine", "ejs"); +const server = http.createServer(app); + +let licenseInfo, licenseOriginal, updatePluginsTime, userPlugins, pluginsLoaded; + +const updatePlugins = (eventType, filename) => { + operationContext.global.logger.info('update Folder: %s ; %s', eventType, filename); + if (updatePluginsTime && 1000 >= (new Date() - updatePluginsTime)) { + return; + } + operationContext.global.logger.info('update Folder true: %s ; %s', eventType, filename); + updatePluginsTime = new Date(); + pluginsLoaded = false; +}; +const readLicense = function*() { + [licenseInfo, licenseOriginal] = yield* license.readLicense(cfgLicenseFile); +}; +const updateLicense = () => { + return co(function*() { + try { + yield* readLicense(); + docsCoServer.setLicenseInfo(licenseInfo, licenseOriginal); + operationContext.global.logger.info('End updateLicense'); + } catch (err) { + operationContext.global.logger.error('updateLicense error: %s', err.stack); + } + }); +}; + +operationContext.global.logger.warn('Express server starting...'); + +if (!(cfgTokenEnableBrowser && cfgTokenEnableRequestInbox && cfgTokenEnableRequestOutbox)) { + operationContext.global.logger.warn('Set services.CoAuthoring.token.enable.browser, services.CoAuthoring.token.enable.request.inbox, ' + + 'services.CoAuthoring.token.enable.request.outbox in the Document Server config ' + + 'to prevent an unauthorized access to your documents and the substitution of important parameters in ONLYOFFICE Document Server requests.'); +} + +if (!tenantManager.isMultitenantMode()) { + updateLicense(); + setInterval(updateLicense, 86400000); +} + +if (config.has('server.static_content')) { + const staticContent = config.get('server.static_content'); + for (let i in staticContent) { + if (staticContent.hasOwnProperty(i)) { + app.use(i, express.static(staticContent[i]['path'], staticContent[i]['options'])); + } + } +} + +if (configStorage.has('fs.folderPath')) { + const cfgBucketName = configStorage.get('bucketName'); + const cfgStorageFolderName = configStorage.get('storageFolderName'); + app.use('/' + cfgBucketName + '/' + cfgStorageFolderName, (req, res, next) => { + const index = req.url.lastIndexOf('/'); + if ('GET' === req.method && -1 != index) { + let sendFileOptions = { + root: configStorage.get('fs.folderPath'), dotfiles: 'deny', headers: { + 'Content-Disposition': 'attachment' + } + }; + const urlParsed = urlModule.parse(req.url); + if (urlParsed && urlParsed.pathname) { + const filename = decodeURIComponent(path.basename(urlParsed.pathname)); + sendFileOptions.headers['Content-Type'] = mime.getType(filename); + } + const realUrl = req.url.substring(0, index); + res.sendFile(realUrl, sendFileOptions, (err) => { + if (err) { + operationContext.global.logger.error(err); + res.status(400).end(); + } + }); + } else { + res.sendStatus(404) + } + }); +} + +try { + fs.watch(config.get('plugins.path'), updatePlugins); +} catch (e) { + operationContext.global.logger.warn('Failed to subscribe to plugin folder updates. When changing the list of plugins, you must restart the server. https://nodejs.org/docs/latest/api/fs.html#fs_availability'); +} + +// Если захочется использовать 'development' и 'production', +// то с помощью app.settings.env (https://github.com/strongloop/express/issues/936) +// Если нужна обработка ошибок, то теперь она такая https://github.com/expressjs/errorhandler +docsCoServer.install(server, () => { + operationContext.global.logger.info('Start callbackFunction'); + + server.listen(config.get('server.port'), () => { + operationContext.global.logger.warn("Express server listening on port %d in %s mode. Version: %s. Build: %s", config.get('server.port'), app.settings.env, commonDefines.buildVersion, commonDefines.buildNumber); + }); + + app.get('/index.html', (req, res) => { + return co(function*() { + let ctx = new operationContext.Context(); + try { + ctx.initFromRequest(req); + let licenseInfo = yield tenantManager.getTenantLicense(ctx); + let buildVersion = commonDefines.buildVersion; + let buildNumber = commonDefines.buildNumber; + let buildDate, packageType, customerId = "", alias = ""; + if (licenseInfo) { + buildDate = licenseInfo.buildDate.toISOString(); + packageType = licenseInfo.packageType; + customerId = licenseInfo.customerId; + alias = licenseInfo.alias; + } + let output = `Server is functioning normally. Version: ${buildVersion}. Build: ${buildNumber}`; + output += `. Release date: ${buildDate}. Package type: ${packageType}. Customer Id: ${customerId}. Alias: ${alias}`; + res.send(output); + } catch (err) { + ctx.logger.error('index.html error: %s', err.stack); + res.sendStatus(400); + } + }); + }); + const rawFileParser = bodyParser.raw( + {inflate: true, limit: config.get('server.limits_tempfile_upload'), type: function() {return true;}}); + const urleEcodedParser = bodyParser.urlencoded({ extended: false }); + let forms = multer(); + + app.get('/coauthoring/CommandService.ashx', utils.checkClientIp, rawFileParser, docsCoServer.commandFromServer); + app.post('/coauthoring/CommandService.ashx', utils.checkClientIp, rawFileParser, + docsCoServer.commandFromServer); + + app.get('/ConvertService.ashx', utils.checkClientIp, rawFileParser, converterService.convertXml); + app.post('/ConvertService.ashx', utils.checkClientIp, rawFileParser, converterService.convertXml); + app.post('/converter', utils.checkClientIp, rawFileParser, converterService.convertJson); + + + app.get('/FileUploader.ashx', utils.checkClientIp, rawFileParser, fileUploaderService.uploadTempFile); + app.post('/FileUploader.ashx', utils.checkClientIp, rawFileParser, fileUploaderService.uploadTempFile); + + app.param('docid', (req, res, next, val) => { + if (constants.DOC_ID_REGEX.test(val)) { + next(); + } else { + res.sendStatus(403); + } + }); + app.param('index', (req, res, next, val) => { + if (!isNaN(parseInt(val))) { + next(); + } else { + res.sendStatus(403); + } + }); + //'*' for backward compatible + app.post('/uploadold/:docid*', fileUploaderService.uploadImageFileOld); + app.post('/upload/:docid*', rawFileParser, fileUploaderService.uploadImageFile); + + app.post('/downloadas/:docid', rawFileParser, canvasService.downloadAs); + app.post('/savefile/:docid', rawFileParser, canvasService.saveFile); + app.get('/printfile/:docid/:filename', canvasService.printFile); + app.get('/downloadfile/:docid', canvasService.downloadFile); + app.get('/healthcheck', utils.checkClientIp, docsCoServer.healthCheck); + + app.get('/baseurl', (req, res) => { + res.send(utils.getBaseUrlByRequest(req)); + }); + + app.get('/robots.txt', (req, res) => { + res.setHeader('Content-Type', 'plain/text'); + res.send("User-agent: *\nDisallow: /"); + }); + + app.post('/docbuilder', utils.checkClientIp, rawFileParser, (req, res) => { + converterService.builder(req, res); + }); + app.get('/info/info.json', utils.checkClientIp, docsCoServer.licenseInfo); + app.put('/internal/cluster/inactive', utils.checkClientIp, docsCoServer.shutdown); + app.delete('/internal/cluster/inactive', utils.checkClientIp, docsCoServer.shutdown); + + if (cfgWopiEnable) { + app.get('/hosting/discovery', utils.checkClientIp, wopiClient.discovery); + app.get('/hosting/capabilities', utils.checkClientIp, wopiClient.collaboraCapabilities); + app.post('/hosting/wopi/:documentType/:mode', urleEcodedParser, forms.none(), utils.lowercaseQueryString, wopiClient.getEditorHtml); + } + + app.post('/dummyCallback', utils.checkClientIp, rawFileParser, function(req, res){ + let ctx = new operationContext.Context(); + ctx.initFromRequest(req); + ctx.logger.debug(`dummyCallback req.body:%s`, req.body); + utils.fillResponseSimple(res, JSON.stringify({error: 0}, "application/json")); + }); + + const sendUserPlugins = (res, data) => { + pluginsLoaded = true; + res.setHeader('Content-Type', 'application/json'); + res.send(JSON.stringify(data)); + }; + app.get('/plugins.json', (req, res) => { + if (userPlugins && pluginsLoaded) { + sendUserPlugins(res, userPlugins); + return; + } + + if (!config.has('server.static_content') || !config.has('plugins.uri')) { + res.sendStatus(404); + return; + } + + let staticContent = config.get('server.static_content'); + let pluginsUri = config.get('plugins.uri'); + let pluginsPath = undefined; + let pluginsAutostart = config.get('plugins.autostart'); + + if (staticContent[pluginsUri]) { + pluginsPath = staticContent[pluginsUri].path; + } + + let baseUrl = '../../../..'; + utils.listFolders(pluginsPath, true).then((values) => { + return co(function*() { + const configFile = 'config.json'; + let stats = null; + let result = []; + for (let i = 0; i < values.length; ++i) { + try { + stats = yield utils.fsStat(path.join(values[i], configFile)); + } catch (err) { + stats = null; + } + + if (stats && stats.isFile) { + result.push( baseUrl + pluginsUri + '/' + path.basename(values[i]) + '/' + configFile); + } + } + + userPlugins = {'url': '', 'pluginsData': result, 'autostart': pluginsAutostart}; + sendUserPlugins(res, userPlugins); + }); + }); + }); + app.get('/themes.json', apicache.middleware("5 minutes"), (req, res) => { + return co(function*() { + let themes = []; + let ctx = new operationContext.Context(); + try { + ctx.initFromRequest(req); + ctx.logger.info('themes.json start'); + if (!config.has('server.static_content') || !config.has('themes.uri')) { + return; + } + let staticContent = config.get('server.static_content'); + let themesUri = config.get('themes.uri'); + let themesList = []; + + for (let i in staticContent) { + if (staticContent.hasOwnProperty(i) && themesUri.startsWith(i)) { + let dir = staticContent[i].path + themesUri.substring(i.length); + themesList = yield utils.listObjects(dir, true); + ctx.logger.debug('themes.json dir:%s', dir); + ctx.logger.debug('themes.json themesList:%j', themesList); + for (let j = 0; j < themesList.length; ++j) { + if (themesList[j].endsWith('.json')) { + let data = yield utils.readFile(themesList[j], true); + themes.push(JSON.parse(data.toString('utf-8'))); + } + } + break; + } + } + } catch (err) { + ctx.logger.error('themes.json error:%s', err.stack); + } finally { + if (themes.length > 0) { + res.setHeader('Content-Type', 'application/json'); + res.send({"themes": themes}); + } else { + res.sendStatus(404); + } + ctx.logger.info('themes.json end'); + } + }); + }); +}); + +process.on('uncaughtException', (err) => { + operationContext.global.logger.error((new Date).toUTCString() + ' uncaughtException:', err.message); + operationContext.global.logger.error(err.stack); + logger.shutdown(() => { + process.exit(1); + }); +}); diff --git a/server.patch b/server.patch deleted file mode 100644 index b70f41b..0000000 --- a/server.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 3c58d272005a300ad8fe575457d5ce25710833e9 Mon Sep 17 00:00:00 2001 -From: Beeant -Date: Sat, 24 Sep 2022 21:38:51 +0800 -Subject: [PATCH] build: license - ---- - Common/sources/constants.js | 2 +- - Common/sources/license.js | 16 ++++++++-------- - DocService/sources/server.js | 2 +- - FileConverter/sources/convertermaster.js | 1 - - Makefile | 2 +- - 5 files changed, 11 insertions(+), 12 deletions(-) - -diff --git a/Common/sources/constants.js b/Common/sources/constants.js -index 65d4c6f..39a7e56 100644 ---- a/Common/sources/constants.js -+++ b/Common/sources/constants.js -@@ -83,7 +83,7 @@ exports.LICENSE_RESULT = { - UsersViewCountOS: 15 - }; - --exports.LICENSE_CONNECTIONS = 20; -+exports.LICENSE_CONNECTIONS = 9999; - exports.LICENSE_EXPIRE_USERS_ONE_DAY = 24 * 60 * 60; // day in seconds - - exports.AVS_OFFICESTUDIO_FILE_UNKNOWN = 0x0000; -diff --git a/Common/sources/license.js b/Common/sources/license.js -index fbd5ec8..203dcb0 100644 ---- a/Common/sources/license.js -+++ b/Common/sources/license.js -@@ -45,22 +45,22 @@ exports.readLicense = function*() { - count: 1, - type: c_LR.Success, - light: false, -- packageType: constants.PACKAGE_TYPE_OS, -+ packageType: constants.PACKAGE_TYPE_I, - mode: constants.LICENSE_MODE.None, -- branding: false, -+ branding: true, - connections: constants.LICENSE_CONNECTIONS, - connectionsView: constants.LICENSE_CONNECTIONS, -- customization: false, -- usersCount: 0, -+ customization: true, -+ usersCount: constants.LICENSE_CONNECTIONS, - usersViewCount: 0, - usersExpire: constants.LICENSE_EXPIRE_USERS_ONE_DAY, -- hasLicense: false, -- plugins: false, -+ hasLicense: true, -+ plugins: true, - buildDate: oBuildDate, - startDate: startDate, -- endDate: null, -+ endDate: new Date("2099-01-01T23:59:59.000Z"), - customerId: "" - }, null]; - }; - --exports.packageType = constants.PACKAGE_TYPE_OS; -+exports.packageType = constants.PACKAGE_TYPE_I; -diff --git a/DocService/sources/server.js b/DocService/sources/server.js -index cf3ba90..d256724 100644 ---- a/DocService/sources/server.js -+++ b/DocService/sources/server.js -@@ -110,7 +110,7 @@ if (!(cfgTokenEnableBrowser && cfgTokenEnableRequestInbox && cfgTokenEnableReque - - if (!tenantManager.isMultitenantMode()) { - updateLicense(); -- fs.watchFile(cfgLicenseFile, updateLicense); - setInterval(updateLicense, 86400000); - } - -diff --git a/FileConverter/sources/convertermaster.js b/FileConverter/sources/convertermaster.js -index 2a0b366..96468f9 100644 ---- a/FileConverter/sources/convertermaster.js -+++ b/FileConverter/sources/convertermaster.js -@@ -93,7 +93,6 @@ if (cluster.isMaster) { - updateLicense(); - - if (!tenantManager.isMultitenantMode()) { -- fs.watchFile(cfgLicenseFile, updateLicense); - setInterval(updateLicense, 86400000); - } - } else { -diff --git a/Makefile b/Makefile -index e8e1308..a4b0a51 100644 ---- a/Makefile -+++ b/Makefile -@@ -87,7 +87,7 @@ DEBUG = $(BRANDING_DIR)/debug.js - .PHONY: all clean install uninstall build-date - - .NOTPARALLEL: --all: $(SPELLCHECKER_DICTIONARIES) $(TOOLS) $(SCHEMA) $(CORE_FONTS) $(DOCUMENT_TEMPLATES) $(LICENSE) $(WELCOME) $(INFO) build-date -+all: $(SPELLCHECKER_DICTIONARIES) $(TOOLS) $(SCHEMA) $(CORE_FONTS) $(DOCUMENT_TEMPLATES) $(WELCOME) $(INFO) build-date - - build-date: $(GRUNT_FILES) - sed "s|\(const buildVersion = \).*|\1'${PRODUCT_VERSION}';|" -i $(COMMON_DEFINES_JS) --- -2.31.1.windows.1 -