diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 000000000..4d6257a33
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,174 @@
+version: 2.1
+
+############################################################################
+
+references:
+ checkout_job_steps: &checkout_job_steps
+ steps:
+ - checkout
+ - run:
+ name: Checking out dependencies
+ command: |
+ git clone -b develop --single-branch https://github.com/Zimbra/zm-pkg-tool.git ~/zm-pkg-tool
+ echo "BUILD_NO=$CIRCLE_BUILD_NUM" > config.build
+ - persist_to_workspace:
+ root: ..
+ paths:
+ - zm-onlyoffice
+ - zm-pkg-tool
+
+ build_job_steps: &build_job_steps
+ steps:
+ - attach_workspace:
+ at: ..
+ - run:
+ name: Creating build
+ command: make -f Makefile.build
+ no_output_timeout: 30m
+ - store_artifacts:
+ path: build/dist
+ - persist_to_workspace:
+ root: ..
+ paths: zm-onlyoffice/build/dist/*
+
+ deploy_s3_job_steps: &deploy_s3_job_steps
+ docker:
+ - image: 'cimg/python:3.10'
+ resource_class: small
+ steps:
+ - attach_workspace:
+ at: ..
+ - run:
+ name: Create a zip file for artifacts and upload them to the OCI bucket
+ command: |
+ cd build/dist/
+ zip -r $CIRCLE_PROJECT_REPONAME.zip .
+ ZIP_FILE_PATH="$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/$CIRCLE_BRANCH-$CIRCLE_BUILD_NUM/archives/$CIRCLE_PROJECT_REPONAME.zip"
+ curl -X PUT "$OCI_PAR_URL$ZIP_FILE_PATH" -T $CIRCLE_PROJECT_REPONAME.zip
+ echo "artifacts uploaded to $ZIP_FILE_PATH"
+
+ std_filters: &std_filters
+ filters:
+ branches:
+ only:
+ - master
+ - develop
+
+############################################################################
+
+jobs:
+ checkout:
+ working_directory: ~/zm-onlyoffice
+ shell: /bin/bash -eo pipefail
+ docker:
+ - image: zimbra/zm-base-os:core-ubuntu
+ resource_class: small
+ <<: *checkout_job_steps
+
+ build_u22:
+ working_directory: ~/zm-onlyoffice
+ shell: /bin/bash -eo pipefail
+ docker:
+ - image: $DOCKER_REGISTRY/zm-base-os:devcore-ubuntu-22.04
+ auth:
+ username: $DOCKER_USER
+ password: $DOCKER_PASS
+ resource_class: small
+ <<: *build_job_steps
+
+ build_u20:
+ working_directory: ~/zm-onlyoffice
+ shell: /bin/bash -eo pipefail
+ docker:
+ - image: zimbra/zm-base-os:devcore-ubuntu-20.04
+ resource_class: small
+ <<: *build_job_steps
+
+ build_u18:
+ working_directory: ~/zm-onlyoffice
+ shell: /bin/bash -eo pipefail
+ docker:
+ - image: zimbra/zm-base-os:devcore-ubuntu-18.04
+ resource_class: small
+ <<: *build_job_steps
+
+ build_c9:
+ working_directory: ~/zm-onlyoffice
+ shell: /bin/bash -eo pipefail
+ docker:
+ - image: $DOCKER_REGISTRY/zm-base-os:devcore-centos-9
+ auth:
+ username: $DOCKER_USER
+ password: $DOCKER_PASS
+ resource_class: small
+ <<: *build_job_steps
+
+ build_c8:
+ working_directory: ~/zm-onlyoffice
+ shell: /bin/bash -eo pipefail
+ docker:
+ - image: zimbra/zm-base-os:devcore-centos-8
+ resource_class: small
+ <<: *build_job_steps
+
+ build_c7:
+ working_directory: ~/zm-onlyoffice
+ shell: /bin/bash -eo pipefail
+ docker:
+ - image: zimbra/zm-base-os:devcore-centos-7
+ resource_class: small
+ <<: *build_job_steps
+
+ deploy_s3:
+ working_directory: ~/zm-onlyoffice
+ shell: /bin/bash -eo pipefail
+ <<: *deploy_s3_job_steps
+
+############################################################################
+
+workflows:
+ version: 2
+ main:
+ jobs:
+ - build:
+ type: approval
+ - checkout:
+ requires:
+ - build
+ - build_u22:
+ requires:
+ - checkout
+ context:
+ - docker-dev-registry
+ - build_u20:
+ requires:
+ - checkout
+ - build_u18:
+ requires:
+ - checkout
+ - build_c9:
+ requires:
+ - checkout
+ context:
+ - docker-dev-registry
+ - build_c8:
+ requires:
+ - checkout
+ - build_c7:
+ requires:
+ - checkout
+ - deploy_s3_hold:
+ type: approval
+ requires:
+ - build_u22
+ - build_u20
+ - build_u18
+ - build_c9
+ - build_c8
+ - build_c7
+
+ - deploy_s3:
+ context:
+ - oracle
+ requires:
+ - deploy_s3_hold
diff --git a/.gitignore b/.gitignore
index b70f8847a..6ab919c2a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ node_modules
/Gruntfile.js.out
local-development-*.json
*.pyc
+.DS_Store
diff --git a/Common/config/default.json b/Common/config/default.json
index 2c1f01fec..89d59ae43 100644
--- a/Common/config/default.json
+++ b/Common/config/default.json
@@ -112,8 +112,12 @@
},
"services": {
"CoAuthoring": {
+ "ssl" :{
+ "key" : "",
+ "cert" : ""
+ },
"server": {
- "port": 8000,
+ "port": 7084,
"workerpercpu": 1,
"mode": "development",
"limits_tempfile_upload": 104857600,
@@ -158,11 +162,11 @@
"limits_image_types_upload": "jpg;jpeg;jpe;png;gif;bmp"
},
"sql": {
- "type": "postgres",
+ "type": "mysql",
"tableChanges": "doc_changes",
"tableResult": "task_result",
"dbHost": "localhost",
- "dbPort": 5432,
+ "dbPort": 7306,
"dbName": "onlyoffice",
"dbUser": "onlyoffice",
"dbPass": "onlyoffice",
@@ -327,5 +331,21 @@
}
]
}
+ },
+ "FileStorage": {
+ "host": "",
+ "port": 4567,
+ "directory": "",
+ "silent": true
+ },
+ "SpellChecker": {
+ "ssl" :{
+ "key" : "",
+ "cert" : ""
+ },
+ "server": {
+ "port": 7085,
+ "mode": "development"
+ }
}
-}
+}
\ No newline at end of file
diff --git a/Common/config/log4js/logconfig.json b/Common/config/log4js/logconfig.json
new file mode 100644
index 000000000..a6f117193
--- /dev/null
+++ b/Common/config/log4js/logconfig.json
@@ -0,0 +1,15 @@
+{
+ "appenders": {
+ "default": {
+ "type": "file",
+ "filename": "/opt/zimbra/log/onlyoffice.log",
+ "layout": {
+ "type": "pattern",
+ "pattern": "[%d] [%p] %c - %.10000m"
+ }
+ }
+ },
+ "categories": {
+ "default": { "appenders": [ "default" ], "level": "WARN" }
+ }
+}
\ No newline at end of file
diff --git a/Common/config/onlyofficeconfig.json b/Common/config/onlyofficeconfig.json
new file mode 100644
index 000000000..3f4cc7ecd
--- /dev/null
+++ b/Common/config/onlyofficeconfig.json
@@ -0,0 +1,70 @@
+{
+ "log": {
+ "filePath": "/opt/zimbra/onlyoffice/documentserver/server/Common/config/log4js/logconfig.json"
+ },
+ "storage": {
+ "fs": {
+ "folderPath": "/opt/zimbra/onlyoffice/documentserver/App_Data/cache/files"
+ }
+ },
+ "services": {
+ "CoAuthoring": {
+ "server": {
+ "static_content": {
+ "/fonts": {
+ "path": "/opt/zimbra/onlyoffice/documentserver/fonts",
+ "options": {"maxAge": "7d"}
+ },
+ "/sdkjs": {
+ "path": "/opt/zimbra/onlyoffice/documentserver/sdkjs",
+ "options": {"maxAge": "7d"}
+ },
+ "/web-apps": {
+ "path": "/opt/zimbra/onlyoffice/documentserver/web-apps",
+ "options": {"maxAge": "7d"}
+ },
+ "/sdkjs-plugins": {
+ "path": "/opt/zimbra/onlyoffice/documentserver/sdkjs-plugins",
+ "options": {"maxAge": "7d"}
+ },
+ "/App_Data": {
+ "path": "/opt/zimbra/onlyoffice/documentserver/App_Data",
+ "options": {"maxAge": "7d"}
+ }
+ }
+ },
+ "utils": {
+ "utils_common_fontdir": "/usr/share/fonts"
+ },
+ "request-filtering-agent" : {
+ "allowPrivateIPAddress": true,
+ "allowMetaIPAddress": true
+ },
+ "sockjs": {
+ "sockjs_url": "/opt/zimbra/onlyoffice/documentserver/web-apps/vendor/sockjs/sockjs.min.js"
+ }
+ }
+ },
+ "license": {
+ "license_file": "/opt/zimbra/onlyoffice/documentserver/license.lic",
+ "warning_limit_percents": 70,
+ "packageType": 0
+ },
+ "FileConverter": {
+ "converter": {
+ "fontDir": "/usr/share/fonts",
+ "presentationThemesDir": "/opt/zimbra/onlyoffice/documentserver/sdkjs/slide/themes",
+ "x2tPath": "/opt/zimbra/onlyoffice/documentserver/server/FileConverter/bin/x2t",
+ "docbuilderPath": "/opt/zimbra/onlyoffice/documentserver/server/FileConverter/bin/docbuilder",
+ "docbuilderAllFontsPath": "/opt/zimbra/onlyoffice/documentserver/App_Data/docbuilder/AllFonts.js"
+ }
+ },
+ "FileStorage": {
+ "directory": "/opt/zimbra/onlyoffice/documentserver/App_Data"
+ },
+ "SpellChecker": {
+ "server": {
+ "dictDir": "/opt/zimbra/onlyoffice/documentserver/dictionaries"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Common/sources/constants.js b/Common/sources/constants.js
index 65d4c6f33..df96adbd2 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 = 99999;
exports.LICENSE_EXPIRE_USERS_ONE_DAY = 24 * 60 * 60; // day in seconds
exports.AVS_OFFICESTUDIO_FILE_UNKNOWN = 0x0000;
diff --git a/DocService/sources/server.js b/DocService/sources/server.js
index 5c744f642..68359f1b4 100644
--- a/DocService/sources/server.js
+++ b/DocService/sources/server.js
@@ -42,6 +42,7 @@ const fs = require('fs');
const express = require('express');
const http = require('http');
+const https = require('https');
const urlModule = require('url');
const path = require('path');
const bodyParser = require("body-parser");
@@ -59,7 +60,6 @@ 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');
@@ -68,11 +68,19 @@ const cfgTokenEnableRequestOutbox = configCommon.get('services.CoAuthoring.token
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 server = null;
+
+if (config.has('ssl')) {
+ const privateKey = fs.readFileSync(config.get('ssl.key')).toString();
+ const certificateKey = fs.readFileSync(config.get('ssl.cert')).toString();
+ //See detailed options format here: http://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener
+ const options = {key: privateKey, cert: certificateKey};
+
+ server = https.createServer(options, app);
+} else {
+ server = http.createServer(app);
+}
let licenseInfo, licenseOriginal, updatePluginsTime, userPlugins, pluginsLoaded;
@@ -360,4 +368,4 @@ process.on('uncaughtException', (err) => {
logger.shutdown(() => {
process.exit(1);
});
-});
+});
\ No newline at end of file
diff --git a/Makefile.build b/Makefile.build
new file mode 100644
index 000000000..f48c87af6
--- /dev/null
+++ b/Makefile.build
@@ -0,0 +1,55 @@
+########################################################################################################
+
+SHELL = bash
+
+SHA512 = sha512sum
+
+OS = $(shell cat /etc/os-release | grep '^NAME' | cut -d'=' -f2 | cut -d'"' -f2)
+
+.PHONY: clean all
+
+########################################################################################################
+
+
+all: clean zimbra-onlyoffice-pkg
+
+########################################################################################################
+
+ONLY_OFFICE_VERSION = 1.0
+ONLY_OFFICE_URL="https://files.zimbra.com/downloads/onlyoffice/u14/zimbra-onlyoffice-v7.2.2.56.tar.gz"
+
+stage-zimbra-onlyoffice-pkg: downloads
+ mkdir -p build/stage/zimbra-onlyoffice/opt/zimbra
+ cp -r downloads/onlyoffice build/stage/zimbra-onlyoffice/opt/zimbra/
+ chmod +x build/stage/zimbra-onlyoffice/opt/zimbra/onlyoffice/bin/jq
+ cp -af bin/zmonlyofficeconfig build/stage/zimbra-onlyoffice/opt/zimbra/onlyoffice/bin/zmonlyofficeconfig
+ rm -rf build/stage/zimbra-onlyoffice/opt/zimbra/onlyoffice/.DS_Store
+ rm -rf build/stage/zimbra-onlyoffice/opt/zimbra/onlyoffice/._.DS_Store
+
+zimbra-onlyoffice-pkg: stage-zimbra-onlyoffice-pkg
+ ./pkg-build.pl \
+ --pkg-version=$(ONLY_OFFICE_VERSION).$(shell git log --format=%at -1) \
+ --pkg-release=1 \
+ --pkg-name=zimbra-onlyoffice \
+ --out-type=binary \
+ --pkg-summary="Zimbra onlyoffice package" \
+ --pkg-pre-install-script='scripts/preinst.sh' \
+ --pkg-post-install-script='scripts/postinst.sh' \
+ --pkg-installs='/opt/zimbra/onlyoffice/*'
+
+
+downloads:
+ mkdir -p downloads
+ wget -O downloads/zimbra-onlyoffice.tar.gz $(ONLY_OFFICE_URL)
+ cd downloads/; tar -xf zimbra-onlyoffice.tar.gz
+ mv downloads/zimbra-onlyoffice downloads/onlyoffice
+
+########################################################################################################
+
+########################################################################################################
+
+clean:
+ rm -rf build
+ rm -rf downloads
+
+########################################################################################################
diff --git a/SpellChecker/sources/server.js b/SpellChecker/sources/server.js
index 61bd8080e..756a45961 100644
--- a/SpellChecker/sources/server.js
+++ b/SpellChecker/sources/server.js
@@ -93,9 +93,9 @@ if (cluster.isMaster) {
if (config.has('ssl')) {
const privateKey = fs.readFileSync(config.get('ssl.key')).toString();
const certificateKey = fs.readFileSync(config.get('ssl.cert')).toString();
- const trustedCertificate = fs.readFileSync(config.get('ssl.ca')).toString();
+
//See detailed options format here: http://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener
- const options = {key: privateKey, cert: certificateKey, ca: [trustedCertificate]};
+ const options = {key: privateKey, cert: certificateKey};
server = https.createServer(options, app);
} else {
diff --git a/bin/createdb.sql b/bin/createdb.sql
new file mode 100644
index 000000000..68de88c20
--- /dev/null
+++ b/bin/createdb.sql
@@ -0,0 +1,81 @@
+--
+-- Create schema onlyoffice
+--
+CREATE DATABASE IF NOT EXISTS onlyoffice DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
+--CREATE USER IF NOT EXISTS 'onlyoffice' IDENTIFIED BY 'onlyoffice';
+--grant all on onlyoffice.* to 'onlyoffice' identified by 'onlyoffice';
+GRANT ALL PRIVILEGES ON onlyoffice.* TO 'zimbra';
+FLUSH PRIVILEGES;
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+
+
+
+USE onlyoffice;
+
+--
+-- Definition of table `doc_changes`
+--
+
+CREATE TABLE IF NOT EXISTS `doc_changes` (
+ `tenant` varchar(255) NOT NULL,
+ `id` varchar(255) NOT NULL,
+ `change_id` int(10) unsigned NOT NULL,
+ `user_id` varchar(255) NOT NULL,
+ `user_id_original` varchar(255) NOT NULL,
+ `user_name` varchar(255) NOT NULL,
+ `change_data` longtext NOT NULL,
+ `change_date` datetime NOT NULL,
+ PRIMARY KEY (`tenant`, `id`,`change_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `doc_changes`
+--
+
+/*!40000 ALTER TABLE `doc_changes` DISABLE KEYS */;
+/*!40000 ALTER TABLE `doc_changes` ENABLE KEYS */;
+
+--
+-- Definition of table `task_result`
+--
+
+CREATE TABLE IF NOT EXISTS `task_result` (
+ `tenant` varchar(255) NOT NULL,
+ `id` varchar(255) NOT NULL,
+ `status` tinyint(3) NOT NULL,
+ `status_info` int(10) NOT NULL,
+ `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `last_open_date` datetime NOT NULL,
+ `user_index` int(10) unsigned NOT NULL DEFAULT 1,
+ `change_id` int(10) unsigned NOT NULL DEFAULT 0,
+ `callback` longtext NOT NULL,
+ `baseurl` text NOT NULL,
+ `password` longtext NULL,
+ `additional` longtext NULL,
+ PRIMARY KEY (`tenant`, `id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `task_result`
+--
+
+/*!40000 ALTER TABLE `task_result` DISABLE KEYS */;
+/*!40000 ALTER TABLE `task_result` ENABLE KEYS */;
+
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
diff --git a/bin/jq b/bin/jq
new file mode 100644
index 000000000..f48b0ca92
Binary files /dev/null and b/bin/jq differ
diff --git a/bin/process_id.json b/bin/process_id.json
new file mode 100644
index 000000000..9bdeba80c
--- /dev/null
+++ b/bin/process_id.json
@@ -0,0 +1,4 @@
+{
+ "docservice": -1,
+ "converter" : -1
+}
diff --git a/bin/zmonlyofficeconfig b/bin/zmonlyofficeconfig
new file mode 100644
index 000000000..510bc6e54
--- /dev/null
+++ b/bin/zmonlyofficeconfig
@@ -0,0 +1,260 @@
+#!/bin/bash
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Zimbra Collaboration Suite Server
+# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2021 Synacor, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software Foundation,
+# version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License along with this program.
+# If not, see .
+# ***** END LICENSE BLOCK *****
+#
+
+source /opt/zimbra/bin/zmshutil || exit 1
+zmsetvars
+
+zmjq="/opt/zimbra/onlyoffice/bin/jq"
+
+defaultjson_path="/opt/zimbra/onlyoffice/documentserver/server/Common/config/default.json"
+mysql_port=7306
+zimbra_mysql_user="zimbra"
+zimbra_mysql_password=""
+
+# Check for commercial certificates
+if [ -f /opt/zimbra/ssl/zimbra/commercial/commercial.crt ] && [ -f /opt/zimbra/ssl/zimbra/commercial/commercial.key ]; then
+ server_crt="/opt/zimbra/ssl/zimbra/commercial/commercial.crt"
+ server_key="/opt/zimbra/ssl/zimbra/commercial/commercial.key"
+else
+ server_crt="/opt/zimbra/ssl/zimbra/server/server.crt"
+ server_key="/opt/zimbra/ssl/zimbra/server/server.key"
+fi
+
+STATUS=0
+
+document_editing_JWT_secret=""
+
+usage() {
+ echo ""
+ echo "Invalid argument. Allowed :"
+ echo "new Configure Onlyoffice on the server"
+ echo "update-jwt-secret arg0 Update Onlyoffice server's jwt secret with the passed value"
+ echo "update-db Update Onlyoffice server's DB connection details from config"
+ echo "update-certificate Update Onlyoffice server's certificate paths"
+ echo ""
+ exit
+}
+
+generate_random()
+{
+ length=8
+ digits=({2..9})
+ lower=({a..k} {m..n} {p..z})
+ upper=({A..N} {P..Z})
+ CharArray=(${digits[*]} ${lower[*]} ${upper[*]})
+ ArrayLength=${#CharArray[*]}
+ password=""
+ while [ $length -gt 0 ]
+ do
+ index=$(($RANDOM%$ArrayLength))
+ char=${CharArray[$index]}
+ password=${password}${char}
+ ((length--))
+ done
+ echo "$password"
+}
+
+update_db_config()
+{
+ #port
+ config_mysql_port=$(su - zimbra -c "zmlocalconfig -x -s mysql_port")
+ if [ -n "$config_mysql_port" ]; then
+ IFS='='
+ read -ra arr <<< "$config_mysql_port"
+ mysql_port=$(echo "${arr[1]}" | xargs)
+ fi
+
+ content=$(${zmjq} --argjson mysql_port "$mysql_port" '.services.CoAuthoring.sql.dbPort=$mysql_port' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+ #user
+ config_mysql_user=$(su - zimbra -c "zmlocalconfig -x -s zimbra_mysql_user")
+ if [ -n "$config_mysql_user" ]; then
+ IFS='='
+ read -ra arr <<< "$config_mysql_user"
+ zimbra_mysql_user=$(echo "${arr[1]}" | xargs)
+ fi
+
+ content=$(${zmjq} --arg zimbra_mysql_user "$zimbra_mysql_user" '.services.CoAuthoring.sql.dbUser=$zimbra_mysql_user' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+ #password
+ config_mysql_pass=$(su - zimbra -c "zmlocalconfig -x -s zimbra_mysql_password")
+ if [ -n "$config_mysql_pass" ]; then
+ IFS='='
+ read -ra arr <<< "$config_mysql_pass"
+ zimbra_mysql_password=$(echo "${arr[1]}" | xargs)
+ fi
+
+ content=$(${zmjq} --arg zimbra_mysql_password "$zimbra_mysql_password" '.services.CoAuthoring.sql.dbPass=$zimbra_mysql_password' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+}
+
+update_certificate_path()
+{
+ content=$(${zmjq} --arg server_crt "$server_crt" '.services.CoAuthoring.ssl.cert=$server_crt' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+ content=$(${zmjq} --arg server_crt "$server_crt" '.SpellChecker.ssl.cert=$server_crt' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+ content=$(${zmjq} --arg server_key "$server_key" '.services.CoAuthoring.ssl.key=$server_key' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+ content=$(${zmjq} --arg server_key "$server_key" '.SpellChecker.ssl.key=$server_key' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+}
+
+update_token_config()
+{
+
+ content=$(${zmjq} '.services.CoAuthoring.token.enable.browser=true' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+ content=$(${zmjq} '.services.CoAuthoring.token.enable.request.inbox=true' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+ content=$(${zmjq} '.services.CoAuthoring.token.enable.request.outbox=true' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+ content=$(${zmjq} '.services.CoAuthoring.requestDefaults.rejectUnauthorized=false' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+}
+
+update_jwt_config()
+{
+ jwtsecret=$1
+ cmd="su - zimbra -c \"zmprov -m -l mcf zimbraDocumentEditingJwtSecret ${jwtsecret}\""
+ eval "$cmd"
+ RC=$?
+ if [ $RC -ne "0" ]; then
+ STATUS=$R
+ echo "Updating zimbraDocumentEditingJwtSecret faced problem."
+ fi
+
+ #update the default.json
+ content=$(${zmjq} --arg jwtsecret "$jwtsecret" '.services.CoAuthoring.secret.browser.string=$jwtsecret' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+ content=$(${zmjq} --arg jwtsecret "$jwtsecret" '.services.CoAuthoring.secret.inbox.string=$jwtsecret' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+ content=$(${zmjq} --arg jwtsecret "$jwtsecret" '.services.CoAuthoring.secret.outbox.string=$jwtsecret' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+
+ content=$(${zmjq} --arg jwtsecret "$jwtsecret" '.services.CoAuthoring.secret.session.string=$jwtsecret' ${defaultjson_path})
+ echo "${content}" > ${defaultjson_path}
+}
+
+set_jwt_secret()
+{
+ echo "Setting Random Secret..."
+ jwtsecret=$(generate_random)
+ update_jwt_config "$jwtsecret"
+}
+
+generate_fonts_data()
+{
+ mkdir -p /opt/zimbra/onlyoffice/documentserver/fonts
+
+ fonts_gen=$(LD_LIBRARY_PATH=/opt/zimbra/onlyoffice/documentserver/server/FileConverter/bin /opt/zimbra/onlyoffice/documentserver/server/tools/allfontsgen \
+ --input="/opt/zimbra/onlyoffice/documentserver/core-fonts" \
+ --allfonts-web="/opt/zimbra/onlyoffice/documentserver/sdkjs/common/AllFonts.js" \
+ --allfonts="/opt/zimbra/onlyoffice/documentserver/server/FileConverter/bin/AllFonts.js" \
+ --images="/opt/zimbra/onlyoffice/documentserver/sdkjs/common/Images" \
+ --selection="/opt/zimbra/onlyoffice/documentserver/server/FileConverter/bin/font_selection.bin" \
+ --output-web="/opt/zimbra/onlyoffice/documentserver/fonts" \
+ --use-system="true")
+ R=$?
+ if [ $R -ne "0" ]; then
+ STATUS=$R
+ echo "Error while generating fonts. ${fonts_gen}"
+ fi
+
+}
+
+generate_presentation_themes()
+{
+ presentation_themes_gen=$(LD_LIBRARY_PATH=/opt/zimbra/onlyoffice/documentserver/server/FileConverter/bin /opt/zimbra/onlyoffice/documentserver/server/tools/allthemesgen \
+ --converter-dir="/opt/zimbra/onlyoffice/documentserver/server/FileConverter/bin"\
+ --src="/opt/zimbra/onlyoffice/documentserver/sdkjs/slide/themes"\
+ --output="/opt/zimbra/onlyoffice/documentserver/sdkjs/common/Images")
+ R=$?
+ if [ $R -ne "0" ]; then
+ STATUS=$R
+ echo "Error while generating presentation themes. ${presentation_themes_gen}"
+ fi
+}
+
+type="$1"
+if [ "$#" -eq 0 ]; then
+ type="new"
+fi
+
+
+case "$type" in
+ new)
+
+ jwtsecret=$(su - zimbra -c "zmprov -m -l getConfig zimbraDocumentEditingJwtSecret")
+ if [ -z "$jwtsecret" ]; then
+ echo "JWT Secret not set."
+ set_jwt_secret
+ else
+ IFS=':'
+ read -ra arr <<< "$jwtsecret"
+ document_editing_JWT_secret=$(echo "${arr[1]}" | xargs)
+ update_jwt_config "$document_editing_JWT_secret"
+ fi
+
+ update_certificate_path
+ update_token_config
+ update_db_config
+ generate_fonts_data
+ generate_presentation_themes
+ echo "Onlyoffice configuration done."
+ exit $STATUS
+ ;;
+
+ update-jwt-secret)
+
+ if [ "$#" -ne 2 ]; then
+ usage
+ exit 1
+ fi
+ jwtsecret="$2"
+
+ update_jwt_config "$jwtsecret"
+ exit $STATUS
+ ;;
+
+ update-db )
+ update_db_config
+ exit $STATUS
+ ;;
+
+ update-certificate )
+ update_certificate_path
+ exit $STATUS
+ ;;
+
+ *)
+ usage
+ exit 1
+ ;;
+esac
diff --git a/pkg-build.pl b/pkg-build.pl
new file mode 100755
index 000000000..c1bb67ac8
--- /dev/null
+++ b/pkg-build.pl
@@ -0,0 +1,714 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Config;
+use Cwd;
+use Data::Dumper;
+use File::Basename;
+use File::Copy;
+use File::Find;
+use File::Path qw/make_path/;
+use Getopt::Long;
+use IPC::Cmd qw/run can_run/;
+use Term::ANSIColor;
+
+my $GLOBAL_PATH_TO_SCRIPT_FILE;
+my $GLOBAL_PATH_TO_SCRIPT_DIR;
+my $GLOBAL_PATH_TO_TOP;
+my $CWD;
+my $ZM_PKG_TOOL_DIR;
+my $PKG_CREATION_DATE = `date -R`;
+
+my %CFG = ();
+
+BEGIN
+{
+ $ENV{ANSI_COLORS_DISABLED} = 1 if ( ! -t STDOUT );
+ $GLOBAL_PATH_TO_SCRIPT_FILE = Cwd::abs_path(__FILE__);
+ $GLOBAL_PATH_TO_SCRIPT_DIR = dirname($GLOBAL_PATH_TO_SCRIPT_FILE);
+ $GLOBAL_PATH_TO_TOP = dirname($GLOBAL_PATH_TO_SCRIPT_DIR);
+ $ZM_PKG_TOOL_DIR = $GLOBAL_PATH_TO_TOP."/zm-pkg-tool";
+ $GLOBAL_PATH_TO_SCRIPT_DIR = $ZM_PKG_TOOL_DIR;
+ $CWD = getcwd();
+}
+
+sub LoadConfiguration($)
+{
+ my $args = shift;
+
+ my $cfg_name = $args->{name};
+ my $cmd_hash = $args->{hash_src};
+ my $default_sub = $args->{default_sub};
+ my $validate_sub = $args->{validate_sub};
+
+ my $val;
+ my $src;
+
+ if ( !defined $val )
+ {
+ y/A-Z_/a-z-/ foreach ( my $cmd_name = $cfg_name );
+
+ if ( $cmd_hash && exists $cmd_hash->{$cmd_name} )
+ {
+ $val = $cmd_hash->{$cmd_name};
+ $src = "cmdline";
+ }
+ }
+
+ if ( !defined $val )
+ {
+ if ( $CFG{CFG_DIR} )
+ {
+ my $file = "$CFG{CFG_DIR}/config.pl";
+ my $hash = LoadProperties($file)
+ if ( -f $file );
+
+ if ( $hash && exists $hash->{$cfg_name} )
+ {
+ $val = $hash->{$cfg_name};
+ $src = "config"
+ }
+ }
+ }
+
+ my $valid = 1;
+
+ if ( defined $val )
+ {
+ $valid = &$validate_sub($val)
+ if ($validate_sub);
+ }
+
+ if ( !defined $val || !$valid )
+ {
+ if ($default_sub)
+ {
+ $val = &$default_sub($cfg_name);
+ $src = "default" . ( $valid ? "" : "($src was rejected)" );
+ }
+ }
+
+ if ( defined $val )
+ {
+ $valid = &$validate_sub($val)
+ if ($validate_sub);
+
+ if ( ref($val) eq "HASH" )
+ {
+ foreach my $k ( keys %{$val} )
+ {
+ $CFG{$cfg_name}{$k} = ${$val}{$k};
+
+ printf( " %-25s: %-17s : %s\n", $cfg_name, $cmd_hash ? $src : "detected", "{" . $k . " => " . ${$val}{$k} . "}" );
+ }
+ }
+ elsif ( ref($val) eq "ARRAY" )
+ {
+ $CFG{$cfg_name} = $val;
+
+ printf( " %-25s: %-17s : %s\n", $cfg_name, $cmd_hash ? $src : "detected", "[" . join( ", ", @{ $CFG{$cfg_name} } ) . "]" );
+ }
+ else
+ {
+ $CFG{$cfg_name} = $val;
+
+ printf( " %-25s: %-17s : %s\n", $cfg_name, $cmd_hash ? $src : "detected", $val );
+ }
+ }
+}
+
+
+sub Die($;$)
+{
+ my $msg = shift;
+ my $info = shift || "";
+ my $err = "$!";
+
+ print "\n";
+ print "\n";
+ print "=========================================================================================================\n";
+ print color('red') . "FAILURE MSG" . color('reset') . " : $msg\n";
+ print color('red') . "SYSTEM ERR " . color('reset') . " : $err\n" if ($err);
+ print color('red') . "EXTRA INFO " . color('reset') . " : $info\n" if ($info);
+ print "\n";
+ print "=========================================================================================================\n";
+ print color('red');
+ print "--Stack Trace--\n";
+ my $i = 1;
+
+ while ( ( my @call_details = ( caller( $i++ ) ) ) )
+ {
+ print $call_details[1] . ":" . $call_details[2] . " called from " . $call_details[3] . "\n";
+ }
+ print color('reset');
+ print "\n";
+ print "=========================================================================================================\n";
+
+ die "END";
+}
+
+
+sub assert($$;$)
+{
+ my $l = shift || "";
+ my $r = shift || "";
+ my $m = shift || "";
+
+ Die( $m, "Got:[$l] != Exp:[$r]" )
+ if ( $l ne $r );
+}
+
+sub LoadProperties($)
+{
+ my $f = shift;
+
+ my $x = SlurpFile($f);
+
+ my @cfg_kvs =
+ map { $_ =~ s/^\s+|\s+$//g; $_ } # trim
+ map { split( /=/, $_, 2 ) } # split around =
+ map { $_ =~ s/#.*$//g; $_ } # strip comments
+ grep { $_ !~ /^\s*#/ } # ignore comments
+ grep { $_ !~ /^\s*$/ } # ignore empty lines
+ @$x;
+
+ my %ret_hash = ();
+ for ( my $e = 0 ; $e < scalar @cfg_kvs ; $e += 2 )
+ {
+ my $probe_key = $cfg_kvs[$e];
+ my $probe_val = $cfg_kvs[ $e + 1 ];
+
+ if ( $probe_key =~ /^%(.*)/ )
+ {
+ my @val_kv_pair = split( /=/, $probe_val, 2 );
+
+ $ret_hash{$1}{ $val_kv_pair[0] } = $val_kv_pair[1];
+ }
+ else
+ {
+ $ret_hash{$probe_key} = $probe_val;
+ }
+ }
+
+ return \%ret_hash;
+}
+
+
+sub SlurpFile($)
+{
+ my $f = shift;
+
+ open( FD, "<", "$f" ) || Die( "In open for read", "file='$f'" );
+
+ chomp( my @x = );
+ close(FD);
+
+ return \@x;
+}
+
+sub System(@)
+{
+ my $cmd_str = "@_";
+
+ print color('green') . "#: pwd=@{[Cwd::getcwd()]}" . color('reset') . "\n";
+ print color('green') . "#: $cmd_str" . color('reset') . "\n";
+
+ $! = 0;
+ my ( $success, $error_message, $full_buf, $stdout_buf, $stderr_buf ) = run( command => \@_, verbose => 1 );
+
+ Die( "cmd='$cmd_str'", $error_message )
+ if ( !$success );
+
+ return { msg => $error_message, out => $stdout_buf, err => $stderr_buf };
+}
+
+sub GetPkgFormat()
+{
+ if ( -f "/etc/redhat-release" )
+ {
+ return "rpm";
+ }
+ elsif ( -f "/etc/lsb-release" )
+ {
+ return "deb";
+ }
+ else
+ {
+ Die("Unknown OS");
+ }
+}
+
+sub GetOsTag()
+{
+ our $gOSTAG;
+
+ if ( !defined $gOSTAG )
+ {
+ if ( -f "/etc/redhat-release" )
+ {
+ chomp( $gOSTAG = `sed -n -e '1{s/[^0-9]*/r/; s/[.].*//; p;}' /etc/redhat-release` );
+ }
+ elsif ( -f "/etc/lsb-release" )
+ {
+ chomp( $gOSTAG = `sed -n -e '/DISTRIB_RELEASE/{s/.*=/u/; s/[.].*//; p;}' /etc/lsb-release` );
+ }
+ else
+ {
+ Die("Unknown OS");
+ }
+ }
+
+ return $gOSTAG
+}
+
+sub _ValidateOutType($)
+{
+ my $ty = shift;
+
+ if ( defined $ty )
+ {
+ return 1 if ( $ty eq "all" );
+ return 1 if ( $ty eq "source" );
+ return 1 if ( $ty eq "binary" );
+ }
+
+ return undef;
+}
+
+sub Init()
+{
+ my %cmd_hash = ();
+
+ my @cmd_args = (
+ {
+ name => "CFG_DIR",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return "pkg-spec"; },
+ },
+ {
+ name => "OUT_TYPE",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => &_ValidateOutType,
+ default_sub => sub { return "all"; },
+ },
+ {
+ name => "OUT_BASE_DIR",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return "build"; },
+ },
+ {
+ name => "OUT_TEMP_DIR",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return "$CFG{OUT_BASE_DIR}/tmp"; },
+ },
+ {
+ name => "OUT_STAGE_DIR",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return "$CFG{OUT_BASE_DIR}/stage"; },
+ },
+ {
+ name => "OUT_DIST_DIR",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return "$CFG{OUT_BASE_DIR}/dist"; },
+ },
+ {
+ name => "PKG_NAME",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return Die("@_ not unspecfied"); },
+ },
+ {
+ name => "PKG_RELEASE",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return Die("@_ not specified"); },
+ },
+ {
+ name => "PKG_VERSION",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return Die("@_ not specified"); },
+ },
+ {
+ name => "PKG_SUMMARY",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return Die("@_ not specified"); },
+ },
+ {
+ name => "PKG_INSTALLS",
+ type => "=s@",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return []; },
+ },
+ {
+ name => "PKG_DEPENDS",
+ type => "=s@",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return []; },
+ },
+ {
+ name => "PKG_PRE_DEPENDS",
+ type => "=s@",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return []; },
+ },
+ {
+ name => "PKG_PROVIDES",
+ type => "=s@",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return []; },
+ },
+ {
+ name => "PKG_CONFLICTS",
+ type => "=s@",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return []; },
+ },
+ {
+ name => "PKG_OBSOLETES",
+ type => "=s@",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return []; },
+ },
+ {
+ name => "PKG_REPLACES",
+ type => "=s@",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return []; },
+ },
+ {
+ name => "PKG_PRE_INSTALL_SCRIPT",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return undef; },
+ },
+ {
+ name => "PKG_POST_INSTALL_SCRIPT",
+ type => "=s",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return undef; },
+ },
+ {
+ name => "PKG_FORMAT",
+ type => "",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return GetPkgFormat(); },
+ },
+ {
+ name => "PKG_OS_TAG",
+ type => "",
+ hash_src => \%cmd_hash,
+ validate_sub => undef,
+ default_sub => sub { return GetOsTag(); },
+ },
+ );
+
+ {
+ my @cmd_opts =
+ map { $_->{opt} =~ y/A-Z_/a-z-/; $_; } # convert the opt named to lowercase to make command line options
+ map { { opt => $_->{name}, opt_s => $_->{type} } } # create a new hash with keys opt, opt_s
+ grep { $_->{type} } # get only names which have a valid type
+ @cmd_args;
+
+ my $help_func = sub {
+ print "Usage: $0 \n";
+ print "Supported options: \n";
+ print " --" . "$_->{opt}$_->{opt_s}\n" foreach (@cmd_opts);
+ exit(0);
+ };
+
+ if ( !GetOptions( \%cmd_hash, ( map { $_->{opt} . $_->{opt_s} } @cmd_opts ), help => $help_func ) )
+ {
+ print Die("wrong commandline options, use --help");
+ }
+ }
+
+ print "=========================================================================================================\n";
+ LoadConfiguration($_) foreach (@cmd_args);
+ print "=========================================================================================================\n";
+}
+
+
+sub _SanitizePkgList($)
+{
+ my $list = shift;
+
+ my $san_list = "";
+ foreach my $entry ( @{$list} )
+ {
+ $entry =~ s/\s//g;
+ $entry =~ s/\/|/g;
+ $entry =~ s/[|][|]*/|/g;
+
+ my @comp = split( /[|]/, $entry );
+
+ my $san_entry = "";
+ foreach my $comp_entry (@comp)
+ {
+ # abc-2.5 -> $pkn
+ # abc-2.5>=2.1.0-1 -> $pkn$cmp$ver
+ # abc-2.5(>=2.1.0-1) -> $pkn($cmp$ver)
+ if ( $comp_entry =~ m/^([^>=<]+)([>=<]*)(.*)$/ )
+ {
+ my $pkn = $1;
+ my $cmp = $2;
+ my $ver = $3;
+
+ $pkn =~ s/[(]$//;
+ $ver =~ s/[)]$//;
+
+ my $no_add_os_tag = 1
+ if ( $ver =~ s/[!]$// );
+
+ my $san_comp = "";
+
+ if ($pkn)
+ {
+ $san_comp = $pkn;
+
+ if ( $cmp && $ver )
+ {
+ my $tag = ( !$no_add_os_tag && $ver =~ m/[-][^-]*$/ ) ? ".$CFG{PKG_OS_TAG}" : "";
+
+ if ( $CFG{PKG_FORMAT} eq "deb" )
+ {
+ $cmp = ">>" if ( $cmp eq ">" );
+ $cmp = "<<" if ( $cmp eq "<" );
+ $cmp = "=" if ( $cmp eq "==" );
+
+ $san_comp .= " (" . $cmp . " " . $ver . "$tag)";
+ }
+ if ( $CFG{PKG_FORMAT} eq "rpm" )
+ {
+ $cmp = ">" if ( $cmp eq ">>" );
+ $cmp = "<" if ( $cmp eq "<<" );
+ $cmp = "=" if ( $cmp eq "==" );
+
+ $san_comp .= " " . $cmp . " " . $ver . "$tag";
+ }
+ }
+ }
+
+ $san_entry .= ( $san_entry && $san_comp ? " | " : "" ) . $san_comp
+ if ( $CFG{PKG_FORMAT} eq "deb" );
+ $san_entry .= ( $san_entry && $san_comp ? " or " : "" ) . $san_comp
+ if ( $CFG{PKG_FORMAT} eq "rpm" );
+ }
+ }
+
+ $san_list .= ( $san_list && $san_entry ? ", " : "" ) . $san_entry;
+ }
+
+ return $san_list;
+}
+
+
+sub Build()
+{
+ System( "rm", "-f", $_ ) foreach glob("$CFG{OUT_DIST_DIR}/$CFG{PKG_OS_TAG}/$CFG{PKG_NAME}_*");
+ System( "rm", "-f", $_ ) foreach glob("$CFG{OUT_DIST_DIR}/$CFG{PKG_OS_TAG}/$CFG{PKG_NAME}-*.rpm");
+
+ System( "rm", "-rf", "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/" );
+ System( "mkdir", "-p", "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/" );
+ System( "mkdir", "-p", "$CFG{OUT_DIST_DIR}/$CFG{PKG_OS_TAG}/" );
+
+ my $pkg_pre_install_list = "";
+ my $pkg_post_install_list = "";
+ if ( defined $CFG{PKG_POST_INSTALL_SCRIPT}) {
+ open FILE, "$CFG{PKG_POST_INSTALL_SCRIPT}" or die "Couldn't open postinst file: $!";
+ $pkg_post_install_list = join("", );
+ close FILE;
+ }
+ if ( defined $CFG{PKG_PRE_INSTALL_SCRIPT}) {
+ open FILE, "$CFG{PKG_PRE_INSTALL_SCRIPT}" or die "Couldn't open preinst file: $!";
+ $pkg_pre_install_list = join("", );
+ close FILE;
+ }
+
+ if ( $CFG{PKG_FORMAT} eq "rpm" )
+ {
+ System( "cp", "-a", "$GLOBAL_PATH_TO_SCRIPT_DIR/default-template/rpm", "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/" );
+ System( "cp", "-a", "$CFG{CFG_DIR}/rpm", "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/SPECS" ) if ( -d "$CFG{CFG_DIR}/rpm" );
+ }
+ elsif ( $CFG{PKG_FORMAT} eq "deb" )
+ {
+ System( "cp", "-a", "$GLOBAL_PATH_TO_SCRIPT_DIR/default-template/debian", "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/" );
+ System( "cp", "-a", "$CFG{CFG_DIR}/debian", "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/" ) if ( -d "$CFG{CFG_DIR}/debian" );
+ }
+ else
+ {
+ Die("Unknown PACKAGING format");
+ }
+
+ find(
+ {
+ wanted => sub {
+ my $tpl_file = $_;
+ if ( -f $tpl_file && $tpl_file =~ /[.]in$/ )
+ {
+ s/[.]in$// for ( my $new_file = $tpl_file );
+
+ open( FDr, "<", "$tpl_file" );
+ open( FDw, ">", "$new_file" );
+
+ while ( my $line = )
+ {
+ {
+ my $pkg_install_list =
+ ( $CFG{PKG_FORMAT} eq "deb" && $tpl_file =~ /install[.]in/ )
+ ? join( "\n", map { $_ =~ s,^/,,; $_ } @{ $CFG{PKG_INSTALLS} } )
+ : join( "\n", @{ $CFG{PKG_INSTALLS} } );
+
+ $line =~ s/[@][@]PKG_INSTALLS[@][@]/$pkg_install_list/g;
+ }
+ $line =~ s/[@][@]PKG_POST_INSTALL[@][@]/$pkg_post_install_list/g;
+ $line =~ s/[@][@]PKG_PRE_INSTALL[@][@]/$pkg_pre_install_list/g;
+ $line =~ s/[@][@]PKG_NAME[@][@]/$CFG{PKG_NAME}/g;
+ $line =~ s/[@][@]PKG_RELEASE[@][@]/$CFG{PKG_RELEASE}/g;
+ $line =~ s/[@][@]PKG_OS_TAG[@][@]/$CFG{PKG_OS_TAG}/g;
+ $line =~ s/[@][@]PKG_VERSION[@][@]/$CFG{PKG_VERSION}/g;
+ $line =~ s/[@][@]PKG_SUMMARY[@][@]/$CFG{PKG_SUMMARY}/g;
+ $line =~ s/[@][@]PKG_CREATION_DATE[@][@]/$PKG_CREATION_DATE/g;
+ $line =~ s/[@][@]PKG_DEPENDS[@][@]/@{[_SanitizePkgList($CFG{PKG_DEPENDS})]}/g;
+ $line =~ s/[@][@]PKG_PRE_DEPENDS[@][@]/@{[_SanitizePkgList($CFG{PKG_PRE_DEPENDS})]}/g;
+ $line =~ s/[@][@]PKG_PROVIDES[@][@]/@{[_SanitizePkgList($CFG{PKG_PROVIDES})]}/g;
+ $line =~ s/[@][@]PKG_CONFLICTS[@][@]/@{[_SanitizePkgList($CFG{PKG_CONFLICTS})]}/g;
+ $line =~ s/[@][@]PKG_OBSOLETES[@][@]/@{[_SanitizePkgList($CFG{PKG_OBSOLETES})]}/g;
+ $line =~ s/[@][@]PKG_REPLACES[@][@]/@{[_SanitizePkgList($CFG{PKG_REPLACES})]}/g;
+
+ if ( $line =~ m/^\s*[A-Za-z][A-Za-z_0-9-]*\s*[:](\s*,*\s*)*$/ ) # drop lines with empty headers
+ {
+ }
+ else
+ {
+ print FDw $line;
+ }
+ }
+
+ close(FDr);
+ close(FDw);
+
+ unlink($tpl_file);
+ }
+ },
+ },
+ "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}"
+ );
+
+ System( "make", "-f", "$CFG{CFG_DIR}/$CFG{PKG_NAME}/Makefile", "PKG_NAME=$CFG{PKG_NAME}", "PKG_STAGE_DIR=$CFG{OUT_STAGE_DIR}/$CFG{PKG_NAME}", "stage" )
+ if ( -f "$CFG{CFG_DIR}/$CFG{PKG_NAME}/Makefile" );
+
+ System( "ant", "-f", "$CFG{CFG_DIR}/$CFG{PKG_NAME}/build.xml", "-DPKG_NAME=$CFG{PKG_NAME}", "-DPKG_STAGE_DIR=$CFG{OUT_STAGE_DIR}/$CFG{PKG_NAME}", "stage" )
+ if ( -f "$CFG{CFG_DIR}/$CFG{PKG_NAME}/build.xml" );
+
+ if ( $CFG{PKG_FORMAT} eq "rpm" )
+ {
+ my @pkg_type_opts = ("-ba");
+ @pkg_type_opts = ("-bb") if ( $CFG{OUT_TYPE} eq "binary" );
+ @pkg_type_opts = ("-bs") if ( $CFG{OUT_TYPE} eq "source" );
+
+ System( "mv", "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/rpm/1.spec", "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/rpm/$CFG{PKG_NAME}.spec" );
+ System( "mkdir", "-p", "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/BUILDROOT/" );
+
+ System( "cp", "-a", $_, "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/BUILDROOT/@{[basename $_]}" ) foreach glob("$CFG{OUT_STAGE_DIR}/$CFG{PKG_NAME}/*");
+
+ {
+ System( "rpmbuild", "-v", "--define", "_topdir $CWD/$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}", "--buildroot=$CWD/$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/BUILDROOT/", @pkg_type_opts, "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/rpm/$CFG{PKG_NAME}.spec" );
+ }
+
+ print "\n\n";
+ print "=========================================================================================================\n";
+ System( "mv", "-v", $_, "$CFG{OUT_DIST_DIR}/$CFG{PKG_OS_TAG}/" ) foreach glob("$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/SRPMS/*.rpm");
+ System( "mv", "-v", $_, "$CFG{OUT_DIST_DIR}/$CFG{PKG_OS_TAG}/" ) foreach glob("$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/RPMS/*/*.rpm");
+ print "=========================================================================================================\n";
+ }
+ elsif ( $CFG{PKG_FORMAT} eq "deb" )
+ {
+ my @pkg_type_opts = ( "-uc", "-us" );
+ push( @pkg_type_opts, "-b" ) if ( $CFG{OUT_TYPE} eq "binary" );
+ push( @pkg_type_opts, "-S" ) if ( $CFG{OUT_TYPE} eq "source" );
+ open(my $fd, ">>$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/debian/rules");
+ print $fd "override_dh_strip: \n";
+ print $fd " cp -r \$\$(pwd)/opt/zimbra/onlyoffice/documentserver/server/DocService/docservice \$\$(pwd)/debian/zimbra-onlyoffice/opt/zimbra/onlyoffice/documentserver/server/DocService/docservice \n";
+ print $fd "override_dh_strip_nondeterminism: \n";
+ print $fd "override_dh_shlibdeps: \n";
+ print $fd "override_dh_builddeb:\n";
+ print $fd " dh_builddeb -- -Zgzip\n";
+ close($fd);
+
+ System( "cp", "-a", $_, "$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}/@{[basename $_]}" ) foreach glob("$CFG{OUT_STAGE_DIR}/$CFG{PKG_NAME}/*");
+
+ {
+ chdir("$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}");
+ print "$CWD \n";
+ System( "dpkg-buildpackage", @pkg_type_opts );
+ chdir($CWD);
+ }
+
+ print "\n\n";
+ print "=========================================================================================================\n";
+ System( "mv", "-v", $_, "$CFG{OUT_DIST_DIR}/$CFG{PKG_OS_TAG}/" ) foreach glob("$CFG{OUT_TEMP_DIR}/$CFG{PKG_NAME}_*.*");
+ print "=========================================================================================================\n";
+ }
+ else
+ {
+ Die("Unknown PACKAGING format");
+ }
+}
+
+sub SelfTest()
+{
+ if ( $CFG{PKG_FORMAT} eq "DEB" )
+ {
+ assert(
+ _SanitizePkgList( [ "abc-3.4(>=4.4)", "def-6.7(>6.6-1)", "def-6.7(>6.6-1!)", "ghi(=7.0)", "jkl", "aaa | bbb | perl(Carp) >= 3.2" ] ),
+ "abc-3.4 (>= 4.4), def-6.7 (>> 6.6-1.$CFG{PKG_OS_TAG}), def-6.7 (>> 6.6-1), ghi (= 7.0), jkl, aaa | bbb | perl(Carp) (>= 3.2)"
+ );
+ }
+
+ if ( $CFG{PKG_FORMAT} eq "RPM" )
+ {
+ assert(
+ _SanitizePkgList( [ "abc-3.4(>=4.4)", "def-6.7(>6.6-1)", "def-6.7(>6.6-1!)", "ghi(=7.0)", "jkl", "aaa | bbb | perl(Carp) >= 3.2" ] ),
+ "abc-3.4 >= 4.4, def-6.7 > 6.6-1.$CFG{PKG_OS_TAG}, def-6.7 > 6.6-1, ghi = 7.0, jkl, aaa or bbb or perl(Carp) >= 3.2"
+ );
+ }
+}
+
+
+sub main()
+{
+ Init();
+ SelfTest();
+ Build();
+}
+
+main();
diff --git a/scripts/postinst.sh b/scripts/postinst.sh
new file mode 100755
index 000000000..053b0f07f
--- /dev/null
+++ b/scripts/postinst.sh
@@ -0,0 +1,21 @@
+if [ -f /opt/zimbra/onlyoffice/bin/jq ]; then
+ chmod +x /opt/zimbra/onlyoffice/bin/jq
+fi
+
+if [ -f /opt/zimbra/onlyoffice/bin/zmonlyofficeconfig ]; then
+ chmod +x /opt/zimbra/onlyoffice/bin/zmonlyofficeconfig
+fi
+
+if [ -f /opt/zimbra/onlyoffice/bin/process_id.json.bak ]; then
+ mv -f /opt/zimbra/onlyoffice/bin/process_id.json.bak /opt/zimbra/onlyoffice/bin/process_id.json
+ /opt/zimbra/onlyoffice/bin/zmonlyofficeconfig
+fi
+
+if [ -f /opt/zimbra/onlyoffice/bin/process_id.json ]; then
+ chmod 775 /opt/zimbra/onlyoffice/bin/process_id.json
+ chown zimbra:zimbra /opt/zimbra/onlyoffice/bin/process_id.json
+fi
+
+if [ -d /opt/zimbra/onlyoffice ]; then
+ chown -R zimbra:zimbra /opt/zimbra/onlyoffice/
+fi
diff --git a/scripts/preinst.sh b/scripts/preinst.sh
new file mode 100755
index 000000000..8d5fcb257
--- /dev/null
+++ b/scripts/preinst.sh
@@ -0,0 +1,5 @@
+if [ -f /opt/zimbra/onlyoffice/bin/process_id.json ]; then
+ cp -af /opt/zimbra/onlyoffice/bin/process_id.json /opt/zimbra/onlyoffice/bin/process_id.json.bak
+ chmod 775 /opt/zimbra/onlyoffice/bin/process_id.json.bak
+ chown zimbra:zimbra /opt/zimbra/onlyoffice/bin/process_id.json.bak
+fi