3

I'm still very new to JavaScript (not to coding though), so feel free to nit-pick and moron-map things for me.

I've attempted to create something that will accept user input. If the first character is an exclamation point, it'll attempt to create an object with that name and run the "action" method of that object. Else it'll treat it like regular text (for now an alert)

<script type="text/javascript">
function GetInput(input){

    // Trim the spaces off the beginning and end
    input = input.trim();

    if(input.charAt(0) != "!"){
        // Just some normal text
        alert(input);

        return true;
    }

/* Cut off the exclamation point, replace multiple spaces with one,
 * and get the arguments if any. args[0] = the command. */

    var args = input.substr(1).replace(/\s{2,}/g, " ").split(" ");

// Make sure the function is an object with a method named "action"
    if(eval("typeof "+args[0]+";") === "function"
        && eval("typeof "+args[0]+".prototype.action;") === "function"){

        eval("var command = new "+args[0]+"();");

        command.action(args);
    }else{
        alert('"'+args[0]+'" is not a command.');
    }

    return true;
}
</script>

The only problem I'm noticing with this so far is the eval statements. I know I could use a switch/case and ditch eval all together, or even make an array containing the names of the allowed functions and compare the input with that array prior to eval, but I'm sure there's got to be a better way.

I just want to be able to make the object and method and not update anything (which I believe is one of the major uses of of duck-typing?). Is this possible without eval? If not, is there an easy way to sanitize input for strings to avoid things like "!eval(alert('u b haxed'))" or "!a;alert('u b haxed')"?

Thanks in advance

PeeHaa
  • 71,436
  • 58
  • 190
  • 262
  • possible duplicate of [dynamic object construction in javascript?](http://stackoverflow.com/questions/3871731/dynamic-object-construction-in-javascript) – zerkms Dec 03 '12 at 01:12

1 Answers1

3

You should use eval only once to get the function, then do everything with it in a variable.

var args = input.substr(1).split(/\s+/);
var fn = eval(args[0]);
if (typeof fn == 'function' && typeof fn.prototype.action == 'function') {
    var command = new fn();
    command.action(args);
} else {
    alert('"'+args[0]+'" could not be evaluated to a valid command.');
}

return true;

If those constructors are global variables, you also can access them as a property of the window object:

var fn = window[ args[0] ];
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Shouldn't use `eval` even once as `args[0]` comes from user input. `windows[args[0]]` is much safer. – TwiNight Dec 03 '12 at 01:30
  • Between this answer and TwiNight's comment I got exactly what I needed. Thank you two so much. –  Dec 03 '12 at 01:36
  • @TwiNight: Not in general, as every user could manually execute malicious code in his own browser. `window[args[0]]` won't have any side effects, but is more restricted. Depends on what the user needs and how experienced he is. – Bergi Dec 03 '12 at 01:58
  • True, but `eval` is generally depreciated. – TwiNight Dec 03 '12 at 02:12
  • @TwiNight `eval` is nowhere near deprecated. The only problem with `eval` is that by inexperienced users it's often misused and abused. There are many scenario's where using `eval` is perfectly acceptable, and no security risks are imposed. Deprecated means that they actually want to remove the feature from the language, but for backward compatibility they keep it around. However there's a good chance they will remove it in a future version. This is not the case with `eval`. – Aidiakapi Dec 14 '12 at 12:57
  • @Aidiakapi: It adds too much quirks to the language, so it is for example not allowed in strict mode. Everywhere you need to parse & execute code, you still could use the `Function` constructor. – Bergi Dec 14 '12 at 13:11
  • @Bergi What's your source for `eval` not working in strict mode? From the MDN strict mode article I quote: `eval of strict mode code does not introduce new variables into the surrounding scope`. That doesn't mean it doesn't allow it. In fact, the code sample below that shows `eval` being used in strict mode. It doesn't add quirks to the language. It's just abused by users. The `Function` constructor (obviously) creates a function from a string of code. It doesn't execute the code. It depends on the way you use it, but `Function` can be just as much abused as `eval`. – Aidiakapi Dec 17 '12 at 08:52