Router Wi-Fi Password Change & Display V5

##Script

The Jscript functions contain a lot of variables at the very top that you need to set. Most of them are self-explanatory.

The script also supports running a simple BAT file or a more complex BAT file. By default, the simple BAT file is preferred and used, and code for the complex BAT file is disabled (commented out).


Name: WiFi
Handler: wifi
Script:

var nowDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");

var minPWlength = 8;

// BAT file settings, the BAT file and PLINK should be in the same Path
var batDrive = 'D:';
var batPath  = "D:/Programs/POS/router/";
var batFile  = "WIFIchange.bat"; // complex BAT
	batFile  = 'WIFIexec.bat';   // simple BAT
var batLog   = "WIFIchange.txt";
var batRes   = "WIFIresult.txt";
var batHidden = true;

// ROUTER setings
var rHost = '192.168.1.1';
var rPort = '22';

// these settings are arbitrary, but are used as part of the Task Name and Identifier
var rName = 'RouterJV';
var rType = 'Trendnet TEW812DRU';

// router firmware dictates which commands to issue in the BAT file
var rFirmware = 'AsusMerlin-WRT'; // restart wireless service
var rFirmware = 'DD-WRT'; // reboot the router

// generally, the username via SSH for DD-WRT firmware is 'root', while other firmware uses 'admin'
var rUser = rFirmware=='DD-WRT' ? 'root' : 'admin';

// we can use a Password or Keyfile to login to the Router
var rPass = 'myrouterpassword';
var rKey  = 'myrouterprivatekey.ppk';


// Task Default parameters
var userName = 'Admin';
var taskType = 'WiFi';
var taskName = '';
var ident = ''
var isCompleted = '';
var customData = [];
var content = '';
var state = '';

// updates WiFi Task
function setPW(pw) {

	// get current PW from DB
	var SQL = "SELECT [Id],[Name],[Value] FROM [ProgramSettingValues] WHERE [Name]='WiFiPW'";
	var res = sql.Exec(SQL);
	var	wifipwDB = res[0].split(',');
		wifipwDB = wifipwDB[2];
	
	// check input parm for value
	pw = typeof(pw)=='undefined' || pw=='' ? wifipwDB : pw;
	
	// check PW length
	if (pw.length < minPWlength) {
		var errmsg = "!!! ERROR !!!\r\nPassword is less than "+minPWlength+" characters!";
		throwError('setPW',taskType,taskName,ident,errmsg,true);
		return -1;
	}
	
	// check PW for illegal characters
	var iChars = '{}[]:;=$%&*';
	for (var c=0; c<iChars.length; c++) {
		var foundChar = pw.indexOf(iChars[c]) > -1 ? true : false;
		if (foundChar) {
			var errmsg = "!!! ERROR !!!\r\nPassword contains illegal character: '"+iChars[c]+"'";
			throwError('setPW',taskType,taskName,ident,errmsg,true);
			return -1;
			break;
		}
	}
	
	//dlg.ShowMessage("Changing Password to:\r\n"+pw);


	
	// execute Router commands -- simple BAT
	// this is the PREFERRED method since it is easier to parse and handle results or errors in JS than in BAT
	var batResult = execRouter(pw,rHost,rPort,rUser,rPass,rKey,rFirmware,batDrive,batPath,batLog,batRes);
	if (batResult != 0) {
		return -1;
	}


	/*
	// execute BAT file -- complex BAT
	// this is NOT the preferred method since it is much more difficult to parse and handle results or errors in BAT files than it is in JS
	var batResult = execBAT(pw,rHost,rPort,rUser,rPass,rKey,rFirmware,batDrive,batPath,batLog,batRes);
	if (batResult != 0) {
		return -1;
	}
	*/
	


	// if Router Commands were executed without errors, then update Task data
	
	// get incomplete Tasks
	isCompleted = 'false';
	var wifi = gqlEXEC(getTasks(taskType,isCompleted));
	//return wifi;
	// {"data":{"tasks":[]}}
	// {"data":null,"errors":[{"message":"Error trying to resolve getTasks.","locations":[{"line":0,"column":0}]}]}
	wifi = JSON.parse(wifi);

	if (wifi.errors) {
		var errmsg = "!!! ERROR !!!\r\ngetTasks()\r\n" + wifi.errors[0].message;
		throwError('setPW',taskType,taskName,ident,errmsg,true);
		return -1;
	}
	
	
	
	// complete previous (incomplete) Tasks
	var taskCount = wifi.data.tasks.length;
	if (taskCount > 0) {
		isCompleted = 'true';
		for (var t=0; t<taskCount; t++) {
			var cident  = wifi.data.tasks[t].identifier;
			var wifi = gqlEXEC(updateTaskByIdentifier([taskType], [cident], isCompleted));
		}
	}



	// add NEW Task
	var pw1 = pw;
	var pw2 = pw;
	var pw3 = pw;

	taskName = rName + ' ' + rType + ' ' + rHost;
	ident    = taskName.replace(/ /g,'_') + '_' + nowDate;
	isCompleted  = '';
	customData   = [];
	customData.push({name:"Id",value:ident});
	customData.push({name:"rName",value:rName});
	customData.push({name:"rHost",value:rHost});
	customData.push({name:"rType",value:rType});
	customData.push({name:"rFirmware",value:rFirmware});
	customData.push({name:"pw1",value:pw1});
	customData.push({name:"pw2",value:pw2});
	customData.push({name:"pw3",value:pw3});

	isCompleted = 'false';
	var wifi = gqlEXEC(addTasks([taskType],[taskName],isCompleted,customData,userName));
	
	// set current PW in DB
	var SQL = "UPDATE [ProgramSettingValues] SET [Value]='"+pw+"' WHERE [Name]='WiFiPW'";
	var res = sql.Exec(SQL);

	// execute Automation Command for any post-process Actions
	cmd.Execute('WIFI Update Password RESULT:0');

	return 0;
}

function execRouter(pw,rHost,rPort,rUser,rPass,rKey,rFirmware,batDrive,batPath,batLog,batRes) {

	// this function executes a very simple BAT file that invokes PLINK to run commands on the Router
	
	// 2.4 GHz band, passwords for networks 1-3
	var pw24_1=pw;
	var pw24_2=pw;
	var pw24_3=pw;
	
	// 5.0 GHz band, passwords for networks 1-3
	var pw50_1=pw;
	var pw50_2=pw;
	var pw50_3=pw;

	// array of error keywords
	var rErrors = ['ERROR','denied','refused'];
	
	// 2.4 GHz band, NVRAM network variables for networks 1-3
	var rGUEST24net1="wl0.1_wpa_psk";
	var rGUEST24net2="wl0.2_wpa_psk";
	var rGUEST24net3="wl0.3_wpa_psk";
	
	// 5.0 GHz band, NVRAM network variables for networks 1-3
	var rGUEST50net1="wl1.1_wpa_psk";
	var rGUEST50net2="wl1.2_wpa_psk";
	var rGUEST50net3="wl1.3_wpa_psk";

	// commands to show current passwords, commit changes, restart, and reboot
	var cShowNets="nvram show | grep wl..._wpa_psk | sort | sed 's/wl/\\r\\nwl/g'";
	var cCommitNVRAM="nvram commit";
	var cRESTARTwifi="service restart_wireless";
	var cREBOOT="reboot";
	
	// 2.4 GHz band commands for setting passwords for networks 1-3
	var cSetNet24_1="nvram set "+rGUEST24net1+"="+pw24_1;
	var cSetNet24_2="nvram set "+rGUEST24net2+"="+pw24_2;
	var cSetNet24_3="nvram set "+rGUEST24net3+"="+pw24_3;
	
	// 5.0 GHz band commands for setting passwords for networks 1-3
	var cSetNet50_1="nvram set "+rGUEST50net1+"="+pw50_1;
	var cSetNet50_2="nvram set "+rGUEST50net2+"="+pw50_2;
	var cSetNet50_3="nvram set "+rGUEST50net3+"="+pw50_3;


	// check to verify batFile exists
	var batcheck = file.ReadFromFile(batPath+batFile);
		batcheck = batcheck.length < 10 ? false : true;

	// check to verify Key File exists
	var keyfile = file.ReadFromFile(batPath+rKey);
	var bKey = keyfile.length < 500 ? "NO" : rKey;



	// build array of commands that we want to execute
	var batParms = [];
	var batSteps = [];
	
	var commonParms = bKey+" "+rHost+" "+rPort+" "+rUser+" "+rPass+" "+batDrive+" "+batPath+" "+batRes;
	
	batSteps.push("Current Passwords");
	batParms.push(commonParms +" "+'"'+cShowNets+'"');
	
	batSteps.push("Setting Password "+rGUEST24net1+"="+pw24_1);
	batParms.push(commonParms +" "+'"'+cSetNet24_1+'"');
	
	batSteps.push("Setting Password "+rGUEST50net1+"="+pw50_1);
	batParms.push(commonParms +" "+'"'+cSetNet50_1+'"');
	
	batSteps.push("Commit");
	batParms.push(commonParms +" "+'"'+cCommitNVRAM+'"');
	
	batSteps.push("New Passwords");
	batParms.push(commonParms +" "+'"'+cShowNets+'"');
	
	batSteps.push("Restarting ("+(rFirmware=='DD-WRT' ? cREBOOT : cRESTARTwifi)+")");
	batParms.push(commonParms +" "+'"'+(rFirmware=='DD-WRT' ? cREBOOT : cRESTARTwifi)+'"');
	


	// start logging
	var filewrite = file.AppendToFile(batPath+batLog,"\r\n==================================================================\r\n\r\n");

	var filewrite = file.AppendToFile(batPath+batLog,"--- WIFI PW Change BEG ---------- "+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")+"\r\n");
	var filewrite = file.AppendToFile(batPath+batLog,"NAME    : "+rName+"\r\n");
	var filewrite = file.AppendToFile(batPath+batLog,"HOST    : "+rHost+"\r\n");
	var filewrite = file.AppendToFile(batPath+batLog,"PORT    : "+rPort+"\r\n");
	var filewrite = file.AppendToFile(batPath+batLog,"TYPE    : "+rType+"\r\n");
	var filewrite = file.AppendToFile(batPath+batLog,"FIRM    : "+rFirmware+"\r\n");
	var filewrite = file.AppendToFile(batPath+batLog,"KEYFILE : "+bKey+"\r\n");
	var filewrite = file.AppendToFile(batPath+batLog,"BATFILE : "+batFile+"\r\n\r\n");
	
	if (!batcheck) {
		var errmsg = 'batFile ['+batPath+batFile+'] does not exist!';
		var filewrite = file.AppendToFile(batPath+batLog,errmsg+"\r\n");
		throwError('execRouter() ['+batResult+']',taskType,taskName,ident,errmsg,true);
		return -1;
	}

	// execute the BAT file using batParms[] array
	for (var p=0; p<batParms.length; p++) {
		if (batHidden) {
			var batResult = file.Starter(batPath+batFile).With(batParms[p]).WorkOn(batPath).Hidden.ShellExecute();
		} else {
			var batResult = file.Starter(batPath+batFile).With(batParms[p]).WorkOn(batPath).ShellExecute();
		}
		
		// the BAT file directs results for each command to a Result File, so we read it to find out what happened and check for errors
		var opres = file.ReadFromFile(batPath+batRes);
			opres = opres.split("\r\n");
			
		// build some output to append to the Log
		var lines = '';
		for (var o=0; o<opres.length; o++) {
			// get rid of empty lines in the Result file, and clean some garbage
			lines += opres[o]=='' || (opres[o].indexOf('size') > -1) ? '' : opres[o].replace(' bytes ','').replace(' left','').replace(/\([0-9]+\)/g,'') + "\r\n";
		}
		
		// write info to the Log, including the Step and cleaned Result File content
		var filewrite = file.AppendToFile(batPath+batLog,batSteps[p]+" ----------\r\n");
		var filewrite = file.AppendToFile(batPath+batLog,lines+"\r\n\r\n");
		
		// iterate error keywords array to check if our Result File contained any errors and terminate the process if any errors found
		for (var e=0; e<rErrors.length; e++) {
			if (lines.indexOf(rErrors[e]) > -1) {
				var filewrite = file.AppendToFile(batPath+batLog,"FAILED\r\n")
				var filewrite = file.AppendToFile(batPath+batLog,"--- WIFI PW Change END ---------- "+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")+"\r\n");
				throwError('execRouter() ['+batResult+']',taskType,taskName,ident,lines,true);
				return -1;
			}
		}
	}
	
	// if everything executed properly, Log the Success
	var filewrite = file.AppendToFile(batPath+batLog,"SUCCESS\r\n")
	var filewrite = file.AppendToFile(batPath+batLog,"--- WIFI PW Change END ---------- "+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")+"\r\n");

	return 0;
}

function execBAT(pw,rHost,rPort,rUser,rPass,rKey,rFirmware,batDrive,batPath,batLog,batRes) {

	// this function executes a somewhat complex BAT file that invokes PLINK to run commands on the Router
	// error checking and logging is all handled in the BAT file

	var batParms = pw+' '+rHost+' '+rPort+' '+rUser+' '+rPass+' '+rKey+' '+rFirmware+' '+batDrive+' '+batPath+' '+batLog+' '+batRes;
	
	var batResult = file.Starter(batPath+batFile).With(batParms).WorkOn(batPath).ShellExecute();

	if (batResult != 0) {
		var errmsg = file.ReadFromFile(batPath+batRes);
		throwError('WIFIchange.bat ['+batResult+']',taskType,taskName,ident,errmsg,true);
		return -1;
	}
	
	return 0;
}


function throwError(func,taskType,taskName,taskIdent,parm,halt) {

	// function to handle errors in a common manner
	
	func = typeof(func)==='undefined' || func=='' ? 'unknown' : func;
	taskType = typeof(taskType)==='undefined' || taskType=='' ? 'unknown' : taskType;
	taskName = typeof(taskName)==='undefined' || taskName=='' ? 'unknown' : taskName;
	taskIdent = typeof(taskIdent)==='undefined' || taskIdent=='' ? 'unknown' : taskIdent;
	parm = typeof(parm)==='undefined' || parm=='' ? 'unknown' : parm;
	halt = typeof(halt)==='undefined' || halt=='' ? true : halt;

	var errmsg = 'ERROR in '+func;
	errmsg += "\r\n"+'taskType: '+taskType;
	errmsg += "\r\n"+'taskName: '+taskName;
	errmsg += "\r\n"+'taskIdent: '+taskIdent;
	errmsg += "\r\n"+'parm: '+parm;
	errmsg += "\r\n"+'halt: '+halt;
	
	//dlg.AskQuestion('<size 12><font Consolas>'+errmsg+'</font></size>',"Ok");

	// execute Automation Command for any post-process Actions
	cmd.Execute("WIFI Update Password RESULT:"+errmsg);

	return -1;
}




// main GraphQL Execute Function
function gqlEXEC(query, callback) {
	//return query;
    var data = gql.Exec(query);  // returns JSON as String
    var dobj = JSON.parse(data); // converts JSON String to Object
    return data;
};

// Query for addTasks
function addTasks(taskTypes,taskNames,isCompleted,customData,userName,content,state) {
    var q = '';
        q+= 'mutation m{';
        for (var t=0; t<taskNames.length; t++) {
            var taskType = taskTypes[t];
            var taskName = taskNames[t];
            q += 'm'+t+': ';
            q+= 'addTask(';
            q+= 'task:{';
            q+= 'taskType:"'+taskType+'"';
            q+= ',name:"'+taskName+'"';
            q+= ',isCompleted:'+isCompleted;
            q+= ',userName:"'+userName+'"';
            q+= typeof(content)==='undefined' ? '' : ',content:' + '"'+content+'"';
            q+= typeof(state)==='undefined' ? '' : ',state:' + '"'+state+'"';
            q+= ',customData:[';
            if (customData) {
                for (var d=0; d<customData.length; d++) {
                    q+= (d==0 ? '' : ',');
                    q+= '{name:"'+customData[d].name+'",value:"'+customData[d].value+'"}';
                }
            }
            q+= ']';
            q+= '}';
            q+= ')';
            q+= '{id,name,identifier,content,isCompleted,userName,customData{name,value}}';
            q += ((t+1) != taskNames.length ? ', ' : '');
        }
        q+= '}';
    return q;
};

// Query for getTasks
function getTasks(taskType, completedFilter, nameLike, startFilter, endFilter, contentLike, fieldFilter, stateFilter, callback) {
    var q = '';
        q+= '{tasks:getTasks(';
        q+= 'taskType:"'+taskType+'"';
        q+= (startFilter ? ',startDate:"'+startFilter+'"' : '');
        q+= (endFilter ? ',endDate:"'+endFilter+'"' : '');
        q+= (completedFilter!='' ? ',isCompleted:'+completedFilter : '');
        q+= (nameLike ? ',nameLike:"'+nameLike+'"' : '');
        q+= (contentLike ? ',contentLike:"'+contentLike+'"' : '');
        q+= (stateFilter ? ',state:"'+stateFilter+'"' : '');
        q+= (fieldFilter ? ',customFields:[{name:"'+fieldFilter.name+'",value:"'+fieldFilter.value+'"}]' : '');
        q+= ')';
        q+= '{id,isCompleted,identifier,name,state,content,contentText,customData{name,value},stateLog{state,start,end},stateDuration{state,duration},startDate,endDate,userName}';
        q+= '}';
    return q;
};

// Query for updateTask (by identifier and taskType)
function updateTaskByIdentifier(taskTypes, taskIdents, isCompleted, taskName, customData, content, state){
    var q = 'mutation m {';
    for (var t=0; t<taskIdents.length; t++) {
        var taskIdent = taskIdents[t];
        var taskType = taskTypes[t];
        q += 'm'+t+': updateTask(';
        q += 'identifier:"'+taskIdent+'"';
        q += ', taskType:"'+taskType+'"';
        q += ', task:{';
        q += 'taskType:"'+taskType+'"';
        q += (isCompleted!='' ? ',isCompleted:'+isCompleted : '');
        q += (taskName ? ', name:"'+taskName+'"' : '');
        q += content ? ',content:"'+content+'"' : '';
        q += state ? ',state:"'+state+'"' : '';
        q += ',customData:[';
        if (customData) {
            for (var d=0; d<customData.length; d++) {
                q+= (d==0 ? '' : ',');
                q+= '{name:"'+customData[d].name+'",value:"'+customData[d].value+'"}';
            }
        }
        q+= ']';
        q += '}';
        q += ')';
        q+= '{id,isCompleted,identifier,name,state,content,contentText,customData{name,value},stateLog{state,start,end},stateDuration{state,duration},startDate,endDate,userName}';
        //q += '}';
        q += ((t+1) != taskIdents.length ? ', ' : '');

    }
    	q += '}';
    return q;
};