// ==UserScript==
// @name Comcast Buisness Gateway PortForward Autoconfig
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Easily/Automaticly create port forwards, without having to sit and wait for each change to apply. Created because my comcast modem randomly forgets it's port forwards, an it seems to be a common problem.
// @author [email protected]
// @include /https?:\/\/10\.\d{1,3}\.\d{1,3}\.\d{1,3}\/user/\index\.asp/
// @grant none
// ==/UserScript==
var Ports = [
["HTTP", 80,80,80,'TCP','10.0.0.12'],
["HTTPS", 443,443,443,'TCP','10.0.0.12'],
["IKEv2-NAT-T", 4500,4500,4500,'UDP','10.0.0.12'],
["IPSEC-IKE", 500,500,500,'UDP','10.0.0.12'],
["IPSEC-ESP", 50,50,50,'ESP','10.0.0.12'],
["SSH", 2222,2222,22,'TCP','10.0.0.12'],
];
function dbg(txt) {
console.log(txt);
}
function getElementByXpath(path,element=document) {
return document.evaluate(path, element, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
function getElementsByXpath(xpath, parent=document)
{
let results = [];
let query = document.evaluate(xpath,
parent,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i=0, length=query.snapshotLength; i<length; ++i) {
results.push(query.snapshotItem(i));
}
return results;
}
function SelectOptionByText(selectList,val) {// class = ffSelectWrapper
dbg("Got Select List");
dbg(selectList);
for (var i=0;i<selectList.options.length;i++) {
dbg("Scanning option " + selectList.options[i].value.trim() + " with id " + i + " for option " + val);
if (selectList.options[i].textContent.trim() == val) {
dbg("Selected option " + val + " with id " + i);
selectList.selectedIndex=i;
break;
}
}
}
function SelectOption(selectList,val) {// class = ffSelectWrapper
dbg("Got Select List");
dbg(selectList);
for (var i=0;i<selectList.options.length;i++) {
dbg("Scanning option " + selectList.options[i].value.trim() + " with id " + i + " for option " + val);
if (selectList.options[i].value.trim() == val) {
dbg("Selected option " + val + " with id " + i);
selectList.selectedIndex=i;
break;
}
}
}
function SetPortForwarding(name,start,stop,local_start,type,ip) {
dbg("Setting up a port forward");
var doc = getElementByXpath('//frame[@src="main.asp"]').contentDocument;
var form = getElementByXpath('//form[@name="PortForwardForm"]',doc);
var f_name = getElementByXpath('.//input[@id="app_X_name"]',form);
var f_start = getElementByXpath('.//input[@id="app_X_public_start"]',form);
var f_stop = getElementByXpath('.//input[@id="app_X_public_end"]',form);
var f_local_start = getElementByXpath('.//input[@id="app_X_private_start"]',form);
var f_type = getElementByXpath('.//select[@id="app_X_protocol"]',form);
var f_ip = getElementByXpath('.//input[@id="app_X_ip"]',form);
var f_submit = getElementByXpath('.//div[@id="submit"]/input',form);
f_name.value=name;
f_start.value=start;
f_stop.value=stop;
f_local_start.value=local_start;
// Update local stop via keyup event
f_local_start.onkeyup();
SelectOptionByText(f_type,type);
f_ip.value=ip;
setTimeout(function() { f_submit.click(); },500);
}
function AddNewForward() {
var doc = getElementByXpath('//frame[@src="main.asp"]').contentDocument;
var form = getElementByXpath('//form[@name="ServiceA"]',doc);
var add_new = getElementByXpath('.//input[@name="add_new"]',form);
add_new.click();
}
function CheckLoop(xpath,callback,thenCall=function(){return null;},tries=1000,errcallback=function(e_xpath) { dbg("Failed to find form '" + e_xpath + "' within tries limit."); }) {
var doc = getElementByXpath('//frame[@src="main.asp"]').contentDocument;
var elm = getElementByXpath(xpath,doc);
if ( elm ) {
callback();
thenCall();
}
else if (tries !== 0) {
dbg("Didn't see element");
dbg(tries);
setTimeout(function() { CheckLoop(xpath,callback,thenCall,tries - 1); }, 500);
}
else {
errcallback(xpath);
}
}
// Intercept Alerts
var oldAlert=window.alert;
window.alert = function() {
dbg("got Alert!");
oldAlert.apply(window,arguments);
};
function rollmsg(elm,msg) {
var NowMsg=elm.textContent;
NowMsg=NowMsg.substring(1,NowMsg.length)+NowMsg.substring(0,1);
elm.textContent = NowMsg;
if (elm.offsetParent !== null) {
setTimeout(function(){ rollmsg(elm,msg); },200);
}
}
var port_i = 0;
function itteratePorts() {
if (port_i < Ports.length) {
var port = Ports[port_i];
port_i++;
var forwardPort = function() {
SetPortForwarding.apply(null,port);
var doc = getElementByXpath('//frame[@src="main.asp"]').contentDocument;
var title = getElementByXpath('//div[@id="body-container"]/h2',doc);
title.textContent="SAVING ! ! !";
// I am not sure why this makes the title 3 lines long, but I like it!
title.style.width*=2;
rollmsg(title,"");
};
var addNewForward = function() {
var doc = getElementByXpath('//frame[@src="main.asp"]').contentDocument;
var form = getElementByXpath('//form[@name="ServiceA"]',doc);
var add_new_btn = getElementByXpath('.//input[@name="add_new"]',form);
var edit_btn = getElementByXpath('.//input[@name="edit"]',form);
var rows = getElementsByXpath('.//tr[td/@class="content"]',form);
var edit = false;
dbg("Configuring Forward Named " + port[0]);
for (var r=0; r<rows.length; r++) {
var row=rows[r];
if (row.children[2].textContent === port[0] ) {
dbg("Found Existing Forward! Editing #" + r);
edit = true;
row.children[0].children[0].click();
}
}
if (edit) {
edit_btn.click();
}
else {
dbg("Creating new Forward!");
add_new_btn.click();
}
};
//CheckLoop('//form[@name="ServiceA"]',addNewForward);
//if (true) return null;
CheckLoop('//form[@name="ServiceA"]',addNewForward,function() {
CheckLoop('//form[@name="PortForwardForm"]',forwardPort,itteratePorts);
});
}
}
itteratePorts();