Currently you are storing something like this in your engine_layers script parameter:
"new GridLayer()|" +
"new CatalogLayer(new NamedStarsCatalog())|" +
"new CatalogLayer(new NGCICCatalog())|" +
"new CatalogLayer(new TychoCatalog())|" +
"new CatalogLayer(new PGCCatalog())"Then your script runs the following code to recreate a set of annotation layers:
var layerConstructors = layersStr.split( "|" );
this.layers = new Array;
for ( var l = 0; l < layerConstructors.length; l++ )
{
this.layers[l] = eval( layerConstructors[l] );
this.layers[l].SetId( l );
this.layers[l].LoadParameters();
}
Although this solution is indeed elegant and powerful (for example, it is not restricted to a finite and fixed set of layer and catalog objects), it in inherently insecure. As a somewhat 'dramatic' example, somebody could change one of these parameters to remove all files in the user's home directory, and your script would execute the corresponding code efficiently in the first call to eval()
You can replace this system with a simple parser. Many people would use XML to implement this functionality, but XML tends to generate a lot of unnecessary overhead in these cases, just to be 'fancy'. Another cleaner option would be JSON. Personally I tend to favor even simpler adhoc solutions. Suppose that instead of the above parameter we had the following stored in engine_layers:
"GRID|CATALOG:NAMED_STARS|CATALOG:NGCIC|CATALOG:TYCHO|CATALOG:PGC"Now instead of your eval()-based code we can implement the following:
var layerConstructors = layersStr.split( "|" );
this.layers = new Array;
for ( var l = 0; l < layerConstructors.length; l++ )
{
var constructorParameters = layerConstructors[l].split( ":" );
if ( constructorParameters.length < 1 )
throw new Error( "Missing layer constructor in parameter." );
switch ( constructorParameters[0] )
{
case "GRID":
if ( constructorParameters.length > 1 )
throw new Error( "Invalid layer constructor: The GRID constructor takes no parameters." );
this.layers[l] = new GridLayer;
break;
case "CATALOG":
if ( constructorParameters.length != 2 )
throw new Error( "Invalid layer constructor: The CATALOG constructor takes one parameter." );
var catalog;
switch ( constructorParameters[1] )
{
case "NAMED_STARS": catalog = new NamedStarsCatalog(); break;
case "NGCIC": catalog = new NGCICCatalog(); break;
case "TYCHO": catalog = new TychoCatalog(); break;
case "PGC": catalog = new PGCCatalog(); break;
default:
throw new Error( "Invalid layer constructor: Unknown catalog type." );
}
this.layers[l] = new CatalogLayer( catalog );
break;
default:
throw new Error( "Invalid layer constructor: Unknown layer type." );
}
this.layers[l].SetId( l );
this.layers[l].LoadParameters();
}
with the corresponding changes to generate the parameter contents. The above code is secure, since there is no way to force it to do anything unwanted. It just generates your annotation layers with basic error checking, and cannot execute anything else. It is considerably uglier and not too elegant, but hey, enforcing security has always had a price