<commit_before>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace IPTables.Net.Iptables.Adapter.Client.Helper
{
    class IPTablesRestoreTableBuilder
    {
        private class Table
        {
            internal readonly HashSet<String> Chains = new HashSet<string>();
            internal readonly List<String> Commands = new List<string>();
        }
        private readonly Dictionary<String, Table> _tables = new Dictionary<String, Table>();

        public void AddChain(String table, String chain)
        {
            if (!_tables.ContainsKey(table))
            {
                _tables.Add(table, new Table());
            }
            var chainTable = _tables[table];

            if (chainTable.Chains.Contains(chain))
            {
                throw new Exception("Chain has already been added");
            }
            chainTable.Chains.Add(chain);
        }

        public void AddCommand(String table, String ruleCommand)
        {
            if (!_tables.ContainsKey(table))
            {
                _tables.Add(table, new Table());
            }
            var commandTable = _tables[table];

            //iptables-restore doesnt support ' quotes
            ruleCommand = ruleCommand.Replace('\'', '"');


            commandTable.Commands.Add(ruleCommand);
        }

        public bool WriteOutput(StreamWriter output)
        {
            foreach (var table in _tables)
            {
                output.WriteLine("*" + table.Key);

                foreach (var chain in table.Value.Chains)
                {
                    bool isInternal = false;
                    if (table.Key == "nat")
                    {
                        isInternal = (chain == "PREROUTING" || chain == "POSTROUTING");
                    }
                    else if (table.Key == "filter")
                    {
                        isInternal = (chain == "INPUT" || chain == "FORWARD" || chain == "OUTPUT");
                    }
                    else if (table.Key == "raw")
                    {
                        isInternal = (chain == "PREROUTING" || chain == "OUTPUT");
                    }

                    if (isInternal)
                    {
                        output.WriteLine(":" + chain+" ACCEPT [0:0]");
                    }
                    else
                    {
                        output.WriteLine(":" + chain + " - [0:0]");
                    }
                }

                foreach (var command in table.Value.Commands)
                {
                    Console.WriteLine(command);
                    output.WriteLine(command);
                }

                output.WriteLine("COMMIT");
                output.WriteLine();
            }

            if (_tables.Count != 0)
            {
                return true;
            }

            return false;
        }

        public void Clear()
        {
            _tables.Clear();
        }

        public bool HasChain(string table, string chainName)
        {
            if (!_tables.ContainsKey(table))
            {
                return false;
            }

            return _tables[table].Chains.Contains(chainName);
        }

        public bool DeleteChain(string table, string chainName)
        {
            if (!_tables.ContainsKey(table))
            {
                return false;<commit_msg>iptables-restore Fix exception if program closes early due to invalid rule<commit_after>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace IPTables.Net.Iptables.Adapter.Client.Helper
{
    class IPTablesRestoreTableBuilder
    {
        private class Table
        {
            internal readonly HashSet<String> Chains = new HashSet<string>();
            internal readonly List<String> Commands = new List<string>();
        }
        private readonly Dictionary<String, Table> _tables = new Dictionary<String, Table>();

        public void AddChain(String table, String chain)
        {
            if (!_tables.ContainsKey(table))
            {
                _tables.Add(table, new Table());
            }
            var chainTable = _tables[table];

            if (chainTable.Chains.Contains(chain))
            {
                throw new Exception("Chain has already been added");
            }
            chainTable.Chains.Add(chain);
        }

        public void AddCommand(String table, String ruleCommand)
        {
            if (!_tables.ContainsKey(table))
            {
                _tables.Add(table, new Table());
            }
            var commandTable = _tables[table];

            //iptables-restore doesnt support ' quotes
            ruleCommand = ruleCommand.Replace('\'', '"');


            commandTable.Commands.Add(ruleCommand);
        }

        private bool WriteOutputLine(StreamWriter output, String line)
        {
            if (!output.BaseStream.CanWrite)
            {
                return false;
            }
            output.WriteLine(line);
            return true;
        }

        public bool WriteOutput(StreamWriter output)
        {
            bool res;
            foreach (var table in _tables)
            {
                res = WriteOutputLine(output, "*" + table.Key);
                if (!res)
                {
                    return true;
                }


                foreach (var chain in table.Value.Chains)
                {
                    bool isInternal = false;
                    if (table.Key == "nat")
                    {
                        isInternal = (chain == "PREROUTING" || chain == "POSTROUTING");
                    }
                    else if (table.Key == "filter")
                    {
                        isInternal = (chain == "INPUT" || chain == "FORWARD" || chain == "OUTPUT");
                    }
                    else if (table.Key == "raw")
                    {
                        isInternal = (chain == "PREROUTING" || chain == "OUTPUT");
                    }

                    if (isInternal)
                    {
                        res = WriteOutputLine(output, ":" + chain + " ACCEPT [0:0]");
                    }
                    else
                    {
                        res = WriteOutputLine(output, ":" + chain + " - [0:0]");
                    } 
                    if (!res)
                    {
                        return true;
                    }
                }

                foreach (var command in table.Value.Commands)
                {
                    Console.WriteLine(command);
                    res = WriteOutputLine(output, command);
                    if (!res)
                    {
                        return true;
                    }
                }

                res = WriteOutputLine(output, "COMMIT");
                if (!res)
                {
                    return true;
                }
                res = WriteOutputLine(output, "");
                if (!res)
                {
                    return true;
                }
            }

            if (_tables.Count != 0)
            {
                return true;
            }

            return false;
        }

        public void Clear()
        {
            _tables.Clear();
        }

        public bool HasChain(string table, string chainName)
        {
            if (!_tables.ContainsKey(table))
            {
                return false;
            }

            return _tables[table].Chains.Contains(chainName);
        }

        public bool DeleteChain(string table, string chainName)
        {
            if (!_tables.ContainsKey(table))
            {
                return false;
{'fraction_non_alphanumeric': 0.09595701125895599, 'fraction_numerical': 0.00127942681678608, 'mean_word_length': 1.0895482491312483, 'pattern_counts': {'":': 4, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6616731', 'n_tokens_mistral': 1892, 'n_tokens_neox': 1758, 'n_words': 414}