require("luamods/command")
require("luamods/layout")
require("luamods/cgi")
require("config/network_conf")

userLevel = db.getPriv(layout.username) or 1

if (userLevel == 1) then
    buttonControl = " disabled"
    inputControl = " readonly"
    scriptControl = "//"
else
    buttonControl = ""
    inputControl = ""
    scriptControl = ""
end

header = layout.getHeader()
footer = layout.getFooter()

if (cgi.post.submitButton == "Save and Apply") and (userLevel ~= 1) then
    num = 0
    newConf = "### "..network_conf.portforward_config.." generated by webconfig\n"
    for count = 1,10 do
        if (cgi.post["interface"..count] ~= nil) and (cgi.post["name"..count] ~= nil) and (cgi.post["protocol"..count] ~= nil)
        and (cgi.post["inPort"..count] ~= nil) and (cgi.post["outIP"..count] ~= nil) 
        and (cgi.post["outIP"..count] ~= nil) then
            name = cgi.post["name"..count]
            interface = cgi.post["interface"..count]
            protocol = cgi.post["protocol"..count]
            inPort = cgi.post["inPort"..count]
            outIP = cgi.post["outIP"..count]
            outPort = cgi.post["outPort"..count]
            if (interface ~= "") and (name ~= "") and (protocol ~= "") and (inPort ~= "")
            and (outIP ~= "") and (outPort ~= "") then
                num = num + 1
                newConf = newConf .. "\n#SERVNAME " .. name .. "\n"
                newConf = newConf .. interface .. "\t" .. protocol .. "\t" .. inPort .. "\t" .. outIP .. "\t" .. outPort .. "\n"
            end
        end
    end
    newConf = newConf .. "\n### end of file\n"
    command.writefile(network_conf.portforward_config, newConf)
    
    num = 0
    newConf = "### "..network_conf.ipforward_config.." generated by webconfig\n"
    for count = 1,10 do
        if (cgi.post["ipname"..count] ~= nil) 
        and (cgi.post["extIP"..count] ~= nil)
        and (cgi.post["lanIP"..count] ~= nil) then
            command.log("Posting "..cgi.post["ipname"..count])
            ipname = cgi.post["ipname"..count]
            extip = cgi.post["extIP"..count]
            lanip = cgi.post["lanIP"..count]
            if (name ~= "") and (extip~= "") and (lanip ~= "") then
                num = num + 1
                newConf = newConf .. "\n#SERVNAME " .. ipname .. "\n"
                newConf = newConf .. extip .. "\t" ..lanip .. "\n"
            end
        end
    end
    newConf = newConf .. "\n### end of file\n"
    command.writefile(network_conf.ipforward_config, newConf)

    saved = 1
    updateResults = command.ex(network_conf.portforward_restart)
end

conf = command.ex("cat "..network_conf.portforward_config) or ""
ipconf = command.ex("cat "..network_conf.ipforward_config) or ""

services = {}
for name,b in conf:gmatch("#SERVNAME%s+([^\n]*)\n%s*([^\n]*)\n") do
    interface, protocol, inPort, outIP, outPort = b:match("[^#]*"):match("%s*(.-)%s+%s*(.-)%s+([0-9%:_]+)%s+(.-)%s+([0-9%:_]+)")
    if (interface ~= nil) and (protocol ~= nil) and (inPort ~= nil) and (outIP ~= nil) and (outPort ~= nil) then
        service = {}
        service.name = name
        service.interface = interface 
        service.protocol = protocol
        service.inPort = inPort
        service.outIP = outIP
        service.outPort = outPort
        table.insert(services, service)
    end
end

ipservices = {}
for name,b in ipconf:gmatch("#SERVNAME%s+([^\n]*)\n%s*([^\n]*)\n") do
    extIP, lanIP = b:match("[^#]*"):match("%s*([0-9%.]+)%s+([0-9%.]+)")
    if (extIP ~= nil) and (lanIP ~= nil) then
        service = {}
        service.name = name
        service.extIP = extIP
        service.lanIP = lanIP
        table.insert(ipservices, service)
    end
end


content = [[
                    <div id="info">
                        <div style="background:url(images/network.png); background-size:32px; background-repeat:no-repeat; background-position: 20px center;">
                            <center><h1>Network - Firewall and Port Forwarding</h1></center>
                        </div>
                    </div>
]]

if (conf == "") then
    -- Bail on error
    content = content .. [[
                    <div id="info">
                        <center>
                            <h2><img src="images/warning.png"/> Cannot read config file</h2>
                            The Blackwall configuration file "]]..network_conf.portforward_config..[[" is missing or unreadable.
                        </center>
                    </div>
]]
    print(header..content..footer)
    return     
else
    if (userLevel == 1) then
        content = content .. [[
                    <center><b>Note:</B> Editing this section requires administrator privileges.</center><br>
]]                    
    end    
    content = content .. [[
                    <script language="Javascript" type="text/javascript">

                        function trim1 (str) {
                            return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
                        }
                        
                        function testInt (str)
                        {
                            return (/^(\d|\d\:\d)+$/.test(str));
                           
                        }
                        
                        function ValidateIPaddress(inputText)  
                        {  
                            var ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
                            if (inputText.match(ipformat))
                            {  
                                return true;  
                            }  
                            else  
                            {  
                                return false;  
                            }  
                        }
                        
                        function validateForm(form)
                        {
                            var div = document.getElementById("serviceDiv");
                            if (form.getAttribute('submitted')) return false;
                            var inputs = div.getElementsByTagName("input");
                            var loop;
                            var errors = 0;
                            for (loop = 0; loop < 10; loop++)
                            {
                                var warn = document.getElementById("problem_"+loop);
                                if (warn)
                                {
                                    warn.parentNode.removeChild(warn);
                                }
                            }
                            errors = 0;
                            // Hey ya'll, lets look at them service names.
                            for (loop = 0; loop < inputs.length; loop+=5)
                            {
                                inputs[loop].value = trim1(inputs[loop].value);
                                // This here entry ain't completely blank, pardner.
                                if ((inputs[loop].value != "") || (inputs[loop+1].value != "") || (inputs[loop+2].value != "") || (inputs[loop+3].value != ""))
                                {
                                    // Do names first
                                    if (inputs[loop].value == "")
                                    {
                                        errors++;
                                        var warn = document.createElement("span");
                                        warn.id = "problem_"+loop/5;
                                        warn.innerHTML = " <img src='images/warning.png' alt='Blank service name' title='Blank service name'/>";
                                        inputs[loop].parentNode.appendChild(warn);
                                    }
                                }
                            }
                            if (errors)
                            {
                                alert("One or more services have blank service names.\nPlease fix the names for the indicated services.");
                                return false;
                            }
                            // Now let's focus our attention to them thar incoming ports. Yep.
                            for (loop = 0; loop < inputs.length; loop+=5)
                            {
                                if ((inputs[loop].value != "") || (inputs[loop+1].value != "") || (inputs[loop+2].value != "") || (inputs[loop+3].value != "") )
                                {
                                    if (!testInt(inputs[loop+2].value))
                                    {
                                        errors++;
                                        var warn = document.createElement("span");
                                        warn.id = "problem_"+loop/5;
                                        warn.innerHTML = " <img src='images/warning.png' alt='Invalid incoming port' title='Invalid incoming port'/>";
                                        inputs[loop].parentNode.appendChild(warn);
                                    }
                                }
                            }
                            if (errors)
                            {
                                alert("One or more services have invalid or blank incoming ports.\nPlease fix the ports for the indicated services.");
                                return false;
                            }
                            // IP ADDRESSSEEEEEEESSS
                            for (loop = 0; loop < inputs.length; loop+=5)
                            {
                                if ((inputs[loop].value != "") || (inputs[loop+1].value != "") || (inputs[loop+2].value != "") || (inputs[loop+3].value != ""))
                                {
                                    console.log("loop: " + inputs[loop].value);
                                    console.log("loop+1: " + inputs[loop+1].value);
                                    console.log("loop+2: " + inputs[loop+2].value);
                                    console.log("loop+3: " + inputs[loop+3].value);
                                    console.log("loop+4: " + inputs[loop+4].value);
                        
                                    if (!ValidateIPaddress(inputs[loop+3].value))
                                    {
                                        errors++;
                                        var warn = document.createElement("span");
                                        warn.id = "problem_"+loop/5;
                                        warn.innerHTML = " <img src='images/warning.png' alt='Invalid IP address' title='Invalid IP address'/>";
                                        inputs[loop].parentNode.appendChild(warn);
                                    }
                                }
                            }
                            if (errors)
                            {
                                alert("One or more services have invalid or blank destination IP addresses.\nPlease fix the IP addresses for the indicated services.");
                                return false;
                            }
                            // Destination ports, finally.
                            for (loop = 0; loop < inputs.length; loop+=5)
                            {
                                if ((inputs[loop].value != "") || (inputs[loop+1].value != "") || (inputs[loop+2].value != "") || (inputs[loop+3].value != ""))
                                {
                                    if (!testInt(inputs[loop+4].value))
                                    {
                                        errors++;
                                        var warn = document.createElement("span");
                                        warn.id = "problem_"+loop/5;
                                        warn.innerHTML = " <img src='images/warning.png' alt='Invalid destination port' title='Invalid destination port'/>";
                                        inputs[loop].parentNode.appendChild(warn);
                                    }
                                }
                            }
                            if (errors)
                            {
                                alert("One or more services have invalid or blank destination ports.\nPlease fix the ports for the indicated services.");
                                return false;
                            }
                            form.setAttribute('submitted','true');
                            return true;
                        }                    
                    
                        function removeField(node,field)
                        {            
                            node.parentNode.parentNode.removeChild(node.parentNode);
                            var field_area = document.getElementById(field+"_list");
                            var all_inputs = field_area.getElementsByTagName("input"); //Get all the input fields in the given area.
                            var all_selects = field_area.getElementsByTagName("select"); //Get all the input fields in the given area.
                            var loop;
                            if (field == "service")
                            {
               

                              for (loop = 0; loop < all_inputs.length; loop+=5)
                              {
                                  all_inputs[loop].name = "name"+((loop/5)+1);
                                   all_inputs[loop+1].name = "interface"+((loop/5)+1);                                  
                                  all_inputs[loop+2].name = "inPort"+((loop/5)+1);
                                  all_inputs[loop+3].name = "outIP"+((loop/5)+1);
                                  all_inputs[loop+4].name = "outPort"+((loop/5)+1);
                              }
                              for (loop = 0; loop < all_selects.length; loop++)
                              {
                                  all_selects[loop].name = "protocol"+(loop+1);
                              }
                            }
                            else
                            {
                              for (loop = 0; loop < all_inputs.length; loop+=3)
                              {
                                  all_inputs[loop].name = "ipname"+((loop/3)+1);
                                  all_inputs[loop+1].name = "extIP"+((loop/3)+1);
                                  all_inputs[loop+2].name = "lanIP"+((loop/3)+1);
                              }
                            }
                        }
                        
                        //Add more fields dynamically.
                        function addField(field, limit)
                        {
                            if (!document.getElementById) return; //Prevent older browsers from getting any further.
                            var field_area = document.getElementById(field+"_list");
                            var all_selects = field_area.getElementsByTagName("select"); //Get all the input fields in the given area.
                            var all_inputs = field_area.getElementsByTagName("input"); //Get all the input fields in the given area.
                           
                            var count = all_selects.length;
                            if (field != "service")
                            {
                               count = all_inputs.length/3;
                            }
                            if(count+1 > limit && limit > 0) return;
                            
                            if(document.createElement)
                            { //W3C Dom method.
                                var li = document.createElement("li");
                                if (field == "service")
                                {
                                 li.innerHTML = 
                                    "<input type=\"text\" name=\"name"+(count+1)+"\" value=\"\" style=\"width: 150px;\" placeholder=\"Service name\"/> "
                                    + "<input type=\"text\" name=\"interface"+(count+1)+"\" value=\"\" style=\"width: 40px;\" placeholder=\"Interface\"/> "
                                    +"<select name=\"protocol"+(count+1)+"\">"
                                        +"<option value=\"tcp\">TCP</option>"
                                        +"<option value=\"udp\">UDP</option>"
                                    +"</select> "
                                    +"<input type=\"text\" name=\"inPort"+(count+1)+"\" value=\"\" style=\"width: 100px;\" placeholder=\"Incoming port\"/> "
                                    +"<input type=\"text\" name=\"outIP"+(count+1)+"\" value=\"\" style=\"width: 140px;\" placeholder=\"Destination IP\"/> "
                                    +"<input type=\"text\" name=\"outPort"+(count+1)+"\" value=\"\" style=\"width: 100px;\" placeholder=\"Destination Port\"/> "
                                    +"<a style=\"cursor:pointer;color:blue;\" onclick=\"removeField(this, '"+field+"');\"> <img src=\"images/trash.png\" alt=\"Delete\" title=\"Delete\"/></a>";
                                }
                                else
                                {
                                  li.innerHTML = 
                                  "<input type=\"text\" name=\"ipname"+(count+1)+"\" value=\"\" style=\"width: 150px;\" placeholder=\"Service name\"/> "
                                  +"<input type=\"text\" name=\"extIP"+(count+1)+"\" value=\"\" style=\"width: 160px;\" placeholder=\"External/WAN IP\"/> "
                                  +"<input type=\"text\" name=\"lanIP"+(count+1)+"\" value=\"\" style=\"width: 160px;\" placeholder=\"Internal/LAN IP\"/> "
                                  +"<a style=\"cursor:pointer;color:blue;\" onclick=\"removeField(this, '"+field+"');\"> <img src=\"images/trash.png\" alt=\"Delete\" title=\"Delete\"/></a>";
                                }
                                field_area.appendChild(li);
                            }
                            else
                            {       //Older Method
                            }
                        }
                        
                    </script>
]]
if (saved == 1) and (updateResults ~= "") then
    content = content ..[[
                    <h3>Update Results</h3>
                    <pre CLASS="formLayoutfull">
]]..updateResults..[[
                    </pre>
]]
end

content = content .. [[
                    <h3>Add and remove port forwarding services to the firewall configuration.</h3>
                    <div class="formLayoutfull">
                         <form action="network_pf.lua" method="post" onsubmit="return validateForm(this);"> 
                            <h3>List of port forwarding services</h3>
                            <div id="serviceDiv">
                            <ol id="service_list">
]]
    if (#(services) > 0) then
        for i = 1, #(services)  do
            if (i > 0) then
                content = content .. [[
                                <li>
                                    <input type="text" name="name]]..i..[[" value="]]..services[i].name..[[" style="width: 150px;" placeholder="Service name"]]..inputControl..[[/>
                                    <input type="text" name="interface]]..i..[[" value="]]..services[i].interface..[[" style="width: 40px;" placeholder="Interface"]]..inputControl..[[/>
                                    <select name="protocol]]..i..[["]]..buttonControl..[[>
                                        <option value="tcp" ]]
                if (services[i].protocol == "tcp") then content = content .. [[selected ]] end
                content = content .. [[>TCP</option>
                                        <option value="udp" ]]
                if (services[i].protocol == "udp") then content = content .. [[selected ]] end                                        
                content = content .. [[>UDP</option>
                                    </select>
                                    <input type="text" name="inPort]]..i..[[" value="]]..services[i].inPort..[[" style="width: 100px;" placeholder="Incoming port"]]..inputControl..[[/>
                                    <input type="text" name="outIP]]..i..[[" value="]]..services[i].outIP..[[" style="width: 140px;" placeholder="Destination IP"]]..inputControl..[[/>
                                    <input type="text" name="outPort]]..i..[[" value="]]..services[i].outPort..[[" style="width: 100px;" placeholder="Destination Port"]]..inputControl..[[/>
                                    <a style="cursor:pointer;color:blue;" onclick="]]..scriptControl..[[removeField(this, 'service');"> <img src="images/trash.png" alt="Delete" title="Delete"/></a>
                                </li>
]]
            end
        end
    end
    content = content .. [[
                            </ol>
                            </div>
                            <input type="button" value="Add Service" onclick="addField('service', 10);"]]..buttonControl..[[/>
                            <br><br><hr><br>
]]                            
content = content .. [[
                        <h3>List of IP forwarding services</h3>
                            <div id="ipDiv">
                            <ol id="ip_list">
]]
                                    
    if (#(ipservices) > 0) then
        for i = 1, #(ipservices)  do
            if (i > 0) then
                content = content .. [[
                                <li>
                                    <input type="text" name="ipname]]..i..[[" value="]]..ipservices[i].name..[[" style="width: 150px;" placeholder="Service name"]]..inputControl..[[/>
                                    <input type="text" name="extIP]]..i..[[" value="]]..ipservices[i].extIP..[[" style="width: 160px;" placeholder="External/WAN IP"]]..inputControl..[[/>
                                    <input type="text" name="lanIP]]..i..[[" value="]]..ipservices[i].lanIP..[[" style="width: 160px;" placeholder="Internal/LAN IP"]]..inputControl..[[/>
                                    <a style="cursor:pointer;color:blue;" onclick="]]..scriptControl..[[removeField(this, 'ip');"> <img src="images/trash.png" alt="Delete" title="Delete"/></a>
                                </li>
]]
            end
        end
    end


 content = content .. [[
                            </ol>
                            </div>
                            <input type="button" value="Add Service" onclick="addField('ip', 10);"]]..buttonControl..[[/>
                            <br><br><hr><br>
]]

if (saved == 1) then
    content = content .. [[
                            <b><img src="images/ok.png"/> Changes saved.</b><br><br>
]]
end
content = content .. [[
                            <input type="submit" name="submitButton" value="Save and Apply"]]..buttonControl..[[/>
                        </form>
                    </div>
        
]]
    content = content .. [[
                    <script>
                        function toggleVis(target)
                        {
                            if (target.style.display == "none")
                            {
                                target.style.display = "inline-block";
                            }
                            else
                            {
                                target.style.display = "none";
                            }
                            return false;
                        }
                    </script>
                    <br><img src="images/magnify.png"/> <a href="javascript:void(0)" onclick="toggleVis(document.getElementById('pf'));">View ]]..network_conf.portforward_config..[[</a></a><br>
        
                    <div id="pf" style="display: none;">
                        <pre class="formLayoutfull">
                        <!-- opkg start -->
]]..conf..[[
                        <!-- opkg end -->
                        </pre>
                    </div>
                    <br><img src="images/magnify.png"/> <a href="javascript:void(0)" onclick="toggleVis(document.getElementById('ippf'));">View ]]..network_conf.ipforward_config..[[</a></a><br>
        
                    <div id="ippf" style="display: none;">
                        <pre class="formLayoutfull">
                        <!-- opkg start -->
]]..ipconf..[[
                        <!-- opkg end -->
                        </pre>
                    </div>
]]  
end

print(header..content..footer)
