Implement SonarCloud generic fix

This commit is contained in:
Daniel Petri Rocha 2022-07-27 20:54:16 +02:00
parent ecc8c2dd1b
commit a3935bb90a
5 changed files with 45 additions and 49 deletions

View File

@ -5,7 +5,7 @@ module.exports = {
'node': true, 'node': true,
}, },
'extends': [ 'extends': [
'eslint:recommended', 'google',
], ],
'parserOptions': { 'parserOptions': {
'ecmaVersion': 'latest', 'ecmaVersion': 'latest',

View File

@ -4,7 +4,11 @@
}, },
"shared": { "shared": {
"presDir": "/var/bigbluebutton", "presDir": "/var/bigbluebutton",
"presAnnDropboxDir": "/tmp/pres-ann-dropbox" "presAnnDropboxDir": "/tmp/pres-ann-dropbox",
"cairosvg": "/usr/bin/cairosvg",
"ghostscript": "/usr/bin/gs",
"imagemagick": "/usr/bin/convert",
"pdftocairo": "/usr/bin/pdftocairo"
}, },
"collector": { "collector": {
"pngWidthRasterizedSlides": 2560 "pngWidthRasterizedSlides": 2560

View File

@ -4,7 +4,7 @@ const fs = require('fs');
const redis = require('redis'); const redis = require('redis');
const {Worker, workerData, parentPort} = require('worker_threads'); const {Worker, workerData, parentPort} = require('worker_threads');
const path = require('path'); const path = require('path');
const {execSync} = require('child_process'); const cp = require('child_process');
const jobId = workerData; const jobId = workerData;
@ -77,7 +77,6 @@ const exportJob = JSON.parse(job);
// so it matches what was shown in the browser. // so it matches what was shown in the browser.
const extract_png_from_pdf = [ const extract_png_from_pdf = [
'pdftocairo',
'-png', '-png',
'-f', pageNumber, '-f', pageNumber,
'-l', pageNumber, '-l', pageNumber,
@ -85,9 +84,9 @@ const exportJob = JSON.parse(job);
'-singlefile', '-singlefile',
'-cropbox', '-cropbox',
pdfFile, outputFile, pdfFile, outputFile,
].join(' '); ];
execSync(extract_png_from_pdf); cp.spawnSync(config.shared.pdftocairo, extract_png_from_pdf, {shell: false});
} }
// If PNG file already available // If PNG file already available
} else if (fs.existsSync(`${presFile}.png`)) { } else if (fs.existsSync(`${presFile}.png`)) {

View File

@ -8,7 +8,7 @@ const path = require('path');
const {workerData, parentPort} = require('worker_threads'); const {workerData, parentPort} = require('worker_threads');
const [jobType, jobId, filename] = workerData; const [jobType, jobId, filename_with_extension] = workerData;
const logger = new Logger('presAnn Notifier Worker'); const logger = new Logger('presAnn Notifier Worker');
@ -27,7 +27,7 @@ async function notifyMeetingActor() {
await client.connect(); await client.connect();
client.on('error', (err) => logger.info('Redis Client Error', err)); client.on('error', (err) => logger.info('Redis Client Error', err));
const link = `${config.notifier.protocol}://${config.notifier.host}/bigbluebutton/presentation/${exportJob.parentMeetingId}/${exportJob.parentMeetingId}/${exportJob.presId}/pdf/${jobId}/${filename}.pdf`; const link = `${config.notifier.protocol}://${config.notifier.host}/bigbluebutton/presentation/${exportJob.parentMeetingId}/${exportJob.parentMeetingId}/${exportJob.presId}/pdf/${jobId}/${filename_with_extension}`;
const notification = { const notification = {
envelope: { envelope: {
name: config.notifier.msgName, name: config.notifier.msgName,
@ -59,7 +59,7 @@ async function notifyMeetingActor() {
async function upload() { async function upload() {
const callbackUrl = `http://${config.bbbWeb.host}:${config.bbbWeb.port}/bigbluebutton/presentation/${exportJob.presentationUploadToken}/upload`; const callbackUrl = `http://${config.bbbWeb.host}:${config.bbbWeb.port}/bigbluebutton/presentation/${exportJob.presentationUploadToken}/upload`;
const formData = new FormData(); const formData = new FormData();
const file = `${exportJob.presLocation}/pdfs/${jobId}/${filename}.pdf`; const file = `${exportJob.presLocation}/pdfs/${jobId}/${filename_with_extension}`;
formData.append('conference', exportJob.parentMeetingId); formData.append('conference', exportJob.parentMeetingId);
formData.append('pod_id', config.notifier.pod_id); formData.append('pod_id', config.notifier.pod_id);

View File

@ -2,7 +2,7 @@ const Logger = require('../lib/utils/logger');
const config = require('../config'); const config = require('../config');
const fs = require('fs'); const fs = require('fs');
const {create} = require('xmlbuilder2', {encoding: 'utf-8'}); const {create} = require('xmlbuilder2', {encoding: 'utf-8'});
const {execSync} = require('child_process'); const cp = require('child_process');
const {Worker, workerData, parentPort} = require('worker_threads'); const {Worker, workerData, parentPort} = require('worker_threads');
const path = require('path'); const path = require('path');
const sanitize = require('sanitize-filename'); const sanitize = require('sanitize-filename');
@ -130,12 +130,13 @@ function to_px(pt) {
// the escape-string-regexp npm package, and Pango markup. // the escape-string-regexp npm package, and Pango markup.
function escapeText(string) { function escapeText(string) {
return string return string
.replace(/[~`!.*+?%^${}()|[\]\\/]/g, '\\$&')
.replace(/-/g, '\\-')
.replace(/&/g, '\\&') .replace(/&/g, '\\&')
.replace(/'/g, '\\'') .replace(/'/g, '\\'')
.replace(/"/g, '\\"')
.replace(/>/g, '\\>') .replace(/>/g, '\\>')
.replace(/</g, '\\&lt;') .replace(/</g, '\\&lt;');
.replace(/[~`!".*+?%^${}()|[\]\\/]/g, '\\$&')
.replace(/-/g, '\\&#x2D;');
} }
function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxWidth = null) { function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxWidth = null) {
@ -144,7 +145,7 @@ function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxW
// Sticky notes need automatic line wrapping: take width into account // Sticky notes need automatic line wrapping: take width into account
// Texbox scaled by a constant factor to improve resolution at small scales // Texbox scaled by a constant factor to improve resolution at small scales
const size = textBoxWidth ? `-size ${textBoxWidth * config.process.textScaleFactor}x` : ''; const size = textBoxWidth ? ['-size', `${textBoxWidth * config.process.textScaleFactor}x`] : [];
const pangoText = `pango:"<span font_family='${font}' font='${fontSize}' color='${textColor}'>${text}</span>"`; const pangoText = `pango:"<span font_family='${font}' font='${fontSize}' color='${textColor}'>${text}</span>"`;
@ -152,19 +153,18 @@ function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxW
textAlign = justify ? 'left' : textAlign; textAlign = justify ? 'left' : textAlign;
const commands = [ const commands = [
'convert',
'-encoding', `${config.process.whiteboardTextEncoding}`, '-encoding', `${config.process.whiteboardTextEncoding}`,
'-density', config.process.pixelsPerInch, '-density', config.process.pixelsPerInch,
'-background', 'transparent', '-background', 'transparent'].concat(size,
size, [
'-define', `pango:align=${textAlign}`, '-define', `pango:align=${textAlign}`,
'-define', `pango:justify=${justify}`, '-define', `pango:justify=${justify}`,
'-define', 'pango:wrap=word-char', '-define', 'pango:wrap=word-char',
pangoText, pangoText,
path.join(dropbox, `text${id}.png`), path.join(dropbox, `text${id}.png`),
].join(' '); ]);
execSync(commands); cp.spawnSync(config.shared.imagemagick, commands, {shell: false});
} }
function get_gap(dash, size) { function get_gap(dash, size) {
@ -244,7 +244,7 @@ function getPath(annotationPoints) {
.map((strokePoint) => strokePoint.point); .map((strokePoint) => strokePoint.point);
let [max_x, max_y] = [0, 0]; let [max_x, max_y] = [0, 0];
const path = stroke.reduce( const inner_path = stroke.reduce(
(acc, [x0, y0], i, arr) => { (acc, [x0, y0], i, arr) => {
if (!arr[i + 1]) return acc; if (!arr[i + 1]) return acc;
const [x1, y1] = arr[i + 1]; const [x1, y1] = arr[i + 1];
@ -261,8 +261,7 @@ function getPath(annotationPoints) {
['M', ...stroke[0], 'Q'], ['M', ...stroke[0], 'Q'],
); );
path.join(' '); return [inner_path, max_x, max_y];
return [path, max_x, max_y];
} }
function getOutlinePath(annotationPoints) { function getOutlinePath(annotationPoints) {
@ -273,7 +272,7 @@ function getOutlinePath(annotationPoints) {
}); });
let [max_x, max_y] = [0, 0]; let [max_x, max_y] = [0, 0];
const path = stroke.reduce( const outline_path = stroke.reduce(
(acc, [x0, y0], i, arr) => { (acc, [x0, y0], i, arr) => {
const [x1, y1] = arr[(i + 1) % arr.length]; const [x1, y1] = arr[(i + 1) % arr.length];
if (x1 >= max_x) { if (x1 >= max_x) {
@ -289,10 +288,9 @@ function getOutlinePath(annotationPoints) {
['M', ...stroke[0], 'Q'], ['M', ...stroke[0], 'Q'],
); );
path.push('Z'); outline_path.push('Z');
path.join(' ');
return [path, max_x, max_y]; return [outline_path, max_x, max_y];
} }
function circleFromThreePoints(A, B, C) { function circleFromThreePoints(A, B, C) {
@ -474,10 +472,9 @@ function overlay_arrow(svg, annotation) {
function overlay_draw(svg, annotation) { function overlay_draw(svg, annotation) {
const dash = annotation.style.dash; const dash = annotation.style.dash;
const [calculated_path, max_x, max_y] = (dash == 'draw') ? getOutlinePath(annotation.points) : getPath(annotation.points);
const [path, max_x, max_y] = (dash == 'draw') ? getOutlinePath(annotation.points) : getPath(annotation.points); if (!calculated_path.length) return;
if (!path.length) return;
const shapeColor = color_to_hex(annotation.style.color); const shapeColor = color_to_hex(annotation.style.color);
const rotation = rad_to_degree(annotation.rotation); const rotation = rad_to_degree(annotation.rotation);
@ -514,7 +511,7 @@ function overlay_draw(svg, annotation) {
svg.ele('path', { svg.ele('path', {
style: `stroke:${shapeColor};stroke-width:${thickness};fill:${fill};${stroke_dasharray}`, style: `stroke:${shapeColor};stroke-width:${thickness};fill:${fill};${stroke_dasharray}`,
d: path, d: calculated_path,
transform: shapeTransform, transform: shapeTransform,
}); });
} }
@ -780,7 +777,7 @@ const exportJob = JSON.parse(job);
const annotations = fs.readFileSync(path.join(dropbox, 'whiteboard')); const annotations = fs.readFileSync(path.join(dropbox, 'whiteboard'));
const whiteboard = JSON.parse(annotations); const whiteboard = JSON.parse(annotations);
const pages = JSON.parse(whiteboard.pages); const pages = JSON.parse(whiteboard.pages);
let ghostScriptInput = ''; const ghostScriptInput = [];
// 3. Convert annotations to SVG // 3. Convert annotations to SVG
for (const currentSlide of pages) { for (const currentSlide of pages) {
@ -848,16 +845,15 @@ for (const currentSlide of pages) {
// generates with the original size in pt. // generates with the original size in pt.
const convertAnnotatedSlide = [ const convertAnnotatedSlide = [
'cairosvg',
SVGfile, SVGfile,
'--output-width', to_px(slideWidth), '--output-width', to_px(slideWidth),
'--output-height', to_px(slideHeight), '--output-height', to_px(slideHeight),
'-o', PDFfile, '-o', PDFfile,
].join(' '); ];
execSync(convertAnnotatedSlide); cp.spawnSync(config.shared.cairosvg, convertAnnotatedSlide, {shell: false});
ghostScriptInput += `${PDFfile} `; ghostScriptInput.push(PDFfile);
} }
// Create PDF output directory if it doesn't exist // Create PDF output directory if it doesn't exist
@ -867,23 +863,20 @@ if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, {recursive: true}); fs.mkdirSync(outputDir, {recursive: true});
} }
const filename = sanitize(exportJob.filename.replace(/\s/g, '_')); const filename_with_extension = `${sanitize(exportJob.filename.replace(/\s/g, '_'))}.pdf`;
const mergePDFs = [ const mergePDFs = [
'gs',
'-dNOPAUSE', '-dNOPAUSE',
'-sDEVICE=pdfwrite', '-sDEVICE=pdfwrite',
`-sOUTPUTFILE="${path.join(outputDir, `${filename}.pdf`)}"`, `-sOUTPUTFILE="${path.join(outputDir, filename_with_extension)}"`,
`-dBATCH`, `-dBATCH`].concat(ghostScriptInput);
ghostScriptInput,
].join(' ');
// Resulting PDF file is stored in the presentation dir // Resulting PDF file is stored in the presentation dir
execSync(mergePDFs); cp.spawnSync(config.shared.ghostscript, mergePDFs, {shell: false});
// Launch Notifier Worker depending on job type // Launch Notifier Worker depending on job type
logger.info(`Saved PDF at ${outputDir}/${jobId}/${filename}.pdf`); logger.info(`Saved PDF at ${outputDir}/${jobId}/${filename_with_extension}`);
kickOffNotifierWorker(exportJob.jobType, filename); kickOffNotifierWorker(exportJob.jobType, filename_with_extension);
parentPort.postMessage({message: workerData}); parentPort.postMessage({message: workerData});