[
  {
    "path": "CONTRIBUTE.md",
    "content": "# Contribute.md\n\n## Team members\n\n* [Mark Baggett](https://github.com/MarkBaggett)\n\n## Adding new features\n\nIf you're interested in adding new features or fixing issues to the `freq` project, the overall process is:\n\n1. Select an issue to work on and assign the issue to yourself.  If not already created, first create the issue.\n2. Fork the project.\n3. Make the changes, including any additional test cases that should be added.\n4. Create a Pull Request against the `master` branch of this repo.\n5. After a review of the PR, make any changes as requested by the reviewer.\n6. The PR will then be merged into the repo.\n\nDon’t get discouraged! We estimate that the response time from the maintainers is around a few days.\n\n## Bug Triage\n\nWe welcome the reporting of issues and do so by using the [integrated Github issues](https://github.com/MarkBaggett/freq/issues).  When creating a new issue, you can help us diagnose and fix existing bugs by asking and providing answers for the following:\n\n* Is the bug reproducible as explained?\n* Is it reproducible in other environments (for instance, different versions of python, or different operating systems)?\n* Are the steps to reproduce the bug clear? If not, can you describe how you might reproduce it?\n* What tags should the bug have?\n\n## Documentation\n\nIf you're interested in working on the documentation for the project, feel free to do so as well.  The same process for adding new features goes for adding documentation.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Mark Baggett\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# freq\n\nThis is a repository for `freq.py` and `freq_server.py`.\n\n## Background:\n\nWhile sitting in SANS SEC511 I listened to [`@sethmisenar`](https://twitter.com/sethmisenar) laement the difficulty in using existing tools to detect DGA (Domain Generation Algorithm) hostnames often used by malware.  There are lots of AI based tools out there that do this but some are rather complex. I thought I could quickly write a tool that would work.  In about 30 minutes I threw together some old code I had lying around from a SQL Injection tool I worked on and I had a working proof of concept.  `freq.py` was born and it worked pretty well.  A year later [`@securitymapper`](https://twitter.com/securitymapper) had me wrap it in a web interface so he could query it from a SIEM and then the tool took off.  It turns out to be a pretty effective technique and gained some popularity and wide use!   This is a rewrite of the tool that incorporates some lessons learned and performance enhancements.\n\n## Recent Improvements:\n\n- Only one table is required for case sensitve or insensitive lookups. The tables are all case sensitive.  You can turn off and on case sensitivity and the .probability lookups will do what is needed to make them case insensitive.\n- Ignored characters with `--exclude` option.  Like `--ignore_case`, the characters are only ignored in the calculations of the probability. They are not ignored in the building of the table.\n- Speed.  Like I said.  It was a proof of concept and never really built with any performance in mind.  This fixes that.\n- Accuracy.  Some errors in calulations were identified by Pepe Berta (thanks!).  This fixes those and several others.  If you find others let me know.\n- Two calculations - I've added a second frequency score that I've calculated differently.  It will requires some testing to see if it is more useful than the previous number in detecting random hosts.\n- Multiple freq tables can be passed and loaded on the CLI then processed in the url.  For example: `python3 freq_server.py 9000 files.freq dns.freq`  Then query the url with the table name instead of measure like this `http://127.0.0.1:9000/dns.freq/hostname` or `http://127.0.0.1:9000/dns.freq1/hostname` for just measurement 1.\n\n## Version Compatibility:\n\nBoth `freq.py` and `freq_server.py` will work in either Python2 or Python3, but ship as a python3 script.\n\n## System-level Service Startup:\n\nA systemd startup file is provided, although you will likely need to adjust paths to the script and `freqtable2018.freq` file. The provided sample assumes you've cloned this repository to /usr/local/share/freq/. Enable with something like the following, again substituting the appropriate paths:\n\n```console\nsudo systemctl enable /usr/local/share/freq/systemd/freq.service\nsudo systemctl start freq.service\n```\n\n## Conntributing\n\nIf you're interested in contributing to the project, feel free to read through our [Contributing](CONTRIBUTE.md) document.\n\n## To Do:\n"
  },
  {
    "path": "freq.py",
    "content": "#!/usr/bin/env python3\nfrom __future__ import division\n\nimport sys\nimport string\nimport re\nimport weakref\nimport json\n\nfrom collections import Counter, defaultdict\nfrom pprint import pprint\n\nclass node():\n    \"\"\"\n    A class to represent a node.\n\n    Note: Assigning a weight actually adds that value.  It doesn't set\n    it to that value. For example node['c'] = 5    increases the value\n    in node by 5\n\n    Attributes\n    ----------\n\n    parent : node\n        the parent to this node\n    count : int\n        the current count for the node\n\"\"\"\n\n    def __init__(self,parent):\n        self.parent = parent\n        self._pairs = Counter()\n        self._cachecount = 0\n        self._dirtycount = False\n\n    def __getitem__(self,key):\n        if self.parent.ignore_case and (key.islower() or key.isupper()):\n            return  self._pairs[key.lower()] + self._pairs[key.upper()]\n        else:\n            return self._pairs[key]\n\n    def __setitem__(self,key,value):\n\n        # TODO: should consider using the __addr__ magic method instead\n        # since the described behavior is this instead\n        self._dirtycount = True\n        self._pairs[key] += value\n\n    @property\n    def count(self):\n        if self._dirtycount:\n           self._cachecount = sum(self._pairs.values())\n           self._dirtycount = False\n        return self._cachecount\n\nclass FreqCounter(dict):\n    \"\"\"\n    A class used for frequency counting.\n\n    Attributes\n    ----------\n\n    ignore_case : bool\n        TODO: Update\n    ignorechars : str\n        TODO: Update\n    verbose : bool\n        When enabled, print verbose messages to the console.\n    count : int\n        The number of entries in the table\n\n    \n    Methods\n    -------\n\n    toJSON()\n        Returns a JSON representation of the Table as a string\n    fromJSON(jsondata)\n        Imports the JSON representation into the Table\n    tally_str(line, weight=1)\n        TODO: Update\n    probability(line)\n        Returns the probability of a given letter combination\n    save(filename)\n        Writes the table to a frequency file\n    load(filename)\n        Loads the table from a given frequency file\n    printtable()\n        Prints the JSON table to the console\n    \"\"\"\n    def __init__(self, *args,**kwargs):\n        self._table = defaultdict(lambda :node(self))\n        self.ignore_case = False\n\n        # TODO: consider refactoring to ignore_chars for consistency\n        self.ignorechars = \"\"\n        self.verbose = \"verbose\" in kwargs\n\n    def __getitem__(self,key):\n        return self._table[key]\n\n    def __iter__(self):\n        return iter(self._table)\n\n    def __len__(self):\n        return len(self._table)\n\n    def toJSON(self):\n        \"\"\"\n        Returns a string JSON reperesentation of the table.\n        \"\"\"\n        serial = []\n        for key,val in self._table.items():\n            serial.append( (key, list(val._pairs.items())) )\n        return json.dumps((self.ignore_case, self.ignorechars, serial))\n\n    def fromJSON(self,jsondata):\n        \"\"\"\n        Imports the table from a string JSON representation of the table\n\n        Parameters\n        ----------\n        jsondata : str\n            A string that represents the JSON Data\n\n        Returns\n        -------\n        str\n            the JSON representation of the table\n        \"\"\"\n\n        # TODO: Raise an error if we get something that we didn't \n        # expect.\n        args = json.loads(jsondata)\n        if args:\n            self.ignore_case = args[0]\n            self.ignorechars = args[1]\n            for outerkey,val in args[2]:\n                self._table[outerkey] = node(self)\n                for letter,count in val:\n                   self._table[outerkey][letter] = count\n\n    def tally_str(self,line,weight=1):\n        \"\"\"\n        TODO: Update\n        \n        Parameters\n        ----------\n        line : string\n            TODO: Update\n        weight : int, optional\n            the weight to be assigned to the pair (default = 1)\n        \"\"\"\n        allpairs = re.findall(r\"..\", line)\n        allpairs.extend(re.findall(r\"..\",line[1:]))\n        for eachpair in allpairs:\n            self[eachpair[0]][eachpair[1]] = weight\n\n    def probability(self,line):\n        \"\"\"\n        Calculates the probability of the word pair\n\n        Parameters\n        ----------\n        line : str\n            TODO: Update\n\n        Returns\n        -------\n        float\n            TODO: verify; the probability of the given word pair\n        \"\"\"\n        allpairs = re.findall(r\"..\", line)\n        allpairs.extend(re.findall(r\"..\",line[1:]))\n        if self.verbose: \n            print(\"All pairs: {0}\".format(allpairs))\n        probs = []\n        for eachpair in allpairs:\n            pair = [eachpair[0], eachpair[1]]\n\n            # check if any part of the pair should be ignored and alert\n            # the user this was skipped\n            if not all(x in self.ignorechars for x in pair):\n                probs.append(self._probability(eachpair))\n                if self.verbose: \n                    print (\"Probability of {0}: {1}\".format(eachpair,probs))\n            elif self.verbose:\n                print(\"Pair '{}' was ignored\",format(self.ignorechars))\n        if probs:\n            average_probability = sum(probs) / len(probs) * 100\n        else:\n            average_probability = 0.0\n        if self.verbose:\n            print(\"Average Probability: {0}% \\n\\n\".format(average_probability))\n        \n        totl1 = 0\n        totl2 = 0\n        for eachpair in allpairs:\n            l1 = l2 = 0\n            pair = [eachpair[0], eachpair[1]]\n\n            if not all(x in self.ignorechars for x in pair):\n                l1 += self[eachpair[0]].count\n                if self.ignore_case and (eachpair[0].islower() or eachpair[0].isupper()):\n                    l1 += self[eachpair[0].swapcase()].count\n                l2 += self[eachpair[0]][eachpair[1]]\n                if self.ignore_case and (eachpair[0].islower() or eachpair[0].isupper()):\n                    l2 += self[eachpair[0].swapcase()][eachpair[1]]\n                totl1 += l1\n                totl2 += l2\n                if self.verbose: \n                    print(\"Letter1:{0} Letter2:{1}  - This pair {2}:{3} {4}:{5}\".format(\n                        totl1,\n                        totl2, \n                        eachpair[0],\n                        l1,\n                        eachpair[1],\n                        l2\n                    ))\n        if (totl1 == 0) or (totl2 == 0):\n            total_word_probability = 0.0\n        else:\n            total_word_probability = totl2/totl1 * 100\n        if self.verbose: print(\"Total Word Probability: {0}/{1} = {2}\".format(totl2, totl1, total_word_probability))\n        return round(average_probability,4),round(total_word_probability,4)\n\n    def _probability(self,twoletters):\n        if self.ignore_case and (self[twoletters[0]].count == 0 and self[twoletters[0].swapcase()].count == 0):\n            return 0.0\n        if not self.ignore_case and self[twoletters[0]].count == 0:\n            return 0.0\n        if self.ignore_case and (twoletters[0].islower() or twoletters[0].isupper()):\n            ignored_tot = sum([self[twoletters[0].lower()][eachlet] for eachlet in self.ignorechars]) + sum([self[twoletters[0].upper()][eachlet] for eachlet in self.ignorechars])\n            let2 = self[twoletters[0].lower()][twoletters[1]] + self[twoletters[0].upper()][twoletters[1]]\n            let1 = self[twoletters[0].lower()].count + self[twoletters[0].upper()].count\n            if let1 - ignored_tot == 0:\n                return 0.0\n            return let2/(let1-ignored_tot)\n        else:\n            ignored_tot = sum([self[twoletters[0]][eachlet] for eachlet in self.ignorechars])\n            if self[twoletters[0]].count - ignored_tot == 0:\n                return 0.0\n            return self[twoletters[0]][twoletters[1]] / (self[twoletters[0]].count - ignored_tot)\n\n    def save(self,filename):\n        try:\n            file_handle =  open(filename, 'wb')\n            file_handle.write(self.toJSON().encode(\"latin1\"))\n            file_handle.flush()\n            file_handle.close()\n        except Exception as e:\n            print(\"Unable to write freq file :\" + str(e))\n            raise(e)\n\n    def load(self,filename):\n        try:\n            file_handle =  open(filename,\"rb\")\n            self.fromJSON(file_handle.read().decode(\"latin1\"))\n            file_handle.close()\n        except Exception as e:\n            print(\"Unable to load freq file :\",str(e))\n            raise(e)\n\n    @property\n    def count(self):\n        return sum(map(lambda y:y.count, x._table.values()))\n\n    def printtable(self):\n        pprint(self.toJSON())\n\n\n\nif __name__ == \"__main__\":\n    import argparse\n    import os\n    parser=argparse.ArgumentParser()\n    parser.add_argument(\n        '-m',\n        '--measure',\n        required=False,\n        help='Measure likelihood of a given string',\n        dest='measure'\n    )\n    parser.add_argument(\n        '-n',\n        '--normal',\n        required=False,\n        help='Update the table based on the following normal string',\n        dest='normal'\n    )\n    parser.add_argument(\n        '-f',\n        '--normalfile',\n        required=False,\n        help='Update the table based on the contents of the normal file',\n        dest='normalfile'\n    )\n    parser.add_argument(\n        '-p',\n        '--print',\n        action='store_true',\n        required=False,\n        help='Print a table of the most likely letters in order',\n        dest='printtable'\n    )\n    parser.add_argument(\n        '-c',\n        '--create',\n        action='store_true',\n        required=False,\n        help='Create a new empty frequency table',dest='create'\n    )\n    parser.add_argument(\n        '-v',\n        '--verbose',\n        action='store_true',\n        required=False,\n        help='show calculation process',\n        dest='verbose'\n    )\n\n    parser.add_argument(\n        '-b',\n        '--bulk',\n        default=None,\n        required=False,\n        help='Measure every line in a file.',\n        dest='bulk'\n    )\n\n    # TODO: break these up as well\n    parser.add_argument('-t','--toggle_case_sensitivity',action='store_true',required=False,help='Ignore case in all future frequecy tabulations',dest='toggle_case')\n    parser.add_argument('-s','--case_sensitive',action='store_true',required=False,help='Consider case in calculations. Default ignores case.',dest='case_sensitive')\n    parser.add_argument('-w','--weight',type=int,default = 1, required=False,help='Affects weight of promote, update and update file (default is 1)',dest='weight')\n    parser.add_argument('-e','--exclude',default = \"\\n\\t~`!@#$%^&*()_+-\", required=False,help='Provide a list of characters to ignore from the tabulations.',dest='exclude')\n    parser.add_argument('freqtable',help='File storing character frequencies.')\n\n    args=parser.parse_args()\n\n    if args.verbose:\n        fc = FreqCounter(verbose=True)\n    else:\n        fc = FreqCounter()\n    if args.create and os.path.exists(args.freqtable):\n        print(\"Frequency table already exists. \" + args.freqtable)\n        sys.exit(1)\n\n    if not args.create:\n        if not os.path.exists(args.freqtable):\n           print(\"Frequency Character file not found. - %s \" % (args.freqtable))\n           raise(Exception(\"File not found.\"))\n        fc.load(args.freqtable)\n\n    if args.printtable: \n        fc.printtable()\n    if args.normal: \n        fc.tally_str(args.normal, args.weight)\n    if args.toggle_case:\n        print(\"This feature has been depricated. By default all calculations ignore case.  Use -s to consider case.\")\n    fc.ignore_case = not args.case_sensitive\n    fc.ignorechars = args.exclude\n    if args.verbose: \n        print(\"Ignoring Case: {0}\".format(fc.ignore_case))\n    if args.verbose: \n        print(\"Ignoring Characters: {0}\".format(fc.ignorechars))\n    if args.normalfile:\n        with open(args.normalfile,\"rb\") as filehandle:\n            for eachline in filehandle:\n                fc.tally_str(eachline.decode(\"latin1\"))\n    if args.measure: \n        print(fc.probability(args.measure))\n    if args.bulk:\n        with open(args.bulk,\"rt\") as filehandle:\n            for eachline in filehandle:\n                print(fc.probability(eachline),\"-\",eachline)\n                \n    fc.save(args.freqtable)"
  },
  {
    "path": "freq_server.py",
    "content": "#!/usr/bin/env python3\n#freq_server.py by Mark Baggett\n#Twitter @MarkBaggett\n#github http://github.com/MarkBaggett/\n#This scripts runs a web server to provide a callable API to use frequency tables.\n#\n#Start the server passing it a port and a frequecy table.  For example:\n#python freq_server.py 8080 english_lowercase.freq\n#\n#Now you can query the API to measure the character frequency of its characters.  \n#wget http://127.0.0.1:8080/?cmd=measure\\&tgt=measurethisstring\n#\n#You can also mark a string as normal.  NOTE: There is a performance impact to updating via the API.  Use CLI freq.py to update tables instead.\n#wget http://127.0.0.1:8080/?cmd=normal\\&tgt=UpdateFreqWithTheseChars&weight=10\n#\n#Thanks to @securitymapper for Testing & suggestions\n\nfrom __future__ import print_function\nfrom freq import *\nimport six\nif six.PY2:\n    import BaseHTTPServer\n    import SocketServer\n    import urlparse\nelse:\n    import http.server as BaseHTTPServer\n    import socketserver as SocketServer\n    import urllib.parse as urlparse\nimport threading\nimport re\nimport argparse\nimport os\n#import resource\n\n\nclass freqapi(BaseHTTPServer.BaseHTTPRequestHandler):\n    def do_GET(self):\n        if self.server.verbose: self.server.safe_print(\"Currently %s threads are active.\" % (threading.activeCount()))\n        #if self.server.verbose: self.server.safe_print(\"Memory usage: %s (kb)\" % resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)\n        self.send_response(200)\n        self.send_header('Content-type','text/plain')\n        self.end_headers()\n        (ignore, ignore, urlpath, urlparams, ignore) = urlparse.urlsplit(self.path)\n        cmdstr = tgtstr = None\n        if self.server.verbose: self.server.safe_print(urlparams)\n        if re.search(legit_urls, urlpath):\n            if self.server.verbose: self.server.safe_print(\"REST API CALL\", urlpath)\n            cmdstr = re.search(cmd_regex, urlpath)\n            tgtstr = re.search(tgtstr_regex, urlpath)\n            if not cmdstr or not tgtstr:\n                help_str = 'API Documentation \\nhttp://%s:%s/measure/<string> \\nhttp://%s:%s/normal/<string> \\n' % (self.server.server_address[0], self.server.server_address[1],self.server.server_address[0], self.server.server_address[1],self.server.server_address[0], self.server.server_address[1])\n                self.wfile.write(help_str.encode(\"Latin-1\"))\n                return\n            params = {}\n            params[\"cmd\"] = cmdstr.group(1)\n            params[\"tgt\"] = tgtstr.group(2)\n        else:\n            if self.server.verbose: self.server.safe_print(\"STANDARD API CALL\", urlpath)        \n            cmdstr=re.search(r\"cmd=\",urlparams)\n            tgtstr =  re.search(r\"tgt=\",urlparams)\n            if not cmdstr or not tgtstr:\n                help_str = 'API Documentation\\nhttp://%s:%s/?cmd=measure&tgt=<string> \\nhttp://%s:%s/measure/<string> \\nhttp://%s:%s/?cmd=normal&tgt=<string>&weight=<weight> \\n' % (self.server.server_address[0], self.server.server_address[1],self.server.server_address[0], self.server.server_address[1],self.server.server_address[0], self.server.server_address[1])\n                self.wfile.write(help_str.encode(\"LATIN-1\"))\n                return\n            params={}\n            try:\n                for prm in urlparams.split(\"&\"):\n                    key,value = prm.split(\"=\")\n                    params[key]=value\n            except:\n                self.wfile.write('<html><body>Unable to parse the url. </body></html>'.encode(\"LATIN-1\"))\n                return\n        if params[\"cmd\"] == \"normal\":\n            self.server.safe_print(\"cache cleared\")\n            try:\n                self.server.cache_lock.acquire()\n                self.server.cache ={}\n            finally:\n                self.server.cache_lock.release()\n            try:\n                self.server.fc_lock.acquire()\n                weight = int(params.get(\"weight\",\"1\"))\n                self.server.fc.tally_str(params[\"tgt\"], weight=weight)\n                self.server.dirty_fc = True\n            finally:\n                self.server.fc_lock.release()\n            self.wfile.write('<html><body>Frequency Table updated</body></html>'.encode(\"LATIN-1\")) \n        elif params[\"cmd\"][:7] == \"measure\":\n            cache_key = \"{0}\".format(params[\"tgt\"])\n            if cache_key in self.server.cache:\n                if self.server.verbose: self.server.safe_print (\"Query from cache:\", params[\"tgt\"])\n                measure =  self.server.cache.get(cache_key)\n            else:\n                if self.server.verbose: self.server.safe_print ( \"Added to cache:\", params[\"tgt\"])\n                measure = self.server.fc.probability(params[\"tgt\"])\n                try:\n                    self.server.cache_lock.acquire()\n                    self.server.cache[cache_key]=measure\n                finally:\n                    self.server.cache_lock.release()\n                if self.server.verbose>=2: self.server.safe_print ( \"Server cache: \", str(self.server.cache))\n            if params[\"cmd\"].endswith(\"1\"):\n                measure = measure[0]\n            elif params[\"cmd\"].endswith(\"2\"):\n                measure = measure[1]\n            self.wfile.write(str(measure).encode(\"LATIN-1\"))\n        elif any([params[\"cmd\"].startswith(x) for x in freqtables]):\n            table = params['cmd']\n            if table.endswith(\"1\") or table.endswith(\"2\"):\n                table = table[:-1]\n            cache_key = \"{0}:{1}\".format(table, params[\"tgt\"])\n            if self.server.verbose: self.server.safe_print(\"Call to table \", params['cmd'])  \n            if cache_key in self.server.cache:\n                if self.server.verbose: self.server.safe_print (\"Query from cache:\",cache_key, params[\"tgt\"])\n                measure =  self.server.cache.get(cache_key)\n            else:\n                if self.server.verbose: self.server.safe_print ( \"Added to cache:\",cache_key, params[\"tgt\"])\n                measure = self.server.fcs[table].probability(params[\"tgt\"])\n                try:\n                    self.server.cache_lock.acquire()\n                    self.server.cache[cache_key]=measure\n                finally:\n                    self.server.cache_lock.release()\n                if self.server.verbose>=2: self.server.safe_print ( \"Server cache: \", str(self.server.cache))\n            if params[\"cmd\"].endswith(\"1\"):\n                measure = measure[0]\n            elif params[\"cmd\"].endswith(\"2\"):\n                measure = measure[1]\n            self.wfile.write(str(measure).encode(\"LATIN-1\"))\n            return\n        else:\n            print(\"Invalid command {} or target {}\".format(params[\"cmd\"], params[\"tgt\"]))\n          \n    def log_message(self, format, *args):\n        return\n\nclass ThreadedFreqServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):\n    def __init__(self, *args,**kwargs):\n        self.fcs = {}\n        self.fc = FreqCounter()\n        self.cache = {}\n        self.cache_lock = threading.Lock()\n        self.screen_lock = threading.Lock()\n        self.verbose = False\n        self.fc_lock = threading.Lock()\n        self.dirty_fc = False\n        self.exitthread = threading.Event()\n        self.exitthread.clear()\n        BaseHTTPServer.HTTPServer.__init__(self, *args, **kwargs)\n\n    def safe_print(self,*args,**kwargs):\n        try:\n            self.screen_lock.acquire()\n            print(*args,**kwargs)\n        finally:\n            self.screen_lock.release()\n\n    def save_freqtable(self,save_path,save_interval):\n        if self.verbose: self.safe_print ( \"Save interval reached.\")\n        if self.dirty_fc:\n            if self.verbose: self.safe_print (\"Frequency counter changed.  Saving to disk.\",save_path)\n            try:\n                self.fc_lock.acquire()\n                self.fc.save(save_path)\n                self.dirty_fc = False\n            finally:\n                self.fc_lock.release()\n        else:\n            if self.verbose: self.safe_print (\"Frequency counter not changed.  Not Saving to disk.\")\n        #Reschedule yourself\n        if not self.exitthread.isSet():\n            self.timer = threading.Timer(60*save_interval, self.save_freqtable, args = (save_path,save_interval))\n            self.timer.start()\n\nif __name__==\"__main__\":\n    parser=argparse.ArgumentParser()\n    parser.add_argument('-ip','--address',required=False,help='IP Address for the server to listen on.  Default is 127.0.0.1',default='127.0.0.1')\n    parser.add_argument('-s','--save_interval',type=float,required=False,help='Number of minutes to wait before trying to save frequency table updates. Default is 10 minutes.  Set to 0 to never save.',default=10)\n    parser.add_argument('port',type=int,help='You must provide a TCP Port to bind to')\n    parser.add_argument('freq_table',nargs=\"+\", help='You must provide the frequency table name (optionally including the path)')\n    parser.add_argument('-v','--verbose',action='count',default=0,required=False,help='Print verbose output to the server screen.  -vv is more verbose.')\n\n    #args = parser.parse_args(\"-s 1 -vv 8081 english_lowercase.freq\".split())\n    args = parser.parse_args()\n    \n    #split paths and filenames on frequency tables\n    freqtables = list(map(lambda x:x[1], map(os.path.split, args.freq_table)))\n\n\n    #Setup the server.\n    server = ThreadedFreqServer((args.address, args.port), freqapi)\n\n    #Load Each of the Frequency Table\n    for eachtable in args.freq_table:\n        path,tablename = os.path.split(eachtable)\n        server.fcs[tablename] = FreqCounter()\n        try:\n            server.fcs[tablename].load(eachtable)\n        except:\n            err = \"********** Unable to load Frequency table {0}. ************\".format(eachtable)\n            raise(Exception(err))\n\n    #add psuedo table names for the two measurements\n    tables = list(freqtables)\n    tables += [x+\"1\" for x in freqtables]\n    tables += [x+\"2\" for x in freqtables]\n\n    #build regex for parsing urls based on table names\n    legit_urls = r\"[\\/](measure|measure1|measure2|normal|{0})[\\/].*?\".format( \"|\".join(tables))\n    cmd_regex = r\"[\\/](measure|measure1|measure2|normal|{0})[\\/].*$\".format( \"|\".join(tables))\n    tgtstr_regex = r\"[\\/](measure|measure1|measure2|normal|{0})[\\/](.*)$\".format( \"|\".join(tables))\n\n    #setup default freq_table\n    server.fc = server.fcs[freqtables[0]]\n    server.verbose = args.verbose\n\n    #Schedule the first save interval unless save_interval was set to 0.\n    if args.save_interval:\n        server.timer = threading.Timer(60 *args.save_interval, server.save_freqtable, args = (args.freq_table[0], args.save_interval))\n        server.timer.start()\n \n    #start the server\n    print('Server is Ready. http://%s:%s/<command>/<string>' % (args.address, args.port))\n    print(\"Commands include {}\".format(cmd_regex))\n    print('[?] - Remember: If you are going to call the api with wget, curl or something else from the bash prompt you need to escape the & with \\& \\n\\n')\n    while True:\n        try:\n            server.handle_request()\n        except KeyboardInterrupt:\n            break\n        \n    server.safe_print(\"Control-C hit: Exiting server...\")\n    server.safe_print(\"Web API Disabled...\")\n    if args.save_interval and server.dirty_fc:\n        server.safe_print(\"The Frequency counter has changed since the last save interval. Saving final update.\")\n        server.exitthread.set()\n        server.timer.cancel()\n        try:\n            server.fc_lock.acquire()\n            server.fc.save(args.freq_table[0])\n            server.fc_lock.release()\n        except:\n            server.safe_print(\"[!] An error occured during the final save.\")\n    elif args.save_interval:\n        server.safe_print( \"No Changes made since last file save.  Canceling scheduled save...\")\n        server.timer.cancel()\n    server.safe_print(\"Server has stopped.\")\n    \n\n"
  },
  {
    "path": "freq_sort.py",
    "content": "#!/usr/bin/env python3\nfrom freq import *\nimport argparse\nimport signal\nimport sys\n\nparser = argparse.ArgumentParser()\nparser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)\nparser.add_argument('-f','--freq_table',default = \"freqtable2018.freq\", required=False,help='Specify the frequency table to use. Default is freqtable2018.freq',dest='freqtable')\n\nparser.add_argument(\"-v\", \"--verbose\", action=\"count\", help = \"Show details of how sort order is determined.\")\nparser.add_argument('-s','--case_sensitive',action='store_true',required=False,help='Consider case in calculations. Default ignores case.',dest='case_sensitive')\nparser.add_argument('-e','--exclude',default = \"\\n\\t~`!@#$%^&*()_+-;\", required=False,help='Specify a full list of characters to ignore from the tabulations.',dest='exclude')\nparser.add_argument('-a','--add_exclude',default = \"\", required=False,help='Provide a list of characters to add to default ignored characters.',dest='additional')\nparser.add_argument('-n','--numeric',action='store_true',required=False,help='Convert input to number for sorting.',dest='numeric')\nparser.add_argument('-c','--cut',nargs=2,help='Specify a delimer and field value to cut a substring for the target of your search. Example -c \"/\" 3 will use the value between the 3rd and 4th \"/\" for sorting.',dest='cut')\nparser.add_argument('-S','--substring',nargs=2,help='Slice out a substring given the starting and stoping position. If cut is used this is performed after cut. Example -S 10,13 would only use the string comprised of characters 10,11 and 12 to determine the sort order.',dest='slice')\nparser.add_argument('-r','--reverse',action='store_true',required=False,help='Reverses the sort order with highest frequency values last',dest='reverse')\nparser.add_argument('-N','--no_length',action='store_true',required=False,help='Do not consider length of string when determining sort order',dest='length')\nparser.add_argument('-l','--line',action='store_true',required=False,help='Include the line number where the string was located in the output.',dest='line')\n\nargs = parser.parse_args()\n\ndef score(line):\n    if args.cut:\n        try:\n            line = line.split(args.cut[0])[int(args.cut[1])]\n        except IndexError:\n            line = \"\"\n        except:\n            raise(Exception(\"Unable to process -c cut options.\"))\n        if args.verbose: print(\"Now sorting on {}\".format(line))\n    if args.slice:\n        try:\n            line = line[int(args.slice[0]):int(args.slice[1])]\n        except:\n            raise(Exception(\"Unable to process -S substring options.\"))\n        if args.verbose: print(\"Now sorting on {}\".format(line))\n    if args.numeric:\n        try:\n            return float(line)\n        except:\n            raise(Exception(\"The value {} can not be treated as numeric. Try without -n.\".format(line)))\n    line_len = len(line) if not args.length else 1\n    return line_len * sum(freq.probability(line))/2\n\ndef signal_handler(sig, frame):\n    sys.exit(0)\n\nsignal.signal(signal.SIGINT, signal_handler)\nsignal.signal(signal.SIGPIPE,signal.SIG_DFL) \n\nfreq = FreqCounter()\n\nfreq.load(args.freqtable)\nif args.additional:\n    args.exclude += args.additional\nfreq.ignorechars = args.exclude\nfreq.ignore_case = not args.case_sensitive\nif args.verbose and args.verbose > 1:\n   freq.verbose = True\nfilecontent = args.infile.readlines()\nfor eachline in sorted(filecontent, key = score, reverse=not args.reverse):\n    if args.verbose:\n       print(score(eachline), freq.probability(eachline), end=\" \")\n    if args.line:\n       print(\"Found on line {} :\".format(filecontent.index(eachline)), end=\" \")\n    print(eachline,end=\"\")\n"
  },
  {
    "path": "freqtable2018.freq",
    "content": "[true, \"\\n\\t~`!@#$%^&*()_+-\", [[\"\\f\", [[\"f\", 2]]], [\" \", [[\" \", 312527], [\"$\", 12], [\"(\", 1520], [\",\", 6], [\"0\", 2], [\"4\", 210], [\"8\", 75], [\"<\", 58], [\"D\", 5449], [\"H\", 14898], [\"L\", 6849], [\"P\", 10276], [\"T\", 23773], [\"X\", 290], [\"`\", 1958], [\"d\", 74474], [\"h\", 195782], [\"l\", 64742], [\"p\", 65902], [\"t\", 408490], [\"x\", 22], [\"|\", 38], [\"#\", 6], [\"'\", 3062], [\"+\", 2], [\"/\", 12], [\"3\", 300], [\"7\", 134], [\";\", 8], [\"?\", 8], [\"C\", 9334], [\"G\", 5688], [\"K\", 2484], [\"O\", 4266], [\"S\", 13139], [\"W\", 9355], [\"[\", 408], [\"_\", 220], [\"c\", 90632], [\"g\", 44086], [\"k\", 13940], [\"o\", 161371], [\"s\", 182472], [\"w\", 187994], [\"{\", 8], [\"\\\"\", 22346], [\"&\", 42], [\"*\", 112], [\".\", 2358], [\"2\", 691], [\"6\", 180], [\":\", 14], [\">\", 2], [\"B\", 12213], [\"F\", 8428], [\"J\", 5957], [\"N\", 7370], [\"R\", 5046], [\"V\", 3389], [\"Z\", 250], [\"b\", 109654], [\"f\", 95818], [\"j\", 6186], [\"n\", 56010], [\"r\", 54486], [\"v\", 15242], [\"z\", 238], [\"~\", 2], [\"%\", 2], [\")\", 2], [\"-\", 550], [\"1\", 1613], [\"5\", 132], [\"9\", 74], [\"A\", 16635], [\"E\", 4590], [\"I\", 45393], [\"M\", 17353], [\"Q\", 356], [\"U\", 753], [\"Y\", 2574], [\"a\", 293192], [\"e\", 47200], [\"i\", 125201], [\"m\", 99016], [\"q\", 5914], [\"u\", 27850], [\"y\", 29288]]], [\"$\", [[\" \", 2], [\"3\", 2], [\"2\", 6], [\"4\", 10]]], [\"(\", [[\" \", 2], [\"\\\"\", 34], [\"$\", 12], [\"'\", 24], [\"*\", 8], [\"1\", 28], [\"3\", 24], [\"2\", 30], [\"5\", 2], [\"A\", 54], [\"C\", 12], [\"B\", 32], [\"E\", 12], [\"D\", 16], [\"G\", 6], [\"F\", 40], [\"I\", 120], [\"H\", 48], [\"K\", 10], [\"J\", 2], [\"M\", 48], [\"L\", 14], [\"O\", 20], [\"N\", 26], [\"P\", 26], [\"S\", 46], [\"U\", 8], [\"T\", 124], [\"W\", 38], [\"V\", 2], [\"Y\", 4], [\"_\", 14], [\"a\", 306], [\"`\", 2], [\"c\", 22], [\"b\", 50], [\"e\", 24], [\"d\", 18], [\"g\", 10], [\"f\", 80], [\"i\", 122], [\"h\", 102], [\"k\", 2], [\"j\", 2], [\"m\", 20], [\"l\", 20], [\"o\", 86], [\"n\", 38], [\"p\", 16], [\"s\", 106], [\"r\", 6], [\"u\", 6], [\"t\", 240], [\"w\", 212], [\"v\", 2], [\"y\", 6], [\"~\", 8]]], [\",\", [[\"!\", 2], [\" \", 200706], [\"\\\"\", 10148], [\"'\", 1656], [\")\", 4], [\"*\", 18], [\"-\", 780], [\",\", 10], [\"1\", 40], [\"0\", 263], [\"3\", 6], [\"2\", 42], [\"5\", 44], [\"4\", 28], [\"7\", 4], [\"6\", 20], [\"9\", 12], [\"8\", 18], [\":\", 4], [\"A\", 4], [\"I\", 42], [\"J\", 2], [\"M\", 2], [\"T\", 2], [\"[\", 2], [\"a\", 328], [\"c\", 8], [\"b\", 76], [\"e\", 6], [\"d\", 4], [\"g\", 10], [\"f\", 60], [\"i\", 36], [\"h\", 36], [\"k\", 6], [\"m\", 10], [\"l\", 6], [\"o\", 22], [\"n\", 8], [\"q\", 2], [\"p\", 2], [\"s\", 64], [\"r\", 8], [\"t\", 84], [\"w\", 70]]], [\"0\", [[\" \", 512], [\"%\", 16], [\"'\", 14], [\")\", 20], [\"-\", 20], [\",\", 155], [\".\", 70], [\"1\", 38], [\"0\", 714], [\"3\", 17], [\"2\", 32], [\"5\", 34], [\"4\", 13], [\"7\", 30], [\"6\", 21], [\"9\", 34], [\"8\", 20], [\";\", 8], [\":\", 22], [\"@\", 20], [\"I\", 6], [\"]\", 46], [\"m\", 2], [\"s\", 6], [\"t\", 74], [\"x\", 10], [\"}\", 18]]], [\"4\", [[\" \", 70], [\"'\", 4], [\")\", 2], [\"-\", 12], [\",\", 70], [\".\", 46], [\"1\", 24], [\"0\", 82], [\"3\", 24], [\"2\", 24], [\"5\", 34], [\"4\", 16], [\"7\", 28], [\"6\", 16], [\"9\", 24], [\"8\", 34], [\";\", 6], [\":\", 44], [\"@\", 8], [\"T\", 2], [\"]\", 60], [\"t\", 64], [\"}\", 18], [\"|\", 32]]], [\"8\", [[\" \", 64], [\"'\", 6], [\"-\", 12], [\",\", 68], [\".\", 28], [\"1\", 192], [\"0\", 155], [\"3\", 132], [\"2\", 89], [\"5\", 26], [\"4\", 56], [\"7\", 26], [\"6\", 74], [\"9\", 37], [\"8\", 12], [\";\", 12], [\":\", 14], [\"?\", 2], [\"@\", 10], [\"]\", 54], [\"m\", 2], [\"t\", 56], [\"}\", 18], [\"|\", 44]]], [\"<\", [[\"A\", 64], [\"C\", 132], [\"B\", 10], [\"E\", 18], [\"D\", 14], [\"G\", 4], [\"F\", 20], [\"I\", 14], [\"H\", 94], [\"K\", 2], [\"M\", 14], [\"L\", 8], [\"O\", 14], [\"N\", 2], [\"P\", 14], [\"S\", 14], [\"R\", 10], [\"T\", 224], [\"W\", 24], [\"Y\", 2], [\"m\", 2], [\"s\", 2]]], [\"@\", [[\" \", 102], [\"c\", 8], [\"e\", 14], [\",\", 8], [\".\", 8], [\"u\", 6], [\"v\", 16]]], [\"D\", [[\"!\", 4], [\" \", 358], [\"'\", 72], [\"*\", 16], [\"-\", 64], [\",\", 14], [\".\", 66], [\";\", 2], [\"?\", 2], [\"A\", 93], [\"C\", 2], [\"E\", 240], [\"D\", 2], [\"G\", 10], [\"F\", 8], [\"I\", 220], [\"M\", 2], [\"L\", 2], [\"O\", 89], [\"N\", 14], [\"P\", 2], [\"S\", 28], [\"R\", 70], [\"U\", 24], [\"V\", 2], [\"Y\", 12], [\"a\", 1027], [\"e\", 2124], [\"i\", 779], [\"j\", 6], [\"m\", 148], [\"o\", 2366], [\"n\", 8], [\"r\", 642], [\"u\", 914], [\"w\", 4], [\"y\", 20]]], [\"H\", [[\" \", 112], [\"'\", 14], [\",\", 8], [\".\", 210], [\"1\", 126], [\"3\", 42], [\"2\", 54], [\"5\", 12], [\"4\", 12], [\"7\", 12], [\"6\", 12], [\"9\", 12], [\"8\", 12], [\"?\", 2], [\"A\", 410], [\"E\", 722], [\"F\", 4], [\"I\", 298], [\"M\", 4], [\"O\", 260], [\"N\", 2], [\"Q\", 4], [\"S\", 6], [\"R\", 20], [\"U\", 26], [\"T\", 60], [\"Y\", 20], [\"a\", 2890], [\"e\", 16114], [\"i\", 2886], [\"h\", 2], [\"m\", 2], [\"o\", 2880], [\"s\", 4], [\"u\", 596], [\"v\", 2], [\"y\", 24]]], [\"L\", [[\"!\", 2], [\" \", 102], [\"'\", 40], [\")\", 2], [\"-\", 4], [\",\", 10], [\".\", 40], [\"1\", 6], [\"2\", 8], [\"5\", 2], [\"4\", 2], [\"6\", 2], [\"8\", 2], [\":\", 8], [\"A\", 120], [\"C\", 14], [\"E\", 261], [\"D\", 38], [\"G\", 14], [\"F\", 26], [\"I\", 210], [\"H\", 4], [\"K\", 46], [\"J\", 2], [\"M\", 6], [\"L\", 134], [\"O\", 98], [\"N\", 2], [\"P\", 4], [\"S\", 36], [\"R\", 6], [\"U\", 84], [\"T\", 12], [\"W\", 2], [\"Y\", 32], [\"a\", 2534], [\"e\", 1957], [\"i\", 1482], [\"h\", 70], [\"l\", 2], [\"o\", 2216], [\"u\", 614], [\"w\", 2], [\"y\", 30]]], [\"P\", [[\"!\", 2], [\" \", 30], [\"-\", 4], [\".\", 72], [\"A\", 198], [\"E\", 228], [\"G\", 8], [\"I\", 66], [\"H\", 24], [\"K\", 2], [\"M\", 8], [\"L\", 90], [\"O\", 110], [\"P\", 26], [\"S\", 18], [\"R\", 198], [\"U\", 54], [\"T\", 202], [\"Y\", 10], [\"a\", 2387], [\"e\", 1866], [\"f\", 50], [\"i\", 2690], [\"h\", 472], [\"l\", 486], [\"o\", 1094], [\"s\", 84], [\"r\", 4898], [\"u\", 314], [\"t\", 12], [\"w\", 2], [\"y\", 38]]], [\"T\", [[\"!\", 20], [\" \", 496], [\"'\", 18], [\"*\", 34], [\"-\", 20], [\",\", 66], [\".\", 132], [\":\", 6], [\"A\", 150], [\"C\", 14], [\"B\", 2], [\"E\", 2568], [\"F\", 2], [\"I\", 236], [\"H\", 1216], [\"M\", 20], [\"L\", 24], [\"O\", 330], [\"N\", 14], [\"P\", 14], [\"S\", 62], [\"R\", 71], [\"U\", 70], [\"T\", 106], [\"W\", 110], [\"Y\", 144], [\"Z\", 2], [\"a\", 643], [\"e\", 802], [\"i\", 1134], [\"h\", 41758], [\"o\", 3328], [\"s\", 100], [\"r\", 532], [\"u\", 500], [\"w\", 517], [\"v\", 8], [\"y\", 54], [\"z\", 4]]], [\"X\", [[\"A\", 2], [\" \", 22], [\"C\", 6], [\"E\", 2], [\"'\", 2], [\"I\", 444], [\"-\", 2], [\",\", 4], [\".\", 84], [\"1\", 2], [\"P\", 6], [\"2\", 2], [\"u\", 30], [\"T\", 78], [\"V\", 302], [\"X\", 266], [\":\", 6], [\"e\", 4]]], [\"`\", [[\" \", 4], [\"\\\"\", 2], [\"'\", 2], [\"2\", 2], [\"A\", 122], [\"C\", 26], [\"B\", 74], [\"E\", 14], [\"D\", 38], [\"G\", 30], [\"F\", 28], [\"I\", 270], [\"H\", 66], [\"K\", 4], [\"J\", 30], [\"M\", 66], [\"L\", 44], [\"O\", 26], [\"N\", 52], [\"P\", 34], [\"S\", 80], [\"R\", 14], [\"U\", 6], [\"T\", 166], [\"W\", 92], [\"V\", 4], [\"Y\", 66], [\"_\", 2], [\"a\", 62], [\"c\", 32], [\"b\", 40], [\"e\", 40], [\"d\", 24], [\"g\", 28], [\"f\", 38], [\"i\", 24], [\"h\", 26], [\"k\", 6], [\"j\", 2], [\"m\", 40], [\"l\", 28], [\"o\", 24], [\"n\", 14], [\"q\", 2], [\"p\", 40], [\"s\", 34], [\"r\", 18], [\"u\", 10], [\"t\", 98], [\"w\", 22], [\"v\", 2], [\"y\", 8]]], [\"d\", [[\"!\", 1346], [\" \", 316392], [\"\\\"\", 78], [\"'\", 892], [\")\", 158], [\"-\", 2110], [\",\", 27454], [\".\", 15448], [\"1\", 6], [\";\", 2238], [\":\", 1318], [\"?\", 904], [\">\", 32], [\"]\", 6], [\"_\", 10], [\"a\", 15612], [\"`\", 12], [\"c\", 64], [\"b\", 98], [\"e\", 66856], [\"d\", 5952], [\"g\", 2672], [\"f\", 682], [\"i\", 36856], [\"h\", 178], [\"k\", 152], [\"j\", 316], [\"m\", 1162], [\"l\", 4894], [\"o\", 27386], [\"n\", 2680], [\"q\", 32], [\"p\", 44], [\"s\", 12352], [\"r\", 13004], [\"u\", 5376], [\"t\", 176], [\"w\", 382], [\"v\", 1300], [\"y\", 5438], [\"z\", 4], [\"}\", 6]]], [\"h\", [[\"!\", 1480], [\" \", 66490], [\"\\\"\", 16], [\"'\", 580], [\")\", 46], [\"-\", 674], [\",\", 7634], [\".\", 3060], [\";\", 500], [\":\", 124], [\"?\", 354], [\">\", 8], [\"_\", 8], [\"a\", 130321], [\"`\", 2], [\"c\", 78], [\"b\", 454], [\"e\", 366316], [\"d\", 180], [\"g\", 2], [\"f\", 464], [\"i\", 118000], [\"h\", 16], [\"k\", 98], [\"m\", 1012], [\"l\", 810], [\"o\", 56794], [\"n\", 878], [\"q\", 34], [\"p\", 20], [\"s\", 1392], [\"r\", 8693], [\"u\", 9628], [\"t\", 23686], [\"w\", 410], [\"v\", 4], [\"y\", 4342], [\"z\", 2]]], [\"l\", [[\"!\", 688], [\" \", 55493], [\"\\\"\", 28], [\"'\", 776], [\")\", 58], [\"*\", 8], [\"-\", 1168], [\",\", 9058], [\"/\", 2], [\".\", 4175], [\"1\", 2], [\"2\", 4], [\";\", 588], [\":\", 138], [\"?\", 512], [\">\", 18], [\"@\", 2], [\"]\", 2], [\"_\", 14], [\"a\", 40424], [\"c\", 880], [\"b\", 428], [\"e\", 90647], [\"d\", 35897], [\"g\", 498], [\"f\", 11866], [\"i\", 53960], [\"h\", 30], [\"k\", 3952], [\"j\", 880], [\"m\", 2350], [\"l\", 72010], [\"o\", 43088], [\"n\", 488], [\"q\", 6], [\"p\", 1936], [\"s\", 9240], [\"r\", 1482], [\"u\", 8878], [\"t\", 7890], [\"w\", 1710], [\"v\", 3288], [\"y\", 43772], [\"x\", 2], [\"z\", 52]]], [\"p\", [[\"!\", 222], [\" \", 12684], [\"\\\"\", 12], [\"'\", 274], [\")\", 8], [\"*\", 16], [\"-\", 458], [\",\", 2678], [\".\", 1598], [\";\", 206], [\":\", 32], [\"?\", 102], [\">\", 2], [\"_\", 2], [\"a\", 24384], [\"c\", 110], [\"b\", 74], [\"e\", 40018], [\"d\", 12], [\"g\", 26], [\"f\", 100], [\"i\", 12578], [\"h\", 3890], [\"k\", 248], [\"m\", 220], [\"l\", 19938], [\"o\", 24960], [\"n\", 82], [\"p\", 12676], [\"s\", 4980], [\"r\", 27372], [\"u\", 7468], [\"t\", 8624], [\"w\", 150], [\"y\", 1538], [\"z\", 4]]], [\"t\", [[\"!\", 1698], [\" \", 244288], [\"\\\"\", 74], [\"'\", 4144], [\")\", 206], [\"*\", 10], [\"-\", 2634], [\",\", 24442], [\"/\", 22], [\".\", 15012], [\"9\", 30], [\";\", 1952], [\":\", 386], [\"?\", 2014], [\">\", 34], [\"@\", 16], [\"I\", 4], [\"N\", 2], [\"]\", 6], [\"_\", 20], [\"a\", 36864], [\"c\", 4804], [\"b\", 164], [\"e\", 93708], [\"d\", 32], [\"g\", 50], [\"f\", 1186], [\"i\", 67393], [\"h\", 380618], [\"k\", 30], [\"j\", 2], [\"m\", 1109], [\"l\", 15192], [\"o\", 120320], [\"n\", 980], [\"p\", 168], [\"s\", 20376], [\"r\", 31046], [\"u\", 18070], [\"t\", 25046], [\"w\", 8348], [\"v\", 6], [\"y\", 14950], [\"x\", 22], [\"z\", 596]]], [\"x\", [[\"!\", 16], [\" \", 1654], [\"'\", 108], [\")\", 6], [\"-\", 174], [\",\", 480], [\"/\", 2], [\".\", 262], [\"1\", 10], [\";\", 40], [\":\", 6], [\"?\", 20], [\"_\", 4], [\"a\", 1314], [\"c\", 2462], [\"b\", 4], [\"e\", 1456], [\"g\", 2], [\"f\", 26], [\"i\", 1676], [\"h\", 354], [\"l\", 20], [\"o\", 82], [\"q\", 56], [\"p\", 3828], [\"s\", 6], [\"u\", 144], [\"t\", 3514], [\"w\", 4], [\"y\", 88], [\"x\", 30]]], [\"|\", [[\" \", 30], [\"C\", 294]]], [\"#\", [[\"1\", 6], [\" \", 2]]], [\"'\", [[\"!\", 22], [\" \", 5218], [\"\\\"\", 130], [\"'\", 52], [\")\", 8], [\"-\", 136], [\",\", 274], [\".\", 194], [\"9\", 24], [\"8\", 10], [\";\", 12], [\":\", 4], [\"?\", 40], [\"A\", 506], [\"C\", 94], [\"B\", 292], [\"E\", 88], [\"D\", 124], [\"G\", 154], [\"F\", 90], [\"I\", 826], [\"H\", 360], [\"K\", 12], [\"J\", 52], [\"M\", 174], [\"L\", 102], [\"O\", 202], [\"N\", 222], [\"Q\", 12], [\"P\", 86], [\"S\", 328], [\"R\", 24], [\"U\", 38], [\"T\", 922], [\"W\", 482], [\"V\", 22], [\"Y\", 356], [\"a\", 288], [\"c\", 614], [\"b\", 42], [\"e\", 614], [\"d\", 2832], [\"g\", 48], [\"f\", 28], [\"i\", 98], [\"h\", 36], [\"k\", 6], [\"m\", 1148], [\"l\", 1792], [\"o\", 90], [\"n\", 44], [\"q\", 2], [\"p\", 40], [\"s\", 16835], [\"r\", 660], [\"u\", 62], [\"t\", 7172], [\"w\", 60], [\"v\", 880], [\"y\", 66], [\"}\", 2]]], [\"+\", [[\";\", 2], [\"B\", 2], [\"-\", 4]]], [\"/\", [[\" \", 26], [\"\\\"\", 2], [\"e\", 20], [\"I\", 14], [\"h\", 6], [\"1\", 2], [\"s\", 2], [\"2\", 4], [\"5\", 4], [\"4\", 2], [\"6\", 2]]], [\"3\", [[\"!\", 2], [\" \", 76], [\")\", 18], [\"*\", 8], [\"-\", 6], [\",\", 98], [\"/\", 2], [\".\", 66], [\"1\", 54], [\"0\", 158], [\"3\", 44], [\"2\", 60], [\"5\", 42], [\"4\", 18], [\"7\", 38], [\"6\", 24], [\"9\", 26], [\"8\", 20], [\";\", 10], [\":\", 48], [\"?\", 2], [\"@\", 4], [\"]\", 60], [\"d\", 6], [\"i\", 4], [\"h\", 2], [\"r\", 50], [\"t\", 26], [\"v\", 2], [\"}\", 18], [\"|\", 38]]], [\"7\", [[\"!\", 2], [\" \", 64], [\"'\", 10], [\"-\", 8], [\",\", 68], [\"/\", 4], [\".\", 46], [\"1\", 21], [\"0\", 36], [\"3\", 12], [\"2\", 35], [\"5\", 16], [\"4\", 14], [\"7\", 32], [\"6\", 26], [\"9\", 40], [\"8\", 34], [\";\", 10], [\":\", 28], [\"@\", 18], [\"]\", 48], [\"h\", 2], [\"m\", 4], [\"t\", 34], [\"}\", 18], [\"|\", 26]]], [\";\", [[\" \", 14368], [\"\\\"\", 42], [\"'\", 54], [\"h\", 2], [\"*\", 2], [\"-\", 146], [\",\", 2], [\"[\", 4]]], [\"?\", [[\" \", 5000], [\"\\\"\", 7386], [\"'\", 680], [\")\", 14], [\"-\", 90], [\",\", 2], [\".\", 118], [\"[\", 2], [\"?\", 2], [\">\", 2]]], [\"C\", [[\" \", 50], [\"\\\"\", 14], [\"'\", 12], [\"*\", 2], [\"-\", 4], [\",\", 6], [\"/\", 2], [\".\", 24], [\"A\", 126], [\"C\", 22], [\"E\", 112], [\"D\", 20], [\"I\", 76], [\"H\", 3260], [\"K\", 60], [\"L\", 26], [\"O\", 164], [\"P\", 6], [\"S\", 8], [\"R\", 38], [\"U\", 26], [\"T\", 117], [\"Y\", 16], [\"a\", 2763], [\"e\", 294], [\"i\", 277], [\"h\", 2428], [\"l\", 446], [\"o\", 4926], [\"s\", 4], [\"r\", 556], [\"u\", 212], [\"y\", 42], [\"z\", 24]]], [\"G\", [[\"!\", 2], [\" \", 132], [\"\\\"\", 8], [\"'\", 8], [\"-\", 56], [\",\", 22], [\".\", 10], [\";\", 2], [\":\", 2], [\"?\", 4], [\"A\", 72], [\"E\", 134], [\"G\", 10], [\"F\", 2], [\"I\", 34], [\"H\", 70], [\"L\", 16], [\"O\", 60], [\"N\", 14], [\"S\", 10], [\"R\", 64], [\"U\", 92], [\"T\", 2], [\"Y\", 2], [\"Z\", 2], [\"a\", 744], [\"e\", 958], [\"d\", 2], [\"i\", 460], [\"h\", 266], [\"l\", 212], [\"o\", 2628], [\"n\", 6], [\"r\", 1160], [\"u\", 880], [\"w\", 2], [\"y\", 2]]], [\"K\", [[\" \", 28], [\"'\", 2], [\",\", 6], [\".\", 8], [\"?\", 2], [\"A\", 4], [\"E\", 64], [\"F\", 2], [\"I\", 44], [\"H\", 2], [\"K\", 4], [\"L\", 12], [\"O\", 2], [\"N\", 4], [\"S\", 12], [\"R\", 6], [\"U\", 2], [\"W\", 4], [\"Y\", 2], [\"a\", 442], [\"e\", 504], [\"i\", 860], [\"h\", 122], [\"l\", 40], [\"o\", 290], [\"n\", 96], [\"r\", 96], [\"u\", 782], [\"y\", 10]]], [\"O\", [[\"!\", 6], [\" \", 466], [\"\\\"\", 2], [\"'\", 106], [\"-\", 4], [\",\", 12], [\".\", 38], [\":\", 2], [\"?\", 2], [\"A\", 6], [\"C\", 47], [\"B\", 32], [\"E\", 13], [\"D\", 52], [\"G\", 52], [\"F\", 288], [\"I\", 18], [\"H\", 28], [\"K\", 222], [\"J\", 50], [\"M\", 160], [\"L\", 98], [\"O\", 78], [\"N\", 489], [\"P\", 30], [\"S\", 64], [\"R\", 346], [\"U\", 338], [\"T\", 104], [\"W\", 64], [\"V\", 39], [\"Y\", 8], [\"Z\", 2], [\"a\", 2], [\"c\", 234], [\"b\", 128], [\"e\", 2], [\"d\", 26], [\"g\", 14], [\"f\", 1458], [\"i\", 6], [\"h\", 1000], [\"k\", 2], [\"m\", 60], [\"l\", 240], [\"o\", 44], [\"n\", 3744], [\"p\", 86], [\"s\", 22], [\"r\", 798], [\"u\", 554], [\"t\", 162], [\"w\", 32], [\"v\", 74], [\"y\", 2], [\"x\", 6], [\"z\", 68]]], [\"S\", [[\"!\", 8], [\" \", 616], [\"'\", 12], [\"*\", 6], [\"-\", 20], [\",\", 40], [\".\", 122], [\";\", 2], [\":\", 12], [\"?\", 2], [\"A\", 56], [\"C\", 58], [\"E\", 296], [\"D\", 2], [\"G\", 4], [\"F\", 4], [\"I\", 91], [\"H\", 76], [\"K\", 8], [\"M\", 14], [\"L\", 10], [\"O\", 98], [\"N\", 2], [\"Q\", 4], [\"P\", 30], [\"S\", 104], [\"R\", 2], [\"U\", 42], [\"T\", 322], [\"W\", 4], [\"Y\", 2], [\"a\", 2150], [\"c\", 1208], [\"e\", 1405], [\"i\", 968], [\"h\", 5152], [\"k\", 34], [\"m\", 374], [\"l\", 166], [\"o\", 4132], [\"n\", 120], [\"q\", 44], [\"p\", 776], [\"s\", 2], [\"u\", 1246], [\"t\", 1564], [\"w\", 144], [\"v\", 8], [\"y\", 126], [\"z\", 18]]], [\"W\", [[\"!\", 2], [\" \", 58], [\")\", 2], [\",\", 10], [\".\", 28], [\"A\", 136], [\"E\", 96], [\"D\", 4], [\"G\", 2], [\"I\", 90], [\"H\", 128], [\"L\", 4], [\"O\", 76], [\"N\", 12], [\"S\", 2], [\"R\", 8], [\"Y\", 4], [\"a\", 1096], [\"e\", 4362], [\"i\", 2096], [\"h\", 10098], [\"o\", 1611], [\"r\", 58], [\"u\", 18]]], [\"[\", [[\"*\", 2], [\"1\", 112], [\"3\", 56], [\"2\", 112], [\"5\", 30], [\"4\", 40], [\"7\", 4], [\"6\", 34], [\"9\", 4], [\"8\", 2], [\"A\", 12], [\"C\", 2], [\"B\", 6], [\"E\", 24], [\"D\", 4], [\"G\", 14], [\"F\", 2], [\"I\", 22], [\"H\", 30], [\"J\", 34], [\"M\", 28], [\"L\", 16], [\"N\", 4], [\"P\", 42], [\"S\", 6], [\"R\", 36], [\"T\", 18], [\"W\", 4], [\"a\", 2], [\"b\", 4], [\"d\", 2], [\"g\", 2], [\"f\", 14], [\"m\", 2], [\"l\", 4], [\"o\", 4], [\"p\", 6], [\"s\", 4], [\"t\", 50]]], [\"_\", [[\" \", 100], [\"'\", 2], [\"-\", 12], [\",\", 38], [\".\", 28], [\";\", 4], [\"A\", 14], [\"D\", 2], [\"I\", 30], [\"H\", 4], [\"M\", 4], [\"L\", 2], [\"O\", 2], [\"N\", 2], [\"T\", 12], [\"_\", 736], [\"^\", 6], [\"a\", 14], [\"c\", 12], [\"b\", 4], [\"e\", 6], [\"d\", 6], [\"f\", 14], [\"i\", 4], [\"h\", 2], [\"m\", 8], [\"l\", 6], [\"o\", 2], [\"n\", 14], [\"p\", 4], [\"s\", 10], [\"r\", 2], [\"u\", 4], [\"t\", 10], [\"w\", 8], [\"v\", 4], [\"y\", 4], [\"x\", 4]]], [\"c\", [[\"!\", 38], [\" \", 2940], [\"\\\"\", 6], [\"'\", 62], [\"-\", 122], [\",\", 498], [\".\", 480], [\";\", 56], [\":\", 18], [\"?\", 22], [\"C\", 8], [\"G\", 8], [\"F\", 2], [\"L\", 230], [\"Q\", 2], [\"P\", 2], [\"S\", 2], [\"a\", 38996], [\"c\", 5012], [\"e\", 54872], [\"d\", 38], [\"i\", 13186], [\"h\", 55038], [\"k\", 20111], [\"m\", 4], [\"l\", 12408], [\"o\", 57624], [\"n\", 26], [\"q\", 496], [\"p\", 66], [\"s\", 944], [\"r\", 13732], [\"u\", 9748], [\"t\", 19868], [\"w\", 8], [\"v\", 6], [\"y\", 1692], [\"z\", 12]]], [\"g\", [[\"!\", 572], [\" \", 77496], [\"\\\"\", 32], [\"'\", 490], [\")\", 44], [\"-\", 1388], [\",\", 8820], [\".\", 5284], [\";\", 654], [\":\", 276], [\"?\", 530], [\">\", 4], [\"a\", 16556], [\"c\", 8], [\"b\", 10], [\"e\", 31120], [\"d\", 134], [\"g\", 3662], [\"f\", 14], [\"i\", 11514], [\"h\", 36708], [\"m\", 368], [\"l\", 8714], [\"o\", 16464], [\"n\", 4300], [\"p\", 22], [\"s\", 6714], [\"r\", 16774], [\"u\", 6849], [\"t\", 1104], [\"w\", 42], [\"y\", 516], [\"z\", 14], [\"}\", 8]]], [\"k\", [[\"!\", 306], [\" \", 20132], [\"\\\"\", 14], [\"'\", 392], [\")\", 32], [\"-\", 554], [\",\", 4148], [\".\", 2414], [\"1\", 2], [\";\", 294], [\":\", 60], [\"?\", 214], [\">\", 10], [\"@\", 10], [\"a\", 870], [\"c\", 66], [\"b\", 38], [\"e\", 34087], [\"d\", 24], [\"g\", 58], [\"f\", 344], [\"i\", 13220], [\"h\", 948], [\"k\", 244], [\"j\", 22], [\"m\", 100], [\"l\", 2880], [\"o\", 816], [\"n\", 11134], [\"q\", 2], [\"p\", 12], [\"s\", 4228], [\"r\", 68], [\"u\", 68], [\"t\", 20], [\"w\", 314], [\"v\", 10], [\"y\", 768], [\"z\", 2]]], [\"o\", [[\"!\", 648], [\" \", 114177], [\"\\\"\", 18], [\"'\", 1162], [\")\", 38], [\"-\", 958], [\",\", 5210], [\".\", 2232], [\";\", 354], [\":\", 58], [\"?\", 516], [\"K\", 2], [\"J\", 2], [\"]\", 4], [\"_\", 6], [\"a\", 7834], [\"`\", 2], [\"c\", 9710], [\"b\", 5854], [\"e\", 2996], [\"d\", 16602], [\"g\", 5294], [\"f\", 99287], [\"i\", 10524], [\"h\", 872], [\"k\", 14852], [\"j\", 986], [\"m\", 51326], [\"l\", 30027], [\"o\", 36626], [\"n\", 131194], [\"q\", 172], [\"p\", 16136], [\"s\", 26802], [\"r\", 99219], [\"u\", 128095], [\"t\", 47116], [\"w\", 48246], [\"v\", 20522], [\"y\", 3366], [\"x\", 840], [\"z\", 456], [\"}\", 2]]], [\"s\", [[\"!\", 2144], [\" \", 245069], [\"\\\"\", 154], [\"'\", 1554], [\")\", 266], [\"*\", 14], [\"-\", 1948], [\",\", 37726], [\".\", 19990], [\"1\", 4], [\";\", 3000], [\":\", 928], [\"=\", 2], [\"?\", 1424], [\">\", 50], [\"[\", 6], [\"]\", 38], [\"_\", 24], [\"a\", 37342], [\"c\", 11410], [\"b\", 1092], [\"e\", 89922], [\"d\", 372], [\"g\", 288], [\"f\", 1206], [\"i\", 41018], [\"h\", 48184], [\"k\", 7002], [\"j\", 20], [\"m\", 5638], [\"l\", 7892], [\"o\", 41490], [\"n\", 2836], [\"q\", 1070], [\"p\", 17022], [\"s\", 38918], [\"r\", 118], [\"u\", 22362], [\"t\", 98283], [\"w\", 5082], [\"v\", 104], [\"y\", 2112], [\"z\", 8]]], [\"w\", [[\"!\", 302], [\" \", 25552], [\"\\\"\", 32], [\"'\", 332], [\")\", 38], [\"-\", 630], [\",\", 4620], [\"/\", 2], [\".\", 2130], [\";\", 296], [\":\", 56], [\"?\", 312], [\">\", 6], [\"_\", 4], [\"a\", 69912], [\"c\", 62], [\"b\", 88], [\"e\", 43746], [\"d\", 980], [\"g\", 230], [\"f\", 300], [\"i\", 50742], [\"h\", 55558], [\"k\", 232], [\"j\", 2], [\"m\", 12], [\"l\", 1768], [\"o\", 28157], [\"n\", 11280], [\"p\", 14], [\"s\", 3452], [\"r\", 3078], [\"u\", 116], [\"t\", 106], [\"w\", 8], [\"y\", 240], [\"z\", 2]]], [\"{\", [[\"`\", 2], [\"c\", 2], [\"E\", 2], [\"G\", 2], [\"s\", 6], [\"o\", 4], [\"1\", 224], [\"3\", 226], [\"2\", 230], [\"5\", 24], [\"4\", 34], [\"7\", 22], [\"6\", 22], [\"9\", 22], [\"8\", 24], [\"t\", 8]]], [\"\\\"\", [[\" \", 19496], [\"\\\"\", 12], [\"'\", 120], [\")\", 34], [\"*\", 70], [\"-\", 198], [\",\", 42], [\".\", 98], [\"1\", 4], [\"3\", 2], [\"2\", 4], [\"5\", 4], [\"4\", 4], [\"6\", 2], [\"8\", 6], [\";\", 74], [\":\", 2], [\"?\", 4], [\"A\", 4542], [\"C\", 1250], [\"B\", 2388], [\"E\", 472], [\"D\", 1474], [\"G\", 1096], [\"F\", 924], [\"I\", 8984], [\"H\", 2746], [\"K\", 138], [\"J\", 270], [\"M\", 1850], [\"L\", 912], [\"O\", 1848], [\"N\", 2630], [\"Q\", 110], [\"P\", 880], [\"S\", 1906], [\"R\", 350], [\"U\", 236], [\"T\", 5524], [\"W\", 6722], [\"V\", 340], [\"Y\", 4228], [\"X\", 4], [\"[\", 14], [\"Z\", 6], [\"]\", 8], [\"_\", 20], [\"a\", 732], [\"`\", 158], [\"c\", 118], [\"b\", 452], [\"e\", 46], [\"d\", 138], [\"g\", 54], [\"f\", 182], [\"i\", 408], [\"h\", 256], [\"k\", 10], [\"j\", 14], [\"m\", 148], [\"l\", 118], [\"o\", 112], [\"n\", 94], [\"q\", 4], [\"p\", 130], [\"s\", 230], [\"r\", 36], [\"u\", 32], [\"t\", 1014], [\"w\", 398], [\"v\", 22], [\"y\", 272]]], [\"&\", [[\"h\", 2], [\"c\", 8], [\" \", 26]]], [\"*\", [[\" \", 206], [\"\\\"\", 146], [\")\", 6], [\"*\", 636], [\",\", 12], [\".\", 4], [\":\", 8], [\">\", 2], [\"A\", 16], [\"C\", 4], [\"B\", 16], [\"E\", 20], [\"D\", 8], [\"G\", 2], [\"F\", 12], [\"I\", 6], [\"H\", 4], [\"K\", 4], [\"L\", 4], [\"O\", 6], [\"N\", 2], [\"P\", 2], [\"S\", 16], [\"T\", 92], [\"W\", 18], [\"V\", 14], [\"Y\", 2], [\"[\", 36], [\"]\", 54], [\"n\", 6]]], [\".\", [[\"!\", 36], [\" \", 88376], [\"\\\"\", 12990], [\"'\", 1624], [\")\", 132], [\"(\", 2], [\"*\", 27], [\"-\", 436], [\",\", 236], [\".\", 4176], [\"0\", 16], [\"2\", 8], [\"4\", 6], [\"7\", 2], [\"6\", 2], [\"9\", 14], [\";\", 20], [\":\", 166], [\"?\", 38], [\"A\", 46], [\"C\", 12], [\"B\", 12], [\"E\", 20], [\"D\", 4], [\"G\", 22], [\"F\", 12], [\"I\", 138], [\"H\", 38], [\"K\", 2], [\"J\", 2], [\"M\", 34], [\"L\", 10], [\"O\", 10], [\"N\", 20], [\"Q\", 2], [\"P\", 8], [\"S\", 38], [\"R\", 2], [\"U\", 4], [\"T\", 108], [\"W\", 42], [\"V\", 6], [\"Y\", 20], [\"[\", 26], [\"]\", 10], [\"_\", 8], [\"a\", 4], [\"`\", 6], [\"c\", 32], [\"b\", 2], [\"e\", 36], [\"i\", 16], [\"m\", 26], [\"o\", 2], [\"s\", 4], [\"u\", 24], [\"t\", 40], [\"x\", 10], [\"z\", 2]]], [\"2\", [[\" \", 128], [\"\\\"\", 2], [\"'\", 6], [\")\", 12], [\"*\", 6], [\"-\", 20], [\",\", 132], [\"/\", 2], [\".\", 82], [\"1\", 127], [\"0\", 229], [\"3\", 90], [\"2\", 98], [\"5\", 112], [\"4\", 96], [\"7\", 78], [\"6\", 88], [\"9\", 51], [\"8\", 80], [\";\", 4], [\":\", 56], [\"@\", 14], [\"]\", 70], [\"d\", 6], [\"n\", 28], [\"t\", 20], [\"}\", 20], [\"|\", 66]]], [\"6\", [[\" \", 60], [\"-\", 12], [\",\", 70], [\"/\", 2], [\".\", 30], [\"1\", 24], [\"0\", 76], [\"3\", 14], [\"2\", 34], [\"5\", 26], [\"4\", 19], [\"7\", 26], [\"6\", 32], [\"9\", 21], [\"8\", 22], [\";\", 10], [\":\", 32], [\"?\", 2], [\"@\", 10], [\"]\", 44], [\"m\", 4], [\"t\", 68], [\"}\", 18], [\"|\", 52]]], [\":\", [[\" \", 3056], [\"\\\"\", 2], [\"'\", 20], [\")\", 2], [\"(\", 8], [\"*\", 2], [\"-\", 1142], [\".\", 260], [\"1\", 118], [\"I\", 4], [\"3\", 44], [\"2\", 90], [\"5\", 14], [\"4\", 30], [\"7\", 14], [\"6\", 16], [\"9\", 12], [\"8\", 12], [\"R\", 4], [\"r\", 4]]], [\">\", [[\" \", 88], [\"#\", 2], [\"\\\"\", 4], [\"$\", 2], [\"-\", 2], [\",\", 2], [\":\", 2], [\"<\", 24], [\"A\", 2], [\"@\", 2], [\"C\", 2], [\"F\", 8], [\"I\", 10], [\"M\", 2], [\"L\", 2], [\"T\", 14], [\"W\", 4], [\"_\", 2], [\"^\", 2], [\"a\", 6], [\"c\", 8], [\"f\", 10], [\"i\", 12], [\"h\", 6], [\"m\", 8], [\"o\", 8], [\"p\", 2], [\"s\", 8], [\"t\", 8], [\"w\", 6], [\"v\", 2], [\"{\", 2]]], [\"B\", [[\" \", 16], [\"'\", 2], [\",\", 4], [\".\", 12], [\"A\", 44], [\"C\", 38], [\"B\", 6], [\"E\", 200], [\"I\", 62], [\"K\", 702], [\"M\", 6], [\"L\", 69], [\"O\", 247], [\"S\", 8], [\"R\", 26], [\"U\", 52], [\"Y\", 62], [\"a\", 2602], [\"e\", 3594], [\"i\", 1068], [\"h\", 100], [\"j\", 2], [\"l\", 520], [\"o\", 2392], [\"r\", 974], [\"u\", 8016], [\"w\", 2], [\"y\", 828]]], [\"F\", [[\"A\", 194], [\" \", 300], [\"E\", 36], [\"F\", 18], [\"I\", 98], [\"j\", 2], [\"l\", 372], [\"O\", 166], [\",\", 2], [\">\", 2], [\"i\", 958], [\"r\", 5046], [\"U\", 14], [\"o\", 3334], [\"a\", 2482], [\"e\", 430], [\"R\", 78], [\".\", 10], [\"u\", 184], [\"L\", 20], [\"T\", 30]]], [\"J\", [[\"A\", 18], [\"a\", 1388], [\"E\", 82], [\"d\", 2], [\"'\", 2], [\"I\", 2], [\"-\", 2], [\"o\", 2830], [\".\", 132], [\"i\", 314], [\"s\", 2], [\"U\", 30], [\"O\", 54], [\"e\", 1904], [\"u\", 1679]]], [\"N\", [[\"!\", 6], [\" \", 451], [\"\\\"\", 8], [\"'\", 28], [\"-\", 4], [\",\", 48], [\".\", 96], [\";\", 2], [\":\", 8], [\"?\", 2], [\"A\", 108], [\"C\", 124], [\"B\", 48], [\"E\", 247], [\"D\", 328], [\"G\", 216], [\"F\", 2], [\"I\", 92], [\"H\", 2], [\"K\", 22], [\"J\", 2], [\"L\", 4], [\"O\", 186], [\"N\", 40], [\"S\", 124], [\"R\", 13], [\"U\", 20], [\"T\", 298], [\"V\", 13], [\"Y\", 14], [\"a\", 3392], [\"e\", 2202], [\"i\", 1384], [\"o\", 4850], [\"u\", 72]]], [\"R\", [[\"!\", 2], [\" \", 2352], [\"\\\"\", 4], [\"'\", 20], [\"*\", 6], [\"-\", 4], [\",\", 78], [\".\", 718], [\":\", 2], [\"?\", 2], [\"A\", 178], [\"C\", 20], [\"B\", 12], [\"E\", 320], [\"D\", 100], [\"G\", 68], [\"F\", 4], [\"I\", 219], [\"K\", 70], [\"M\", 30], [\"L\", 42], [\"O\", 189], [\"N\", 84], [\"Q\", 2], [\"P\", 18], [\"S\", 90], [\"R\", 70], [\"U\", 34], [\"T\", 272], [\"W\", 16], [\"V\", 14], [\"Y\", 93], [\"a\", 374], [\"e\", 1237], [\"i\", 323], [\"h\", 52], [\"o\", 2304], [\"u\", 2014], [\"t\", 2], [\"y\", 20]]], [\"V\", [[\"A\", 47], [\"a\", 1798], [\"B\", 2], [\"E\", 276], [\"'\", 2], [\" \", 18], [\"I\", 587], [\"-\", 2], [\",\", 12], [\"O\", 26], [\"l\", 30], [\"i\", 510], [\"r\", 4], [\"U\", 2], [\"o\", 228], [\"y\", 26], [\"e\", 465], [\"R\", 22], [\".\", 162], [\"u\", 4], [\"Y\", 6]]], [\"Z\", [[\"a\", 32], [\"\\\"\", 2], [\"E\", 16], [\"d\", 4], [\"I\", 2], [\"h\", 68], [\",\", 4], [\"o\", 22], [\"n\", 30], [\"i\", 26], [\"u\", 10], [\"O\", 4], [\"e\", 124]]], [\"b\", [[\"!\", 40], [\" \", 1058], [\"'\", 68], [\")\", 4], [\"*\", 4], [\"-\", 98], [\",\", 414], [\".\", 244], [\";\", 24], [\":\", 6], [\"?\", 36], [\">\", 4], [\"a\", 13924], [\"c\", 22], [\"b\", 1618], [\"e\", 60104], [\"d\", 78], [\"g\", 4], [\"f\", 16], [\"i\", 6998], [\"h\", 46], [\"j\", 990], [\"m\", 324], [\"l\", 22082], [\"o\", 19980], [\"n\", 44], [\"s\", 2992], [\"r\", 13256], [\"u\", 20366], [\"t\", 1570], [\"w\", 30], [\"v\", 88], [\"y\", 13906]]], [\"f\", [[\"!\", 178], [\" \", 90391], [\"\\\"\", 8], [\"'\", 72], [\")\", 16], [\"*\", 2], [\"-\", 876], [\",\", 2770], [\".\", 1846], [\";\", 240], [\":\", 102], [\"?\", 144], [\"G\", 2], [\"I\", 2], [\"a\", 20108], [\"c\", 14], [\"b\", 38], [\"e\", 23990], [\"d\", 2], [\"g\", 10], [\"f\", 10886], [\"i\", 22788], [\"h\", 6], [\"k\", 12], [\"j\", 16], [\"m\", 12], [\"l\", 7808], [\"o\", 46468], [\"n\", 16], [\"p\", 2], [\"s\", 464], [\"r\", 21052], [\"u\", 10540], [\"t\", 10202], [\"w\", 62], [\"v\", 2], [\"y\", 396], [\"x\", 2]]], [\"j\", [[\"a\", 724], [\"!\", 2], [\"e\", 4002], [\"'\", 2], [\"i\", 118], [\"o\", 3558], [\".\", 4], [\"u\", 4654]]], [\"n\", [[\"!\", 1140], [\" \", 164227], [\"\\\"\", 84], [\"'\", 9982], [\")\", 108], [\"*\", 6], [\"-\", 2184], [\",\", 19804], [\".\", 11592], [\";\", 1670], [\":\", 478], [\"?\", 1178], [\">\", 50], [\"J\", 4], [\"]\", 18], [\"_\", 4], [\"a\", 17316], [\"c\", 30762], [\"b\", 372], [\"e\", 74881], [\"d\", 155134], [\"g\", 116276], [\"f\", 3720], [\"i\", 23814], [\"h\", 996], [\"k\", 7828], [\"j\", 896], [\"m\", 518], [\"l\", 7014], [\"o\", 57750], [\"n\", 7832], [\"q\", 950], [\"p\", 298], [\"s\", 29725], [\"r\", 506], [\"u\", 4864], [\"t\", 72732], [\"w\", 558], [\"v\", 3580], [\"y\", 9090], [\"x\", 498], [\"z\", 154], [\"}\", 4]]], [\"r\", [[\"!\", 1102], [\" \", 128583], [\"\\\"\", 78], [\"'\", 2438], [\")\", 108], [\"*\", 14], [\"-\", 2050], [\",\", 18518], [\".\", 12898], [\";\", 1346], [\":\", 332], [\"?\", 1112], [\">\", 28], [\"A\", 2], [\"@\", 14], [\"_\", 6], [\"a\", 45838], [\"c\", 7992], [\"b\", 2520], [\"e\", 175663], [\"d\", 22490], [\"g\", 6450], [\"f\", 3064], [\"i\", 57977], [\"h\", 1474], [\"k\", 6764], [\"j\", 14], [\"m\", 12284], [\"l\", 8396], [\"o\", 61720], [\"n\", 15999], [\"q\", 220], [\"p\", 3358], [\"s\", 36440], [\"r\", 17042], [\"u\", 12282], [\"t\", 29678], [\"w\", 1522], [\"v\", 4906], [\"y\", 24200], [\"x\", 6], [\"z\", 128]]], [\"v\", [[\"!\", 34], [\" \", 1478], [\"'\", 360], [\")\", 2], [\"-\", 58], [\",\", 566], [\".\", 316], [\";\", 12], [\":\", 4], [\"?\", 30], [\"_\", 2], [\"a\", 8210], [\"e\", 85189], [\"g\", 2], [\"i\", 17242], [\"k\", 2], [\"m\", 16], [\"l\", 218], [\"o\", 6350], [\"n\", 508], [\"s\", 216], [\"r\", 658], [\"u\", 248], [\"t\", 4], [\"v\", 22], [\"y\", 640]]], [\"z\", [[\"!\", 8], [\" \", 344], [\"\\\"\", 2], [\"'\", 14], [\")\", 4], [\"-\", 40], [\",\", 172], [\".\", 178], [\";\", 8], [\":\", 2], [\"?\", 22], [\"a\", 592], [\"b\", 6], [\"e\", 3788], [\"d\", 18], [\"g\", 8], [\"i\", 920], [\"h\", 122], [\"k\", 6], [\"m\", 104], [\"l\", 356], [\"o\", 1122], [\"n\", 2], [\"s\", 6], [\"r\", 2], [\"u\", 156], [\"v\", 14], [\"y\", 202], [\"z\", 622]]], [\"~\", [[\")\", 6]]], [\"\\t\", [[\"\\t\", 174], [\" \", 136], [\"D\", 2]]], [\"!\", [[\"!\", 12], [\" \", 7580], [\"\\\"\", 6860], [\"'\", 556], [\")\", 42], [\"*\", 12], [\"-\", 108], [\",\", 4], [\".\", 170], [\"I\", 2], [\"v\", 6], [\"[\", 2], [\"_\", 6]]], [\"%\", [[\" \", 8]]], [\")\", [[\" \", 830], [\"-\", 56], [\",\", 506], [\".\", 102], [\"5\", 2], [\"[\", 2], [\":\", 16], [\";\", 58], [\"?\", 2]]], [\"-\", [[\"!\", 8], [\" \", 5090], [\"\\\"\", 550], [\"'\", 68], [\"(\", 2], [\"+\", 4], [\"-\", 6008], [\",\", 22], [\".\", 2], [\"1\", 12], [\"2\", 16], [\"5\", 24], [\"4\", 2], [\"7\", 4], [\"6\", 6], [\"8\", 4], [\"?\", 22], [\"A\", 170], [\"C\", 118], [\"B\", 200], [\"E\", 88], [\"D\", 116], [\"G\", 118], [\"F\", 62], [\"I\", 194], [\"H\", 172], [\"K\", 16], [\"J\", 90], [\"M\", 196], [\"L\", 74], [\"O\", 38], [\"N\", 44], [\"Q\", 6], [\"P\", 134], [\"S\", 172], [\"R\", 44], [\"T\", 160], [\"W\", 74], [\"V\", 28], [\"Y\", 22], [\"Z\", 4], [\"a\", 1098], [\"`\", 16], [\"c\", 1092], [\"b\", 1366], [\"e\", 476], [\"d\", 942], [\"g\", 452], [\"f\", 1014], [\"i\", 408], [\"h\", 966], [\"k\", 224], [\"j\", 64], [\"m\", 808], [\"l\", 922], [\"o\", 468], [\"n\", 446], [\"q\", 40], [\"p\", 884], [\"s\", 1836], [\"r\", 562], [\"u\", 122], [\"t\", 1410], [\"w\", 812], [\"v\", 66], [\"y\", 140], [\"z\", 12]]], [\"1\", [[\" \", 112], [\"'\", 4], [\")\", 16], [\"*\", 10], [\"-\", 14], [\",\", 112], [\"/\", 2], [\".\", 68], [\"1\", 246], [\"0\", 318], [\"3\", 164], [\"2\", 280], [\"5\", 224], [\"4\", 214], [\"7\", 188], [\"6\", 204], [\"9\", 126], [\"8\", 572], [\";\", 4], [\":\", 40], [\"@\", 4], [\"O\", 2], [\"]\", 48], [\"s\", 52], [\"t\", 22], [\"}\", 18], [\"|\", 88]]], [\"5\", [[\" \", 98], [\"\\\"\", 2], [\"'\", 2], [\"-\", 4], [\",\", 88], [\".\", 46], [\"1\", 22], [\"0\", 140], [\"3\", 28], [\"2\", 32], [\"5\", 32], [\"4\", 22], [\"7\", 32], [\"6\", 16], [\"9\", 14], [\"8\", 18], [\";\", 10], [\":\", 48], [\"?\", 2], [\"@\", 14], [\"]\", 64], [\"t\", 82], [\"}\", 18], [\"|\", 44]]], [\"9\", [[\" \", 74], [\"'\", 2], [\")\", 4], [\"-\", 6], [\",\", 40], [\".\", 22], [\"1\", 26], [\"0\", 43], [\"3\", 48], [\"2\", 14], [\"5\", 18], [\"4\", 15], [\"7\", 34], [\"6\", 20], [\"9\", 18], [\"8\", 10], [\";\", 12], [\":\", 38], [\"@\", 6], [\"]\", 44], [\"t\", 32], [\"}\", 18], [\"|\", 46]]], [\"=\", [[\"E\", 2], [\"=\", 8], [\"T\", 14], [\" \", 12]]], [\"A\", [[\" \", 4464], [\"\\\"\", 2], [\"'\", 12], [\"-\", 18], [\",\", 4], [\".\", 24], [\"A\", 6], [\"C\", 108], [\"B\", 58], [\"E\", 22], [\"D\", 77], [\"G\", 50], [\"F\", 18], [\"I\", 98], [\"H\", 10], [\"K\", 18], [\"M\", 89], [\"L\", 220], [\"N\", 497], [\"Q\", 2], [\"P\", 2116], [\"S\", 220], [\"R\", 481], [\"U\", 44], [\"T\", 292], [\"W\", 18], [\"V\", 78], [\"Y\", 66], [\"X\", 6], [\"Z\", 2], [\"a\", 2], [\"c\", 208], [\"b\", 496], [\"e\", 2], [\"d\", 372], [\"g\", 352], [\"f\", 1144], [\"i\", 66], [\"h\", 554], [\"k\", 64], [\"j\", 4], [\"m\", 1358], [\"l\", 3042], [\"o\", 140], [\"n\", 12454], [\"q\", 4], [\"p\", 230], [\"s\", 2898], [\"r\", 1643], [\"u\", 754], [\"t\", 3060], [\"w\", 48], [\"v\", 60], [\"y\", 30], [\"x\", 2], [\"z\", 30]]], [\"E\", [[\"!\", 20], [\" \", 1253], [\"\\\"\", 2], [\"'\", 18], [\"*\", 2], [\"-\", 14], [\",\", 30], [\".\", 100], [\":\", 8], [\"?\", 4], [\"A\", 176], [\"C\", 152], [\"B\", 30], [\"E\", 92], [\"D\", 166], [\"G\", 32], [\"F\", 34], [\"I\", 60], [\"H\", 6], [\"K\", 8], [\"M\", 80], [\"L\", 142], [\"O\", 14], [\"N\", 490], [\"Q\", 6], [\"P\", 124], [\"S\", 360], [\"R\", 730], [\"U\", 18], [\"T\", 184], [\"W\", 90], [\"V\", 102], [\"Y\", 34], [\"X\", 64], [\"a\", 450], [\"c\", 46], [\"b\", 14], [\"d\", 90], [\"g\", 62], [\"f\", 20], [\"i\", 64], [\"h\", 58], [\"k\", 6], [\"m\", 1500], [\"l\", 226], [\"o\", 4], [\"n\", 1398], [\"q\", 20], [\"p\", 138], [\"s\", 148], [\"r\", 118], [\"u\", 358], [\"t\", 98], [\"v\", 1326], [\"y\", 70], [\"x\", 298], [\"z\", 2], [\"}\", 2]]], [\"I\", [[\"!\", 34], [\" \", 40514], [\"\\\"\", 4], [\"'\", 2748], [\"-\", 52], [\",\", 526], [\".\", 576], [\";\", 42], [\":\", 6], [\"?\", 88], [\"A\", 76], [\"C\", 182], [\"B\", 47], [\"E\", 82], [\"D\", 78], [\"G\", 140], [\"F\", 78], [\"I\", 1054], [\"K\", 12], [\"M\", 76], [\"L\", 150], [\"O\", 134], [\"N\", 704], [\"Q\", 4], [\"P\", 18], [\"S\", 277], [\"R\", 122], [\"U\", 2], [\"T\", 378], [\"V\", 298], [\"X\", 156], [\"Z\", 8], [\"_\", 46], [\"a\", 2], [\"c\", 146], [\"b\", 10], [\"d\", 16], [\"g\", 48], [\"f\", 1944], [\"m\", 196], [\"l\", 216], [\"o\", 30], [\"n\", 5298], [\"p\", 28], [\"s\", 930], [\"r\", 122], [\"t\", 8656], [\"v\", 100], [\"x\", 2], [\"z\", 2]]], [\"M\", [[\"!\", 4], [\" \", 68], [\"\\\"\", 2], [\"'\", 12], [\"-\", 4], [\",\", 12], [\"/\", 8], [\".\", 1208], [\":\", 2], [\"A\", 346], [\"C\", 28], [\"B\", 34], [\"E\", 243], [\"D\", 6], [\"G\", 12], [\"I\", 130], [\"M\", 24], [\"L\", 2], [\"O\", 117], [\"N\", 16], [\"P\", 50], [\"S\", 26], [\"R\", 8], [\"U\", 28], [\"W\", 6], [\"Y\", 24], [\"a\", 8688], [\"c\", 378], [\"e\", 1576], [\"f\", 2], [\"i\", 2158], [\"o\", 4266], [\"s\", 2], [\"r\", 2578], [\"u\", 518], [\"y\", 1492]]], [\"Q\", [[\"U\", 48], [\"C\", 2], [\"u\", 494], [\".\", 4]]], [\"U\", [[\"!\", 2], [\" \", 106], [\"'\", 6], [\",\", 2], [\".\", 10], [\"A\", 16], [\"C\", 48], [\"B\", 24], [\"E\", 54], [\"D\", 44], [\"G\", 12], [\"F\", 6], [\"I\", 12], [\"K\", 2], [\"M\", 60], [\"L\", 68], [\"N\", 116], [\"P\", 26], [\"S\", 130], [\"R\", 182], [\"U\", 2], [\"T\", 156], [\"V\", 2], [\"Z\", 6], [\"c\", 2], [\"g\", 12], [\"h\", 34], [\"k\", 4], [\"m\", 16], [\"l\", 30], [\"n\", 859], [\"p\", 360], [\"s\", 32], [\"r\", 68], [\"t\", 50], [\"v\", 16]]], [\"Y\", [[\"!\", 4], [\" \", 260], [\"\\\"\", 2], [\"'\", 4], [\"-\", 68], [\",\", 10], [\".\", 22], [\";\", 2], [\"A\", 2], [\"B\", 2], [\"E\", 26], [\"L\", 4], [\"O\", 112], [\"S\", 26], [\"R\", 4], [\"T\", 2], [\"a\", 122], [\"c\", 2], [\"e\", 1328], [\"i\", 10], [\"o\", 3878], [\"s\", 10], [\"u\", 26], [\"v\", 8]]], [\"]\", [[\"!\", 2], [\" \", 322], [\"J\", 2], [\"-\", 2], [\",\", 44], [\".\", 14], [\";\", 24], [\">\", 2]]], [\"a\", [[\"!\", 310], [\" \", 65518], [\"\\\"\", 24], [\"'\", 716], [\")\", 20], [\"*\", 1], [\"-\", 724], [\",\", 2766], [\".\", 1558], [\"1\", 2], [\";\", 152], [\":\", 30], [\"?\", 144], [\">\", 2], [\"S\", 2], [\"_\", 6], [\"a\", 122], [\"`\", 6], [\"c\", 35608], [\"b\", 19042], [\"e\", 752], [\"d\", 56288], [\"g\", 18377], [\"f\", 7666], [\"i\", 47228], [\"h\", 1140], [\"k\", 13604], [\"j\", 480], [\"m\", 24754], [\"l\", 68865], [\"o\", 314], [\"n\", 216874], [\"q\", 102], [\"p\", 18548], [\"s\", 105951], [\"r\", 97182], [\"u\", 12725], [\"t\", 135418], [\"w\", 10880], [\"v\", 25744], [\"y\", 29029], [\"x\", 666], [\"z\", 1906], [\"}\", 2]]], [\"e\", [[\"!\", 3010], [\" \", 487805], [\"\\\"\", 166], [\"'\", 4249], [\")\", 336], [\"*\", 10], [\"-\", 4298], [\",\", 40540], [\".\", 24278], [\";\", 3704], [\":\", 890], [\"?\", 2866], [\">\", 78], [\"B\", 2], [\"I\", 2], [\"S\", 2], [\"[\", 6], [\"]\", 18], [\"_\", 42], [\"a\", 79086], [\"`\", 2], [\"c\", 27918], [\"b\", 1598], [\"e\", 45884], [\"d\", 142368], [\"g\", 8394], [\"f\", 13916], [\"i\", 18692], [\"h\", 2842], [\"k\", 1590], [\"j\", 380], [\"m\", 31126], [\"l\", 54118], [\"o\", 4898], [\"n\", 129345], [\"q\", 1706], [\"p\", 17078], [\"s\", 100714], [\"r\", 205409], [\"u\", 2658], [\"t\", 41944], [\"w\", 11422], [\"v\", 24561], [\"y\", 23800], [\"x\", 14052], [\"z\", 560], [\"}\", 4]]], [\"i\", [[\"!\", 50], [\" \", 1222], [\"\\\"\", 2], [\"'\", 184], [\")\", 4], [\"*\", 2], [\"-\", 384], [\",\", 450], [\".\", 254], [\";\", 14], [\":\", 6], [\"?\", 14], [\"@\", 2], [\"G\", 2], [\"Y\", 2], [\"]\", 2], [\"_\", 8], [\"a\", 10716], [\"c\", 45183], [\"b\", 6986], [\"e\", 33445], [\"d\", 40015], [\"g\", 26388], [\"f\", 17002], [\"i\", 24], [\"h\", 72], [\"k\", 7006], [\"j\", 18], [\"m\", 40198], [\"l\", 43870], [\"o\", 33038], [\"n\", 232657], [\"q\", 394], [\"p\", 5884], [\"s\", 107323], [\"r\", 32008], [\"u\", 1844], [\"t\", 102683], [\"w\", 38], [\"v\", 16166], [\"y\", 2], [\"x\", 2074], [\"z\", 2892]]], [\"m\", [[\"!\", 462], [\" \", 35852], [\"\\\"\", 24], [\"'\", 294], [\")\", 58], [\"-\", 610], [\",\", 7564], [\".\", 6290], [\"1\", 2], [\";\", 758], [\":\", 298], [\"?\", 470], [\">\", 22], [\"]\", 2], [\"a\", 45673], [\"c\", 96], [\"b\", 7420], [\"e\", 83120], [\"d\", 36], [\"g\", 4], [\"f\", 768], [\"i\", 24836], [\"h\", 10], [\"k\", 22], [\"m\", 5770], [\"l\", 522], [\"o\", 32940], [\"n\", 1218], [\"p\", 15046], [\"s\", 8640], [\"r\", 202], [\"u\", 10278], [\"t\", 200], [\"w\", 24], [\"y\", 17480]]], [\"q\", [[\"a\", 2], [\" \", 2], [\"u\", 12073], [\",\", 2], [\"'\", 2]]], [\"u\", [[\"!\", 428], [\" \", 17752], [\"\\\"\", 16], [\"'\", 1182], [\")\", 6], [\"-\", 186], [\",\", 1924], [\".\", 1140], [\";\", 124], [\":\", 18], [\"?\", 428], [\"S\", 12], [\"T\", 2], [\"_\", 2], [\"a\", 6632], [\"c\", 12934], [\"b\", 5730], [\"e\", 10797], [\"d\", 6988], [\"g\", 18286], [\"f\", 2056], [\"i\", 9148], [\"h\", 30], [\"k\", 496], [\"j\", 84], [\"m\", 8440], [\"l\", 37068], [\"o\", 708], [\"n\", 43221], [\"q\", 64], [\"p\", 17232], [\"s\", 44836], [\"r\", 48568], [\"u\", 18], [\"t\", 49162], [\"w\", 10], [\"v\", 428], [\"y\", 210], [\"x\", 498], [\"z\", 722]]], [\"y\", [[\"!\", 1032], [\" \", 118640], [\"\\\"\", 62], [\"'\", 1440], [\")\", 154], [\"-\", 2010], [\",\", 18388], [\".\", 10860], [\";\", 1366], [\":\", 466], [\"?\", 946], [\">\", 26], [\"]\", 2], [\"_\", 4], [\"a\", 2624], [\"`\", 2], [\"c\", 242], [\"b\", 640], [\"e\", 11272], [\"d\", 206], [\"g\", 138], [\"f\", 198], [\"i\", 4422], [\"h\", 84], [\"k\", 76], [\"m\", 714], [\"l\", 818], [\"o\", 28106], [\"n\", 212], [\"p\", 410], [\"s\", 8723], [\"r\", 738], [\"u\", 58], [\"t\", 3028], [\"w\", 464], [\"v\", 110], [\"x\", 14], [\"z\", 40]]], [\"}\", [[\" \", 6], [\",\", 2]]]]]"
  },
  {
    "path": "systemd/freq.service",
    "content": "[Unit]\nDescription=Freq service\nAfter=network.target\n\n[Service]\nWorkingDirectory=/usr/bin\nExecStart=/usr/local/share/freq/freq_server.py -s 0 10004 /usr/local/share/freq/freqtable2018.freq\nPIDFile=/var/run/freq.pid\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "upstart/sample_upstart.config",
    "content": "description     \"Freq Server\"\nstart on filesystem or runlevel [2345]\nstop on runlevel [!2345]\n\nrespawn\n\nscript\n      export HOME=\"/usr/bin\"\n      echo $$ > /var/run/freqserver.pid\n      exec python3 /opt/freqserver/freq_server.py -ip <IP> <port> /opt/freqserver/freqtable2018.freq\nend script\n\npre-start script\n      echo \"[`date`] Freq Server starting\" >> /var/log/messages\nend script\n\npre-stop script\n      echo \"[`date`] Freq Server stopping\" >> /var/log/messages\nend script\n"
  }
]