Comcast Business SMCD3G Port Forward Autoconfig

Easily/Automatically create port forwards, without having to sit and wait for each change to apply. Created to while diagnosing an issue with SMCD3G that caused it to forgets all configured port forwards, which seems to be a common problem for some xfinity customers as well.

اعتبارا من 27-03-2017. شاهد أحدث إصدار.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

ستحتاج إلى تثبيت إضافة مثل Stylus لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتتمكن من تثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

(لدي بالفعل مثبت أنماط للمستخدم، دعني أقم بتثبيته!)

// ==UserScript==
// @name         Comcast Business SMCD3G Port Forward Autoconfig
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Easily/Automatically create port forwards, without having to sit and wait for each change to apply. Created to while diagnosing an issue with SMCD3G that caused it to forgets all configured port forwards, which seems to be a common problem for some xfinity customers as well. 
// @author       [email protected]
// @include      /https?:\/\/10\.\d{1,3}\.\d{1,3}\.\d{1,3}\/user/\index\.asp/
// @grant        none
// ==/UserScript==

// [ "Application Name", Public port start, Public port end, Internal port Start, "Protocall", "Forward IP"]
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.onmouseup(); 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;},timeout=500,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,timeout,tries - 1); }, timeout);
    }
    else {
        errcallback(xpath);
    }
}




var rollTimeout=null;
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) {
        clearTimeout(rollTimeout);
        rollTimeout=setTimeout(function(){ rollmsg(elm,msg); },200);
    }
}
var origTitle="";
function SavingBanner() {
    dbg("Activating Saving Banner");
    var doc = getElementByXpath('//frame[@src="main.asp"]').contentDocument;
    var title  = getElementByXpath('//div[@id="body-container"]/h2',doc);
    origTitle=title.textContent;
    title.textContent="SAVING ! ! !";
    // I am not sure why this makes the title 3 lines long, but I like it!
    title.style.width*=2;
    clearTimeout(rollTimeout);
    rollmsg(title,"");
}
function SetApplyBanner() {
    dbg("Apply Btn now calls Saving Banner");
    var doc = getElementByXpath('//frame[@src="main.asp"]').contentDocument;
    var form  = getElementByXpath('//form',doc);
    var apply = getElementByXpath('.//div[@id="submit"]/input',form);
    var origOnClick = apply.onclick;
    //apply.onclick=function() {rollTimeout=setTimeout(function(){ SavingBanner(); },200); origOnClick.apply(null,arguments);};
    apply.onmouseup=function() { rollTimeout=setTimeout(function(){ SavingBanner(); },200);};
    // Intercept Alerts
    var awin = getElementByXpath('//frame[@src="main.asp"]').contentWindow;
    var oldAlert=window.alert;
    awin.alert = function() {
        dbg("got Alert!");
        clearTimeout(rollTimeout);
        oldAlert.apply(awin,arguments);
    };
}
function SetApplyBannerLoop() {
    CheckLoop('//form//div[@id="submit"]/input',SetApplyBanner,function() { setTimeout(SetApplyBannerLoop,5000); },5000);
}
SetApplyBannerLoop();

var port_i = 0;
function itteratePorts() {
    if (port_i < Ports.length) {
        var port = Ports[port_i];
        port_i++;
        var forwardPort = function() {
            SetApplyBanner();
            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 + 1));
                    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();