瀏覽代碼

refactor code to use command template and escape shell to prevent unescaped characters

Abhinav 2 年之前
父節點
當前提交
794c3bf007
共有 1 個文件被更改,包括 134 次插入13 次删除
  1. 134 13
      src/services/imageProcessor.ts

+ 134 - 13
src/services/imageProcessor.ts

@@ -8,9 +8,57 @@ import { logErrorSentry } from './sentry';
 import { isPlatform } from '../utils/main';
 import { isDev } from '../utils/common';
 import path from 'path';
+import log from 'electron-log';
+const shellescape = require('any-shell-escape');
 
 const asyncExec = util.promisify(exec);
 
+const IMAGE_MAGICK_PLACEHOLDER = 'IMAGE_MAGICK';
+const MAX_DIMENSION_PLACEHOLDER = 'MAX_DIMENSION';
+const SAMPLE_SIZE_PLACEHOLDER = 'SAMPLE_SIZE';
+const INPUT_PATH_PLACEHOLDER = 'INPUT';
+const OUTPUT_PATH_PLACEHOLDER = 'OUTPUT';
+
+const SIPS_HEIC_CONVERT_COMMAND_TEMPLATE = [
+    'sips',
+    '-s',
+    'format',
+    'jpeg',
+    INPUT_PATH_PLACEHOLDER,
+    '--out',
+    OUTPUT_PATH_PLACEHOLDER,
+];
+
+const SIPS_THUMBNAIL_GENERATE_COMMAND_TEMPLATE = [
+    'sips',
+    '-s',
+    'format',
+    'jpeg',
+    INPUT_PATH_PLACEHOLDER,
+    '-Z',
+    MAX_DIMENSION_PLACEHOLDER,
+    '--out',
+    OUTPUT_PATH_PLACEHOLDER,
+];
+
+const IMAGEMAGICK_HEIC_CONVERT_COMMAND_TEMPLATE = [
+    IMAGE_MAGICK_PLACEHOLDER,
+    INPUT_PATH_PLACEHOLDER,
+    '-quality',
+    '100%',
+    OUTPUT_PATH_PLACEHOLDER,
+];
+
+const IMAGE_MAGICK_THUMBNAIL_GENERATE_COMMAND_TEMPLATE = [
+    IMAGE_MAGICK_PLACEHOLDER,
+    '-define',
+    `jpeg:size=${SAMPLE_SIZE_PLACEHOLDER}x${SAMPLE_SIZE_PLACEHOLDER}`,
+    INPUT_PATH_PLACEHOLDER,
+    '-thumbnail',
+    `${MAX_DIMENSION_PLACEHOLDER}x${MAX_DIMENSION_PLACEHOLDER}>`,
+    OUTPUT_PATH_PLACEHOLDER,
+];
+
 function getImageMagickStaticPath() {
     return isDev
         ? 'build/image-magick'
@@ -58,17 +106,49 @@ async function runConvertCommand(
     tempInputFilePath: string,
     tempOutputFilePath: string
 ) {
+    const convertCmd = constructConvertCommand(
+        tempInputFilePath,
+        tempOutputFilePath
+    );
+    const escapedCmd = shellescape(convertCmd);
+    log.info('running convert command: ' + escapedCmd);
+    await asyncExec(escapedCmd);
+}
+
+function constructConvertCommand(
+    tempInputFilePath: string,
+    tempOutputFilePath: string
+) {
+    let convertCmd: string[];
     if (isPlatform('mac')) {
-        await asyncExec(
-            `sips -s format jpeg "${tempInputFilePath}" --out "${tempOutputFilePath}"`
-        );
+        convertCmd = SIPS_HEIC_CONVERT_COMMAND_TEMPLATE.map((cmdPart) => {
+            if (cmdPart === INPUT_PATH_PLACEHOLDER) {
+                return tempInputFilePath;
+            }
+            if (cmdPart === OUTPUT_PATH_PLACEHOLDER) {
+                return tempOutputFilePath;
+            }
+            return cmdPart;
+        });
     } else if (isPlatform('linux')) {
-        await asyncExec(
-            `${getImageMagickStaticPath()} "${tempInputFilePath}" -quality 100% "${tempOutputFilePath}"`
+        convertCmd = IMAGEMAGICK_HEIC_CONVERT_COMMAND_TEMPLATE.map(
+            (cmdPart) => {
+                if (cmdPart === IMAGE_MAGICK_PLACEHOLDER) {
+                    return getImageMagickStaticPath();
+                }
+                if (cmdPart === INPUT_PATH_PLACEHOLDER) {
+                    return tempInputFilePath;
+                }
+                if (cmdPart === OUTPUT_PATH_PLACEHOLDER) {
+                    return tempOutputFilePath;
+                }
+                return cmdPart;
+            }
         );
     } else {
         Error(`${process.platform} native heic convert not supported yet`);
     }
+    return convertCmd;
 }
 
 export async function generateImageThumbnail(
@@ -107,20 +187,61 @@ async function runThumbnailGenerationCommand(
     tempOutputFilePath: string,
     maxDimension: number
 ) {
+    const thumbnailGenerationCmd: string[] =
+        constructThumbnailGenerationCommand(
+            inputFilePath,
+            tempOutputFilePath,
+            maxDimension
+        );
+    const escapedCmd = shellescape(thumbnailGenerationCmd);
+    log.info('running thumbnail generation command: ' + escapedCmd);
+    await asyncExec(escapedCmd);
+}
+function constructThumbnailGenerationCommand(
+    inputFilePath: string,
+    tempOutputFilePath: string,
+    maxDimension: number
+) {
+    let thumbnailGenerationCmd: string[];
     if (isPlatform('mac')) {
-        await asyncExec(
-            `sips -s format jpeg -Z ${maxDimension}  "${inputFilePath}" --out "${tempOutputFilePath}" `
+        thumbnailGenerationCmd = SIPS_THUMBNAIL_GENERATE_COMMAND_TEMPLATE.map(
+            (cmdPart) => {
+                if (cmdPart === INPUT_PATH_PLACEHOLDER) {
+                    return inputFilePath;
+                }
+                if (cmdPart === OUTPUT_PATH_PLACEHOLDER) {
+                    return tempOutputFilePath;
+                }
+                if (cmdPart === MAX_DIMENSION_PLACEHOLDER) {
+                    return maxDimension.toString();
+                }
+                return cmdPart;
+            }
         );
     } else if (isPlatform('linux')) {
-        await asyncExec(
-            `${getImageMagickStaticPath()} -define jpeg:size=${
-                2 * maxDimension
-            }x${2 * maxDimension}  "${inputFilePath}"  -auto-orient   
-                -thumbnail ${maxDimension}x${maxDimension}> -gravity center -unsharp 0x.5  "${tempOutputFilePath}"`
-        );
+        thumbnailGenerationCmd =
+            IMAGE_MAGICK_THUMBNAIL_GENERATE_COMMAND_TEMPLATE.map((cmdPart) => {
+                if (cmdPart === IMAGE_MAGICK_PLACEHOLDER) {
+                    return getImageMagickStaticPath();
+                }
+                if (cmdPart === INPUT_PATH_PLACEHOLDER) {
+                    return inputFilePath;
+                }
+                if (cmdPart === OUTPUT_PATH_PLACEHOLDER) {
+                    return tempOutputFilePath;
+                }
+                if (cmdPart === SAMPLE_SIZE_PLACEHOLDER) {
+                    return (2 * maxDimension).toString();
+                }
+                if (cmdPart === MAX_DIMENSION_PLACEHOLDER) {
+                    return maxDimension.toString();
+                }
+                return cmdPart;
+            });
     } else {
         Error(
             `${process.platform} native thumbnail generation not supported yet`
         );
     }
+    return thumbnailGenerationCmd;
 }