iscpy-1.05/0000755000076500000240000000000012060712451013523 5ustar sharrellstaff00000000000000iscpy-1.05/Authors0000644000076500000240000000005412060712346015075 0ustar sharrellstaff00000000000000MAIN DEVELOEPRS: Jacob Collins John Pavlick iscpy-1.05/ChangeLog0000644000076500000240000000030212060712346015273 0ustar sharrellstaff00000000000000Release 1.05 - Fixed bug to allow for empty braces clauses Release 1.04 - Added cut_tag.py to automate cutting releases - Fixed inline comments - Fixed token parsing of single option clauses iscpy-1.05/ez_setup/0000755000076500000240000000000012060712451015361 5ustar sharrellstaff00000000000000iscpy-1.05/ez_setup/__init__.py0000755000076500000240000002400012060712353017472 0ustar sharrellstaff00000000000000#!python """Bootstrap setuptools installation If you want to use setuptools in your package's setup.py, just include this file in the same directory with it, and add this to the top of your setup.py:: from ez_setup import use_setuptools use_setuptools() If you want to require a specific version of setuptools, set a download mirror, or use an alternate download directory, you can do so by supplying the appropriate options to ``use_setuptools()``. This file can also be run as a script to install or upgrade setuptools. """ import sys DEFAULT_VERSION = "0.6c11" DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] md5_data = { 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', 'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090', 'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4', 'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7', 'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5', 'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de', 'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b', 'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2', 'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086', 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20', 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab', 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53', 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2', 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e', 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372', 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902', 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de', 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b', 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03', 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a', 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6', 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a', } import sys, os try: from hashlib import md5 except ImportError: from md5 import md5 def _validate_md5(egg_name, data): if egg_name in md5_data: digest = md5(data).hexdigest() if digest != md5_data[egg_name]: print >>sys.stderr, ( "md5 validation of %s failed! (Possible download problem?)" % egg_name ) sys.exit(2) return data def use_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15 ): """Automatically find/download setuptools and make it available on sys.path `version` should be a valid setuptools version number that is available as an egg for download under the `download_base` URL (which should end with a '/'). `to_dir` is the directory where setuptools will be downloaded, if it is not already available. If `download_delay` is specified, it should be the number of seconds that will be paused before initiating a download, should one be required. If an older version of setuptools is installed, this routine will print a message to ``sys.stderr`` and raise SystemExit in an attempt to abort the calling script. """ was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules def do_download(): egg = download_setuptools(version, download_base, to_dir, download_delay) sys.path.insert(0, egg) import setuptools; setuptools.bootstrap_install_from = egg try: import pkg_resources except ImportError: return do_download() try: pkg_resources.require("setuptools>="+version); return except pkg_resources.VersionConflict, e: if was_imported: print >>sys.stderr, ( "The required version of setuptools (>=%s) is not available, and\n" "can't be installed while this script is running. Please install\n" " a more recent version first, using 'easy_install -U setuptools'." "\n\n(Currently using %r)" ) % (version, e.args[0]) sys.exit(2) except pkg_resources.DistributionNotFound: pass del pkg_resources, sys.modules['pkg_resources'] # reload ok return do_download() def download_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, delay = 15 ): """Download setuptools from a specified location and return its filename `version` should be a valid setuptools version number that is available as an egg for download under the `download_base` URL (which should end with a '/'). `to_dir` is the directory where the egg will be downloaded. `delay` is the number of seconds to pause before an actual download attempt. """ import urllib2, shutil egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) url = download_base + egg_name saveto = os.path.join(to_dir, egg_name) src = dst = None if not os.path.exists(saveto): # Avoid repeated downloads try: from distutils import log if delay: log.warn(""" --------------------------------------------------------------------------- This script requires setuptools version %s to run (even to display help). I will attempt to download it for you (from %s), but you may need to enable firewall access for this script first. I will start the download in %d seconds. (Note: if this machine does not have network access, please obtain the file %s and place it in this directory before rerunning this script.) ---------------------------------------------------------------------------""", version, download_base, delay, url ); from time import sleep; sleep(delay) log.warn("Downloading %s", url) src = urllib2.urlopen(url) # Read/write all in one block, so we don't create a corrupt file # if the download is interrupted. data = _validate_md5(egg_name, src.read()) dst = open(saveto,"wb"); dst.write(data) finally: if src: src.close() if dst: dst.close() return os.path.realpath(saveto) def main(argv, version=DEFAULT_VERSION): """Install or upgrade setuptools and EasyInstall""" try: import setuptools except ImportError: egg = None try: egg = download_setuptools(version, delay=0) sys.path.insert(0,egg) from setuptools.command.easy_install import main return main(list(argv)+[egg]) # we're done here finally: if egg and os.path.exists(egg): os.unlink(egg) else: if setuptools.__version__ == '0.0.1': print >>sys.stderr, ( "You have an obsolete version of setuptools installed. Please\n" "remove it from your system entirely before rerunning this script." ) sys.exit(2) req = "setuptools>="+version import pkg_resources try: pkg_resources.require(req) except pkg_resources.VersionConflict: try: from setuptools.command.easy_install import main except ImportError: from easy_install import main main(list(argv)+[download_setuptools(delay=0)]) sys.exit(0) # try to force an exit else: if argv: from setuptools.command.easy_install import main main(argv) else: print "Setuptools version",version,"or greater has been installed." print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' def update_md5(filenames): """Update our built-in md5 registry""" import re for name in filenames: base = os.path.basename(name) f = open(name,'rb') md5_data[base] = md5(f.read()).hexdigest() f.close() data = [" %r: %r,\n" % it for it in md5_data.items()] data.sort() repl = "".join(data) import inspect srcfile = inspect.getsourcefile(sys.modules[__name__]) f = open(srcfile, 'rb'); src = f.read(); f.close() match = re.search("\nmd5_data = {\n([^}]+)}", src) if not match: print >>sys.stderr, "Internal error!" sys.exit(2) src = src[:match.start(1)] + repl + src[match.end(1):] f = open(srcfile,'w') f.write(src) f.close() if __name__=='__main__': if len(sys.argv)>2 and sys.argv[1]=='--md5update': update_md5(sys.argv[2:]) else: main(sys.argv[1:]) iscpy-1.05/ez_setup/README.txt0000755000076500000240000000114612060712353017065 0ustar sharrellstaff00000000000000This directory exists so that Subversion-based projects can share a single copy of the ``ez_setup`` bootstrap module for ``setuptools``, and have it automatically updated in their projects when ``setuptools`` is updated. For your convenience, you may use the following svn:externals definition:: ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup You can set this by executing this command in your project directory:: svn propedit svn:externals . And then adding the line shown above to the file that comes up for editing. Then, whenever you update your project, ``ez_setup`` will be updated as well. iscpy-1.05/iscpy/0000755000076500000240000000000012060712451014652 5ustar sharrellstaff00000000000000iscpy-1.05/iscpy/__init__.py0000755000076500000240000000361212060712346016773 0ustar sharrellstaff00000000000000#!/usr/bin/python # Copyright (c) 2009, Purdue University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # Neither the name of the Purdue University nor the names of its contributors # may be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Toplevel RosterCore API. This presents entities to external consumers.""" __copyright__ = 'Copyright (C) 2009, Purdue University' __license__ = 'BSD' __version__ = '1.05' from iscpy_core.core import * import iscpy_dns.named_importer_lib as dns __all__ = ['ParseTokens', 'Clip', 'Explode', 'ScrubComments', 'MakeISC', 'Parse', 'dns'] # vi: set ai aw sw=2: iscpy-1.05/iscpy/iscpy_core/0000755000076500000240000000000012060712451017011 5ustar sharrellstaff00000000000000iscpy-1.05/iscpy/iscpy_core/__init__.py0000755000076500000240000000000012060712346021116 0ustar sharrellstaff00000000000000iscpy-1.05/iscpy/iscpy_core/core.py0000755000076500000240000002133112060712346020321 0ustar sharrellstaff00000000000000#!/usr/bin/env python # Copyright (c) 2009, Purdue University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # Neither the name of the Purdue University nor the names of its contributors # may be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import copy import cPickle def ParseTokens(char_list): """Parses exploded isc named.conf portions. Inputs: char_list: List of isc file parts Outputs: dict: fragment or full isc file dict Recursive dictionary of isc file, dict values can be of 3 types, dict, string and bool. Boolean values are always true. Booleans are false if key is absent. Booleans represent situations in isc files such as: acl "registered" { 10.1.0/32; 10.1.1:/32;}} Example: {'stanza1 "new"': 'test_info', 'stanza1 "embedded"': {'acl "registered"': {'10.1.0/32': True, '10.1.1/32': True}}} """ index = 0 dictionary_fragment = {} new_char_list = copy.deepcopy(char_list) if( type(new_char_list) == str ): return new_char_list if( type(new_char_list) == dict ): return new_char_list last_open = None continuous_line = False temp_list = [] while( index < len(new_char_list) ): if( new_char_list[index] == '{' ): last_open = index if( new_char_list[index] == ';' and continuous_line ): dictionary_fragment = temp_list temp_list = [] continuous_line = False if( new_char_list[index] == ';' ): continuous_line = False if( len(new_char_list) > index + 1 and new_char_list[index] == '}' and new_char_list[index + 1] != ';' ): skip, value = Clip(new_char_list[last_open:]) temp_list.append({key: copy.deepcopy(ParseTokens(value))}) continuous_line = True if( len(new_char_list) > index + 1 and new_char_list[index + 1] == '{' ): key = new_char_list.pop(index) skip, dict_value = Clip(new_char_list[index:]) if( continuous_line ): temp_list.append({key: copy.deepcopy(ParseTokens(dict_value))}) else: dictionary_fragment[key] = copy.deepcopy(ParseTokens(dict_value)) index += skip else: if( len(new_char_list[index].split()) == 1 and '{' not in new_char_list ): for item in new_char_list: if( item in [';'] ): continue dictionary_fragment[item] = True #If there are more than 1 'keywords' at new_char_list[index] #ex - "recursion no;" elif( len(new_char_list[index].split()) >= 2 ): dictionary_fragment[new_char_list[index].split()[0]] = ' '.join(new_char_list[ index].split()[1:]) index += 1 #If there is just 1 'keyword' at new_char_list[index] #ex "recursion;" (not a valid option, but for example's sake it's fine) elif( new_char_list[index] not in ['{', ';', '}'] ): key = new_char_list[index] dictionary_fragment[key] = '' index += 1 index += 1 return dictionary_fragment def Clip(char_list): """Clips char_list to individual stanza. Inputs: char_list: partial of char_list from ParseTokens Outputs: tuple: (int: skip to char list index, list: shortened char_list) """ assert(char_list[0] == '{') char_list.pop(0) skip = 0 for index, item in enumerate(char_list): if( item == '{' ): skip += 1 elif( item == '}' and skip == 0 ): return (index, char_list[:index]) elif( item == '}' ): skip -= 1 raise Exception("Invalid brackets.") def Explode(isc_string): """Explodes isc file into relevant tokens. Inputs: isc_string: String of isc file Outputs: list: list of isc file tokens delimited by brackets and semicolons ['stanza1 "new"', '{', 'test_info', ';', '}'] """ str_array = [] temp_string = [] prev_char = '' for char in isc_string: if( char in ['\n'] ): continue if( char in ['{', '}', ';'] ): if( ''.join(temp_string).strip() == '' ): str_array.append(char) else: str_array.append(''.join(temp_string).strip()) str_array.append(char) temp_string = [] else: temp_string.append(char) prev_char = char return str_array def ScrubComments(isc_string): """Clears comments from an isc file Inputs: isc_string: string of isc file Outputs: string: string of scrubbed isc file """ isc_list = [] if( isc_string is None ): return '' expanded_comment = False for line in isc_string.split('\n'): no_comment_line = "" # Vet out any inline comments if( '/*' in line.strip() ): try: striped_line = line.strip() chars = enumerate(striped_line) while True: i, c = chars.next() try: if c == '/' and striped_line[i+1] == '*': expanded_comment = True chars.next() # Skipp '*' continue elif c == '*' and striped_line[i+1] == '/': expanded_comment = False chars.next() # Skipp '/' continue except IndexError: continue # We are at the end of the line if expanded_comment: continue else: no_comment_line += c except StopIteration: if no_comment_line: isc_list.append(no_comment_line) continue if( expanded_comment ): if( '*/' in line.strip() ): expanded_comment = False isc_list.append(line.split('*/')[-1]) continue else: continue if( line.strip().startswith(('#', '//')) ): continue else: isc_list.append(line.split('#')[0].split('//')[0].strip()) return '\n'.join(isc_list) def MakeISC(isc_dict, terminate=True): """Outputs an isc formatted file string from a dict Inputs: isc_dict: a recursive dictionary to be turned into an isc file (from ParseTokens) Outputs: str: string of isc file without indentation """ if( terminate ): terminator = ';' else: terminator = '' if( type(isc_dict) == str ): return isc_dict isc_list = [] for option in isc_dict: if( type(isc_dict[option]) == bool ): isc_list.append('%s%s' % (option, terminator)) elif( type(isc_dict[option]) == str or type(isc_dict[option]) == unicode): isc_list.append('%s %s%s' % (option, isc_dict[option], terminator)) elif( type(isc_dict[option]) == list ): new_list = [] for item in isc_dict[option]: new_list.append(MakeISC(item, terminate=False)) new_list[-1] = '%s%s' % (new_list[-1], terminator) isc_list.append('%s { %s }%s' % (option, ' '.join(new_list), terminator)) elif( type(isc_dict[option]) == dict ): isc_list.append('%s { %s }%s' % (option, MakeISC(isc_dict[option]), terminator)) return '\n'.join(isc_list) def ParseISCString(isc_string): """Makes a dictionary from an ISC file string Inputs: isc_string: string of isc file Outputs: dict: dictionary of ISC file representation """ return ParseTokens(Explode(ScrubComments(isc_string))) def Serialize(isc_string): """Makes a pickled string of a dict from an ISC file string Inputs: isc_string: string of an isc file Outputs: serialized_isc: serialized string of isc dict """ return u'%s' % cPickle.dumps(ParseISCString(isc_string)) def Deserialize(serialized_string): """Makes an iscpy dict from a serliazed ISC dict Inputs: isc_string: string of an isc file Outputs: deserialized_isc: unserialized dict of serialized isc dict """ return u'%s' % MakeISC(cPickle.loads(str(serialized_string))) iscpy-1.05/iscpy/iscpy_dhcp/0000755000076500000240000000000012060712451016777 5ustar sharrellstaff00000000000000iscpy-1.05/iscpy/iscpy_dhcp/__init__.py0000755000076500000240000000000012060712346021104 0ustar sharrellstaff00000000000000iscpy-1.05/iscpy/iscpy_dns/0000755000076500000240000000000012060712451016645 5ustar sharrellstaff00000000000000iscpy-1.05/iscpy/iscpy_dns/__init__.py0000755000076500000240000000000012060712346020752 0ustar sharrellstaff00000000000000iscpy-1.05/iscpy/iscpy_dns/named_importer_lib.py0000755000076500000240000001331412060712346023062 0ustar sharrellstaff00000000000000#!/usr/bin/env python # Copyright (c) 2009, Purdue University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # Neither the name of the Purdue University nor the names of its contributors # may be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import copy import iscpy def MakeNamedDict(named_string): """Makes a more organized named specific dict from parsed_dict Inputs: named_string: string of named file Outputs: dict: organized dict with keys views options and acls {'acls': {'acl1': ['10.1.0/32', '10.1.1/32']}, 'views': {'view1': {'zones': {'test_zone': {'file': '/path/to/zonefile', 'type': 'master', 'options': 'zone_options'}}, 'options': 'view_options'}}} """ named_string = iscpy.ScrubComments(named_string) parsed_dict = copy.deepcopy(iscpy.ParseTokens(iscpy.Explode(named_string))) named_data = {'acls': {}, 'views': {}, 'options': {}, 'orphan_zones': {}} for key in parsed_dict: if( key.startswith('acl') ): named_data['acls'][key.split()[1]] = [] for cidr in parsed_dict[key]: named_data['acls'][key.split()[1]].append(cidr) elif( key.startswith('view') ): view_name = key.split()[1].strip('"').strip() named_data['views'][view_name] = {'zones': {}, 'options': {}} for view_key in parsed_dict[key]: if( view_key.startswith('zone') ): zone_name = view_key.split()[1].strip('"').strip() named_data['views'][view_name]['zones'][zone_name] = ( {'options': {}, 'file': ''}) for zone_key in parsed_dict[key][view_key]: if( zone_key.startswith('file') ): named_data['views'][view_name]['zones'][zone_name]['file'] = ( parsed_dict[key][view_key][zone_key].strip('"').strip()) elif( zone_key.startswith('type') ): named_data['views'][view_name]['zones'][zone_name]['type'] = ( parsed_dict[key][view_key][zone_key].strip('"').strip()) else: named_data['views'][view_name]['zones'][zone_name]['options'][ zone_key] = parsed_dict[key][view_key][zone_key] else: named_data['views'][view_name]['options'][view_key] = ( parsed_dict[key][view_key]) elif( key.startswith('zone') ): zone_name = key.split()[1].strip('"').strip() named_data['orphan_zones'][zone_name] = ( {'options': {}, 'file': ''}) for zone_key in parsed_dict[key]: if( zone_key.startswith('file') ): named_data['orphan_zones'][zone_name]['file'] = ( parsed_dict[key][zone_key].strip('"').strip()) elif( zone_key.startswith('type') ): named_data['orphan_zones'][zone_name]['type'] = ( parsed_dict[key][zone_key].strip('"').strip()) else: named_data['orphan_zones'][zone_name]['options'][ zone_key] = parsed_dict[key][zone_key] else: named_data['options'][key] = parsed_dict[key] return named_data def MakeZoneViewOptions(named_data): """Makes zone and view data into strings to load into database. Inputs: named_data: named dict from MakeNamedDict Outputs: dict: dict with keys {'views': {}, 'zones': {}} """ options_dict = {'views':{}, 'zones': {}} for view in named_data['views']: options_dict['views'][view] = iscpy.MakeISC(named_data['views'][view]['options']) for zone in named_data['views'][view]['zones']: options_dict['zones'][zone] = iscpy.MakeISC(named_data['views'][view]['zones'][ zone]['options']) for zone in named_data['orphan_zones']: options_dict['zones'][zone] = iscpy.MakeISC(named_data['orphan_zones'][zone][ 'options']) return options_dict def DumpNamedHeader(named_data): """This function dumps the named header from a named_data dict Inputs: named_data: named dict from MakeNamedDict Outputs: str: stirng of named header """ return iscpy.MakeISC(named_data['options']) def MergeOrphanZones(named_data, view): """Merges orphaned zones into regular zones in named_data Inputs: named_data: named dict from MakeNamedDict view: string of view name """ for zone in named_data['orphan_zones']: if( view not in named_data['views'] ): named_data['views'][view] = {'zones': {}, 'options': {}} named_data['views'][view]['zones'][zone] = named_data['orphan_zones'][zone] iscpy-1.05/iscpy.egg-info/0000755000076500000240000000000012060712451016344 5ustar sharrellstaff00000000000000iscpy-1.05/iscpy.egg-info/dependency_links.txt0000644000076500000240000000000112060712451022412 0ustar sharrellstaff00000000000000 iscpy-1.05/iscpy.egg-info/entry_points.txt0000644000076500000240000000000512060712451021635 0ustar sharrellstaff00000000000000 iscpy-1.05/iscpy.egg-info/not-zip-safe0000644000076500000240000000000112060712451020572 0ustar sharrellstaff00000000000000 iscpy-1.05/iscpy.egg-info/PKG-INFO0000644000076500000240000000101212060712451017433 0ustar sharrellstaff00000000000000Metadata-Version: 1.0 Name: iscpy Version: 1.05 Summary: Python library to parse ISC style config files. Home-page: UNKNOWN Author: Jacob C. Collins Author-email: jc@purdue.edu License: BSD Description: ISCpy is a robust ISC config file parser. It has virtually unlimited possibilities for depth and quantity of ISC config files. ISC config files include BIND and DHCP config files among a few others. Keywords: isc config bind dhcp parser dns python Platform: UNKNOWN iscpy-1.05/iscpy.egg-info/SOURCES.txt0000644000076500000240000000101412060712451020224 0ustar sharrellstaff00000000000000Authors ChangeLog License MANIFEST setup.py ez_setup/README.txt ez_setup/__init__.py iscpy/__init__.py iscpy.egg-info/PKG-INFO iscpy.egg-info/SOURCES.txt iscpy.egg-info/dependency_links.txt iscpy.egg-info/entry_points.txt iscpy.egg-info/not-zip-safe iscpy.egg-info/top_level.txt iscpy/iscpy_core/__init__.py iscpy/iscpy_core/core.py iscpy/iscpy_dhcp/__init__.py iscpy/iscpy_dns/__init__.py iscpy/iscpy_dns/named_importer_lib.py test/blank_named_regtest.py test/named_importer_lib_regtest.py test/test_data/named.example.confiscpy-1.05/iscpy.egg-info/top_level.txt0000644000076500000240000000000612060712451021072 0ustar sharrellstaff00000000000000iscpy iscpy-1.05/License0000644000076500000240000000276312060712346015043 0ustar sharrellstaff00000000000000Roster is licensed under the BSD license: Copyright (c) 2009, Purdue University All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the Purdue University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. iscpy-1.05/MANIFEST0000644000076500000240000000031212060712346014653 0ustar sharrellstaff00000000000000Authors ChangeLog License setup.py iscpy/__init__.py iscpy/iscpy_core/core.py iscpy/iscpy_core/__init__.py iscpy/iscpy_dhcp/__init__.py iscpy/iscpy_dns/__init__.py iscpy/iscpy_dns/named_importer_lib.py iscpy-1.05/PKG-INFO0000644000076500000240000000101212060712451014612 0ustar sharrellstaff00000000000000Metadata-Version: 1.0 Name: iscpy Version: 1.05 Summary: Python library to parse ISC style config files. Home-page: UNKNOWN Author: Jacob C. Collins Author-email: jc@purdue.edu License: BSD Description: ISCpy is a robust ISC config file parser. It has virtually unlimited possibilities for depth and quantity of ISC config files. ISC config files include BIND and DHCP config files among a few others. Keywords: isc config bind dhcp parser dns python Platform: UNKNOWN iscpy-1.05/setup.cfg0000644000076500000240000000007312060712451015344 0ustar sharrellstaff00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 iscpy-1.05/setup.py0000644000076500000240000000162512060712346015244 0ustar sharrellstaff00000000000000try: from setuptools import setup, find_packages except ImportError: from ez_setup import use_setuptools use_setuptools() from setuptools import setup, find_packages import sys, os version = '1.05' setup( name='iscpy', version=version, description="Python library to parse ISC style config files.", long_description="""\ ISCpy is a robust ISC config file parser. It has virtually unlimited possibilities for depth and quantity of ISC config files. ISC config files include BIND and DHCP config files among a few others. """, classifiers=[], keywords='isc config bind dhcp parser dns python', author='Jacob C. Collins', author_email='jc@purdue.edu', url='', license='BSD', packages=find_packages(exclude=['ez_setup']), include_package_data=True, zip_safe=False, install_requires=[], entry_points=""" """, ) iscpy-1.05/test/0000755000076500000240000000000012060712451014502 5ustar sharrellstaff00000000000000iscpy-1.05/test/blank_named_regtest.py0000755000076500000240000000722212060712345021054 0ustar sharrellstaff00000000000000#!/usr/bin/python # Copyright (c) 2009, Purdue University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # Neither the name of the Purdue University nor the names of its contributors # may be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Regression test for iscpy.py Make sure you are running this against a database that can be destroyed. DO NOT EVER RUN THIS TEST AGAINST A PRODUCTION DATABASE. """ __copyright__ = 'Copyright (C) 2009, Purdue University' __license__ = 'BSD' __version__ = '1.05' import unittest import os import iscpy NAMED_FILE = 'test_data/named.example.conf' class TestNamedImport(unittest.TestCase): def setUp(self): self.named_file = ( 'include "/home/jcollins/roster-dns-management/test/test_data/rndc.key";' 'options { pid-file "test_data/named.pid";};\n' 'controls { inet 127.0.0.1 port 35638 allow{localhost;} keys {rndc-key;};};') self.maxDiff = None def testSingleOption(self): test_string = ( u'single-option;\n' u'boolean-option yes;\n' u'list-option { a; b; };\n' u'options {};\n') self.assertEqual(iscpy.Deserialize(iscpy.Serialize(test_string)), u'single-option ;\n' u'boolean-option yes;\n' u'options { };\n' u'list-option { a;\n' u'b; };') def testParse(self): self.assertEqual(iscpy.Explode(iscpy.ScrubComments(self.named_file)), ['include "/home/jcollins/roster-dns-management/test/test_data/rndc.key"', ';', 'options', '{', 'pid-file "test_data/named.pid"', ';', '}', ';', 'controls', '{', 'inet 127.0.0.1 port 35638 allow', '{', 'localhost', ';', '}', 'keys', '{', 'rndc-key', ';', '}', ';', '}', ';']) self.assertEqual(iscpy.ParseISCString(self.named_file), {'include': '"/home/jcollins/roster-dns-management/test/test_data/rndc.key"', 'options': {'pid-file': '"test_data/named.pid"'}, 'controls': [{'inet 127.0.0.1 port 35638 allow': {'localhost': True}}, {'keys': {'rndc-key': True}}]}) self.assertEqual(iscpy.MakeISC(iscpy.ParseISCString(self.named_file)), 'include "/home/jcollins/roster-dns-management/test/test_data/rndc.key";\n' 'options { pid-file "test_data/named.pid"; };\n' 'controls { inet 127.0.0.1 port 35638 allow { localhost; } keys { rndc-key; }; };') if( __name__ == '__main__' ): unittest.main() iscpy-1.05/test/named_importer_lib_regtest.py0000755000076500000240000004433112060712345022456 0ustar sharrellstaff00000000000000#!/usr/bin/python # Copyright (c) 2009, Purdue University # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # Neither the name of the Purdue University nor the names of its contributors # may be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Regression test for iscpy.py Make sure you are running this against a database that can be destroyed. DO NOT EVER RUN THIS TEST AGAINST A PRODUCTION DATABASE. """ __copyright__ = 'Copyright (C) 2009, Purdue University' __license__ = 'BSD' __version__ = '1.05' import unittest import os import iscpy NAMED_FILE = 'test_data/named.example.conf' class TestNamedImport(unittest.TestCase): def setUp(self): self.named_file = open(NAMED_FILE).read() self.maxDiff = None def testScrubComments01(self): self.assertEqual(iscpy.ScrubComments("/* */foobar"), "foobar") def testScrubComments02(self): self.assertEqual(iscpy.ScrubComments("/*\n*/foobar"), "foobar") def testScrubComments03(self): self.assertEqual(iscpy.ScrubComments("/*\n*\n*\n*/foobar"), "foobar") def testScrubComments(self): self.assertEqual(iscpy.ScrubComments(self.named_file), 'options {\ndirectory "/var/domain";\nrecursion yes;\n' 'allow-query { any; };\nmax-cache-size 512M;\n};\n\n' 'logging {\nchannel "security" {\n' 'file "/var/log/named-security.log" ' 'versions 10 size 10m;\nprint-time yes;\n};\n' 'channel "query_logging" {\nsyslog local5;\n' 'severity info;\n};\ncategory "client" { "null"; };\n' 'category "update-security" { "security"; };\n' 'category "queries" { "query_logging"; };\n};\n\n' 'controls {\ninet * allow { control-hosts; } keys ' '{rndc-key; };\n};\n\ninclude "/etc/rndc.key";\n\n' 'acl control-hosts {\n127.0.0.1/32;\n192.168.1.3/32;\n};\n' '\nacl admin {\n192.168.0.0/16;\n192.168.1.2/32;\n' '192.168.1.4/32;\n};\n\nview "unauthorized" {\n' 'recursion no;\nmatch-clients { network-unauthorized; };\n' 'additional-from-auth no;\nadditional-from-cache no;\n\n' 'zone "0.0.127.in-addr.arpa" {\ntype slave;\n' 'file "test_data/university.rev.bak";\nmasters {\n' '192.168.1.3;\n' '};\n};\n\nzone "1.210.128.in-addr.arpa" {\ntype master;\n' 'file "test_data/test_reverse_zone.db";\n' 'allow-query { network-unauthorized; };\n};\n\n' 'zone "." {\ntype hint;\nfile "named.ca";\n};\n};\n\n' 'view "authorized" {\nrecursion yes;\n' 'match-clients { network-authorized; };\n' 'allow-recursion { network-authorized; };\n' 'allow-query-cache { network-authorized; };\n' 'additional-from-auth yes;\nadditional-from-cache yes;\n\n' 'zone "university.edu" {\ntype slave;\n' 'file "test_data/university.db.bak";\nmasters {\n' '192.168.11.37;\n};\ncheck-names ignore;\n};\n\n' 'zone "smtp.university.edu" {\ntype master;\n' 'file "test_data/test_zone.db";\nmasters {\n' '192.168.11.37;\n};\n};\n\nzone "." {\ntype hint;\n' 'file "named.ca";\n};\n};\n\n') def testExplode(self): self.assertEqual(iscpy.Explode(self.named_file), ['options', '{', 'directory "/var/domain"', ';', 'recursion yes', ';', 'allow-query', '{', 'any', ';', '}', ';', 'max-cache-size 512M', ';', '}', ';', 'logging', '{', 'channel "security"', '{', 'file "/var/log/named-security.log" versions 10 size 10m', ';', 'print-time yes', ';', '}', ';', 'channel "query_logging"', '{', 'syslog local5', ';', 'severity info', ';', '}', ';', 'category "client"', '{', '"null"', ';', '}', ';', 'category "update-security"', '{', '"security"', ';', '}', ';', 'category "queries"', '{', '"query_logging"', ';', '}', ';', '}', ';', 'controls', '{', 'inet * allow', '{', 'control-hosts', ';', '}', 'keys', '{', 'rndc-key', ';', '}', ';', '}', ';', 'include "/etc/rndc.key"', ';', 'acl control-hosts', '{', '127.0.0.1/32', ';', '192.168.1.3/32', ';', '}', ';', 'acl admin', '{', '192.168.0.0/16', ';', '192.168.1.2/32', ';', '192.168.1.4/32', ';', '}', ';', 'view "unauthorized"', '{', 'recursion no', ';', 'match-clients', '{', 'network-unauthorized', ';', '}', ';', 'additional-from-auth no', ';', 'additional-from-cache no', ';', '//\t// Loopback network\t//\tzone "0.0.127.in-addr.arpa"', '{', 'type slave', ';', 'file "test_data/university.rev.bak"', ';', 'masters', '{', '192.168.1.3', ';', '}', ';', '}', ';', '//\t// 192.168.1.0/24\t//\tzone "1.210.128.in-addr.arpa"', '{', 'type master', ';', 'file "test_data/test_reverse_zone.db"', ';', 'allow-query', '{', 'network-unauthorized', ';', '}', ';', '}', ';', '//\t// Cache File\t//\tzone "."', '{', 'type hint', ';', 'file "named.ca"', ';', '}', ';', '}', ';', 'view "authorized"', '{', 'recursion yes', ';', 'match-clients', '{', 'network-authorized', ';', '}', ';', 'allow-recursion', '{', 'network-authorized', ';', '}', ';', 'allow-query-cache', '{', 'network-authorized', ';', '}', ';', 'additional-from-auth yes', ';', 'additional-from-cache yes', ';', 'zone "university.edu"', '{', 'type slave', ';', 'file "test_data/university.db.bak"', ';', 'masters', '{', '192.168.11.37', ';', '}', ';', 'check-names ignore', ';', '}', ';', '//\t// Internal view of "smtp.university.edu"\t//\tzone "smtp.university.edu"', '{', 'type master', ';', 'file "test_data/test_zone.db"', ';', 'masters', '{', '192.168.11.37', ';', '}', ';', '}', ';', '//\t// Cache File\t//\tzone "."', '{', 'type hint', ';', 'file "named.ca"', ';', '}', ';', '}', ';']) def testParse(self): self.assertEqual(iscpy.ParseTokens( iscpy.Explode( iscpy.ScrubComments(self.named_file))), {'acl control-hosts': {'127.0.0.1/32': True, '192.168.1.3/32': True}, 'acl admin': {'192.168.1.2/32': True, '192.168.1.4/32': True, '192.168.0.0/16': True}, 'view "authorized"': {'zone "smtp.university.edu"': {'masters': {'192.168.11.37': True}, 'type': 'master', 'file': '"test_data/test_zone.db"'}, 'allow-query-cache': {'network-authorized': True}, 'allow-recursion': {'network-authorized': True}, 'recursion': 'yes', 'zone "university.edu"': {'check-names': 'ignore', 'masters': {'192.168.11.37': True}, 'type': 'slave', 'file': '"test_data/university.db.bak"'}, 'match-clients': {'network-authorized': True}, 'zone "."': {'type': 'hint', 'file': '"named.ca"'}, 'additional-from-cache': 'yes', 'additional-from-auth': 'yes'}, 'controls': [{'inet * allow': {'control-hosts': True}}, {'keys': {'rndc-key': True}}], 'view "unauthorized"': {'zone "1.210.128.in-addr.arpa"': {'allow-query': {'network-unauthorized': True}, 'type': 'master', 'file': '"test_data/test_reverse_zone.db"'}, 'recursion': 'no', 'match-clients': {'network-unauthorized': True}, 'zone "."': {'type': 'hint', 'file': '"named.ca"'}, 'zone "0.0.127.in-addr.arpa"': { 'masters': {'192.168.1.3': True}, 'type': 'slave', 'file': '"test_data/university.rev.bak"'}, 'additional-from-cache': 'no', 'additional-from-auth': 'no'}, 'logging': {'category "update-security"': {'"security"': True}, 'category "queries"': {'"query_logging"': True}, 'channel "query_logging"': {'syslog': 'local5', 'severity': 'info'}, 'category "client"': {'"null"': True}, 'channel "security"': {'file': '"/var/log/named-security.log" versions 10 size 10m', 'print-time': 'yes'}}, 'include': '"/etc/rndc.key"', 'options': {'directory': '"/var/domain"', 'recursion': 'yes', 'allow-query': {'any': True}, 'max-cache-size': '512M'}}) def testMakeNamedDict(self): self.assertEqual(iscpy.dns.MakeNamedDict(self.named_file), {'acls': {'admin': ['192.168.1.2/32', '192.168.1.4/32', '192.168.0.0/16'], 'control-hosts': ['127.0.0.1/32', '192.168.1.3/32']}, 'options': {'include': '"/etc/rndc.key"', 'logging': {'category "update-security"': {'"security"': True}, 'category "queries"': {'"query_logging"': True}, 'channel "query_logging"': {'syslog': 'local5', 'severity': 'info'}, 'category "client"': {'"null"': True}, 'channel "security"': {'file': '"/var/log/named-security.log" versions 10 size 10m', 'print-time': 'yes'}}, 'options': {'directory': '"/var/domain"', 'recursion': 'yes', 'allow-query': {'any': True}, 'max-cache-size': '512M'}, 'controls': [{'inet * allow': {'control-hosts': True}}, {'keys': {'rndc-key': True}}]}, 'orphan_zones': {}, 'views': {'authorized': {'zones': {'university.edu': {'type': 'slave', 'options': {'masters': {'192.168.11.37': True}, 'check-names': 'ignore'}, 'file': 'test_data/university.db.bak'}, 'smtp.university.edu': {'type': 'master', 'options': {'masters': {'192.168.11.37': True}}, 'file': 'test_data/test_zone.db'}, '.': {'type': 'hint', 'options': {}, 'file': 'named.ca'}}, 'options': {'allow-recursion': {'network-authorized': True}, 'recursion': 'yes', 'match-clients': {'network-authorized': True}, 'allow-query-cache': {'network-authorized': True}, 'additional-from-cache': 'yes', 'additional-from-auth': 'yes'}}, 'unauthorized': {'zones': {'0.0.127.in-addr.arpa': {'type': 'slave', 'options': {'masters': {'192.168.1.3': True}}, 'file': 'test_data/university.rev.bak'}, '1.210.128.in-addr.arpa': {'type': 'master', 'options': {'allow-query': {'network-unauthorized': True}}, 'file': 'test_data/test_reverse_zone.db'}, '.': {'type': 'hint', 'options': {}, 'file': 'named.ca'}}, 'options': {'recursion': 'no', 'additional-from-cache': 'no', 'match-clients': {'network-unauthorized': True}, 'additional-from-auth': 'no'}}}}) def testMakeZoneViewOptions(self): self.assertEqual(iscpy.dns.MakeZoneViewOptions( iscpy.dns.MakeNamedDict(self.named_file)), {'zones': {'university.edu': 'masters { 192.168.11.37; };\n' 'check-names ignore;', '0.0.127.in-addr.arpa': 'masters { 192.168.1.3; };', 'smtp.university.edu': 'masters { 192.168.11.37; };', '1.210.128.in-addr.arpa': 'allow-query { network-unauthorized; };', '.': ''}, 'views': {'authorized': 'allow-recursion { network-authorized; };\n' 'recursion yes;\nmatch-clients { ' 'network-authorized; };\nallow-query-cache { ' 'network-authorized; };\nadditional-from-cache ' 'yes;\nadditional-from-auth yes;', 'unauthorized': 'recursion no;\nadditional-from-cache no;\n' 'match-clients { network-unauthorized; };\n' 'additional-from-auth no;'}}) def testMakeNamedHeader(self): self.assertEqual(iscpy.dns.DumpNamedHeader( iscpy.dns.MakeNamedDict(self.named_file)), 'include "/etc/rndc.key";\n' 'logging { category "update-security" { "security"; };\n' 'category "queries" { "query_logging"; };\n' 'channel "query_logging" { syslog local5;\nseverity info; };\n' 'category "client" { "null"; };\n' 'channel "security" { file "/var/log/named-security.log" ' 'versions 10 size 10m;\nprint-time ' 'yes; }; };\n' 'options { directory "/var/domain";\nrecursion yes;\n' 'allow-query { any; };\nmax-cache-size 512M; };\n' 'controls { inet * allow { control-hosts; } keys { rndc-key; }; ' '};') def testMakeISC(self): self.assertEqual(iscpy.MakeISC( {'level1': {'level2': {'level3': {'level4': { 'test1': True, 'test2': True, 'test3': True}}}}, 'newarg': 'newval', 'new_stanza': {'test': True}}), 'new_stanza { test; };\n' 'level1 { level2 { level3 { level4 { test1;\n' 'test3;\n' 'test2; }; }; }; };\n' 'newarg newval;') self.assertEqual(iscpy.MakeISC(iscpy.ParseISCString(self.named_file)), 'acl control-hosts { 127.0.0.1/32;\n' '192.168.1.3/32; };\n' 'acl admin { 192.168.1.2/32;\n' '192.168.1.4/32;\n' '192.168.0.0/16; };\n' 'view "authorized" { zone "smtp.university.edu" { masters { 192.168.11.37; };\n' 'type master;\n' 'file "test_data/test_zone.db"; };\n' 'allow-query-cache { network-authorized; };\n' 'allow-recursion { network-authorized; };\n' 'recursion yes;\n' 'zone "university.edu" { check-names ignore;\n' 'masters { 192.168.11.37; };\n' 'type slave;\n' 'file "test_data/university.db.bak"; };\n' 'match-clients { network-authorized; };\n' 'zone "." { type hint;\n' 'file "named.ca"; };\n' 'additional-from-cache yes;\n' 'additional-from-auth yes; };\n' 'controls { inet * allow { control-hosts; } keys { rndc-key; }; };\n' 'view "unauthorized" { zone "1.210.128.in-addr.arpa" { allow-query { network-unauthorized; };\n' 'type master;\n' 'file "test_data/test_reverse_zone.db"; };\n' 'recursion no;\n' 'match-clients { network-unauthorized; };\n' 'zone "." { type hint;\n' 'file "named.ca"; };\n' 'zone "0.0.127.in-addr.arpa" { masters { 192.168.1.3; };\n' 'type slave;\n' 'file "test_data/university.rev.bak"; };\n' 'additional-from-cache no;\n' 'additional-from-auth no; };\n' 'logging { category "update-security" { "security"; };\n' 'category "queries" { "query_logging"; };\n' 'channel "query_logging" { syslog local5;\n' 'severity info; };\n' 'category "client" { "null"; };\n' 'channel "security" { file "/var/log/named-security.log" versions 10 size 10m;\n' 'print-time yes; }; };\n' 'include "/etc/rndc.key";\n' 'options { directory "/var/domain";\n' 'recursion yes;\n' 'allow-query { any; };\n' 'max-cache-size 512M; };') if( __name__ == '__main__' ): unittest.main() iscpy-1.05/test/test_data/0000755000076500000240000000000012060712451016452 5ustar sharrellstaff00000000000000iscpy-1.05/test/test_data/named.example.conf0000644000076500000240000000331512060712345022043 0ustar sharrellstaff00000000000000options { directory "/var/domain"; recursion yes; allow-query { any; }; max-cache-size 512M; }; logging { channel "security" { file "/var/log/named-security.log" versions 10 size 10m; print-time yes; }; channel "query_logging" { syslog local5; severity info; }; category "client" { "null"; }; category "update-security" { "security"; }; category "queries" { "query_logging"; }; }; controls { inet * allow { control-hosts; } keys {rndc-key; }; }; include "/etc/rndc.key"; acl control-hosts { 127.0.0.1/32; 192.168.1.3/32; }; acl admin { 192.168.0.0/16; 192.168.1.2/32; 192.168.1.4/32; }; view "unauthorized" { recursion no; match-clients { network-unauthorized; }; additional-from-auth no; additional-from-cache no; // // Loopback network // zone "0.0.127.in-addr.arpa" { type slave; file "test_data/university.rev.bak"; masters { 192.168.1.3; }; }; // // 192.168.1.0/24 // zone "1.210.128.in-addr.arpa" { type master; file "test_data/test_reverse_zone.db"; allow-query { network-unauthorized; }; }; // // Cache File // zone "." { type hint; file "named.ca"; }; }; view "authorized" { recursion yes; match-clients { network-authorized; }; allow-recursion { network-authorized; }; allow-query-cache { network-authorized; }; additional-from-auth yes; additional-from-cache yes; zone "university.edu" { type slave; file "test_data/university.db.bak"; masters { 192.168.11.37; }; check-names ignore; }; // // Internal view of "smtp.university.edu" // zone "smtp.university.edu" { type master; file "test_data/test_zone.db"; masters { 192.168.11.37; }; }; // // Cache File // zone "." { type hint; file "named.ca"; }; };