/* * (c) Copyright Ascensio System SIA 2010-2024 * * 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-6 Ernesta Birznieka-Upish * 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 sockjs = require('sockjs'); const nodehun = require('nodehun'); const logger = require('./../../Common/sources/logger'); const utils = require('./../../Common/sources/utils'); const fs = require('fs'); const co = require('co'); const cfgSockjs = require('config').get('services.CoAuthoring.sockjs'); const languages = require('./languages'); const allLanguages = languages.allLanguages; const path = require('path'); const arrExistDictionaries = {}; const pathDictionaries = require('config').get('SpellChecker.server.dictDir'); const arrDictionaries = {}; function spell(type, word, id) { return new Promise(function (resolve, reject) { let dict = null; if (arrDictionaries[id]) { dict = arrDictionaries[id]; } else { if (arrExistDictionaries[id]) { let pathTmp = path.join(pathDictionaries, allLanguages[id], allLanguages[id] + '.'); dict = arrDictionaries[id] = new nodehun(pathTmp + 'aff', pathTmp + 'dic'); } } if (dict) { if ('spell' === type) { // use setImmediate because https://github.com/nodejs/node/issues/5691 dict.spell(word).then(isCorrect => { return setImmediate(resolve, isCorrect); }); } else if ('suggest' === type) { dict.suggest(word).then(suggestions => { return setImmediate(resolve, suggestions); }); } } else { return setImmediate(resolve, true); } }); } exports.install = function (server, callbackFunction) { 'use strict'; utils.listFolders(pathDictionaries, true).then(values => { return co(function* () { let lang; for (let i = 0; i < values.length; ++i) { lang = languages.sToId(path.basename(values[i])); if (-1 !== lang) { arrExistDictionaries[lang] = 1; } } yield spell('spell', 'color', 0x0409); callbackFunction(); }); }); const sockjs_echo = sockjs.createServer(cfgSockjs); sockjs_echo.on('connection', function (conn) { if (!conn) { logger.error('null == conn'); return; } conn.on('data', function (message) { try { let data = JSON.parse(message); switch (data.type) { case 'spellCheck': spellCheck(conn, data.spellCheckData); break; } } catch (e) { logger.error('error receiving response: %s', e); } }); conn.on('error', function () { logger.error('On error'); }); conn.on('close', function () { logger.info('Connection closed or timed out'); }); sendData(conn, {type: 'init', languages: Object.keys(arrExistDictionaries)}); }); function sendData(conn, data) { conn.write(JSON.stringify(data)); } function spellCheck(conn, data) { return co(function* () { let promises = []; for (let i = 0, length = data.usrWords.length; i < length; ++i) { promises.push(spell(data.type, data.usrWords[i], data.usrLang[i])); } yield Promise.all(promises).then(values => { data['spell' === data.type ? 'usrCorrect' : 'usrSuggest'] = values; }); sendData(conn, {type: 'spellCheck', spellCheckData: data}); }); } sockjs_echo.installHandlers(server, { prefix: '/doc/[0-9-.a-zA-Z_=]*/c', log: function (severity, message) { //TODO: handle severity logger.info(message); } }); }; exports.spellSuggest = function (type, word, lang, callbackFunction) { return co(function* () { callbackFunction(yield spell(type, word, lang)); }); };