在不使用eval

时间:2016-02-15 19:17:16

标签: javascript node.js

我正在编写代码以根据用户选择的图像处理操作生成缩略图,这些操作可能是用户使用lwip npm包模块选择的多个。

对于多个动作,lwip提供批处理功能,然后链接其他操作函数。我遇到的问题是用户可以选择操作函数的任何组合,并且检查所选动作的每个组合太麻烦。

所以,我已经生成了代码作为js代码字符串动态生成我需要作为函数执行而不使用可能危及应用程序安全性的eval

以下是我的代码

    'use strict';
(function(uploadhandler){

    var lwip=require('lwip'),
        imageSettingProvider=require('../data/imagesettingprovider'),
        uploadFolder='public/uploads/',
        imageManipulatorHelper=require('./imagemanipulationactions'),
        manipulatedImage='';

    uploadhandler.generateThumbnail=function(filePath,filename,ImageUploadSetting,fs){
        // compound effects
        var thumbnailPath='';

        lwip.open(filePath, function(err, image) {
            if (err) {
                console.log(err);
            }else{
                imageSettingProvider.getImageSetting(ImageUploadSetting,{},function(err,imageSettings){
                    imageSettings.forEach(function(element,index,array){
                        thumbnailPath=uploadFolder + element.folderName + '/' + filename;
                        var imageAction=element.action;
                        if(imageAction.indexOf(',')>-1){
                            var imageManipulationActions=imageAction.split(',');
                            var manipulationHtml='';
                            manipulationHtml += 'image.batch()';
                            var actionHtml='';
                            imageManipulationActions.forEach(function(actionelement,actionindex,actionarray){
                                actionHtml += uploadhandler.PerformMultipleImageManipulation(actionelement,element,actionHtml);
                            });
                            manipulationHtml += actionHtml;
                            console.log('----------------------------------------------------------------------------------------------------------');
                            manipulationHtml += '.writeFile(thumbnailPath, function(err) { if (err) throw err;});';
                            console.log(manipulationHtml);

                        }
                    });
                });
            }
        });
    };


    uploadhandler.PerformMultipleImageManipulation=function(imageAction,imageOpts,actionHtml){
        switch (imageAction){
            case "crop":
                actionHtml = '.crop(' + imageOpts.width + ',' + imageOpts.height + ')';
                break;
            case "cropbycoordinates":
                actionHtml = '.crop(' + imageOpts.cropLeftPos + ',' + imageOpts.cropTopPos + ',' + imageOpts.cropRightPos + ',' + imageOpts.cropBottomPos + ')';
                break;
            case "resize":
                actionHtml = '.resize(' + imageOpts.width + ',' + imageOpts.height + ')';
                break;
            case "resizecrop":
                actionHtml = '.resize(' + imageOpts.width + ',' + imageOpts.height + ')' + '.crop(' + imageOpts.width + ',' + imageOpts.height + ')';
                break;
            case "rotate":
                actionHtml = '.rotate(' + imageOpts.rotateDegree + ',' + imageOpts.backgroundColor + ')';
                break;
            case "blur":
                actionHtml = '.blur(' + imageOpts.blurVal + ')';
                break;
            case "scale":
                actionHtml = '.scale(' + imageOpts.scaleVal + ')';
                break;
            case "mirror":
                actionHtml = '.mirror(' + imageOpts.flipAxes + ')';
                break;
            case "fade":
                actionHtml = '.fade(' + imageOpts.fadeVal + ')';
                break;
        }
        return actionHtml;
    };

})(module.exports);

现在,当我将操纵变量记录到控制台时,它会给出:

image.batch()
.resize(480,320)
.crop(480,320)
.rotate(75,white)
.writeFile(thumbnailPath, function(err) { 
if (err) throw err;
});

现在我需要执行以上js代码字符串作为函数来生成缩略图而不使用javascript eval函数。

我尝试过使用sitepoint网站的以下方法:

// function we want to run
var fnstring = "runMe";

// find object
var fn = window[fnstring];

// is object a function?
if (typeof fn === "function") fn();

但它给了我错误" ReferenceError:未定义窗口  "

请指导我解决这个问题。

2 个答案:

答案 0 :(得分:4)

将操作提取到全局对象中,并使用每个特定函数的命名空间执行每个操作。

var helper = {};
helper.b = function() {
  console.log("foo");
}
helper.c = function() {
  console.log("bar");
}

//execute them

function execute(key) {
  try {
    helper[key]();
  } catch (e) {
    throw new Error("Function does not exist");
  }
}

execute("b");
execute("c");
execute("d");

答案 1 :(得分:0)

如果有帮助,您可以运行正则表达式替换功能。

注意:我尚未对此进行测试。

// if worried about security with eval, you may want to put functions in an object instead of using global
const myFunctions = {
    runMe: function(){/* do stuff */},
    runMe2: function(){/* do stuff */}
};

const allowedFuncs = ['runMe', 'runMe2'];
// or dynamic to entire object
const allowedFuncs = Object.keys(myFunctions);

str = str.replace(new RegExp('(''+allowedFuncs.join('|')+)\\((.*?)\\)', 'g'), (str, func, attrs) => {
    // check allowed list for added security
    if(allowedFuncs.includes(func)){
        attrs = attrs.split(',');
        myFunctions[func](...attrs); // 3 dots makes js expand array to params separated by camas
    }
    return str; // returning str replaces nothing
});