00001 """
00002 Configuration file parsing utilities, layered on top of stock Python
00003 ConfigParser module.
00004
00005 $Id: config.py 2926 2010-01-04 22:28:34Z sra $
00006
00007 Copyright (C) 2009 Internet Systems Consortium ("ISC")
00008
00009 Permission to use, copy, modify, and distribute this software for any
00010 purpose with or without fee is hereby granted, provided that the above
00011 copyright notice and this permission notice appear in all copies.
00012
00013 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00014 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00015 AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00016 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00017 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00018 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00019 PERFORMANCE OF THIS SOFTWARE.
00020
00021 Portions copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN")
00022
00023 Permission to use, copy, modify, and distribute this software for any
00024 purpose with or without fee is hereby granted, provided that the above
00025 copyright notice and this permission notice appear in all copies.
00026
00027 THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH
00028 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00029 AND FITNESS. IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT,
00030 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00031 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00032 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00033 PERFORMANCE OF THIS SOFTWARE.
00034 """
00035
00036 import ConfigParser
00037
00038 class parser(object):
00039 """
00040 Extensions to stock Python ConfigParser:
00041
00042 Read config file and set default section while initializing parser object.
00043
00044 Support for OpenSSL-style subscripted options.
00045
00046 get-methods with default values and default section name.
00047 """
00048
00049 def __init__(self, filename, section = None, allow_missing = False):
00050 """
00051 Initialize this parser.
00052 """
00053
00054 self.filename = filename
00055 self.cfg = ConfigParser.RawConfigParser()
00056 try:
00057 self.cfg.readfp(open(filename), filename)
00058 except IOError:
00059 if not allow_missing:
00060 raise
00061 self.default_section = section
00062
00063 def has_section(self, section):
00064 """
00065 Test whether a section exists.
00066 """
00067
00068 return self.cfg.has_section(section)
00069
00070 def has_option(self, option, section = None):
00071 """
00072 Test whether an option exists.
00073 """
00074
00075 if section is None:
00076 section = self.default_section
00077 return self.cfg.has_option(section, option)
00078
00079 def multiget(self, option, section = None):
00080 """
00081 Parse OpenSSL-style foo.0, foo.1, ... subscripted options.
00082
00083 Returns a list of values matching the specified option name.
00084 """
00085
00086 matches = []
00087 if section is None:
00088 section = self.default_section
00089 if self.cfg.has_option(section, option):
00090 matches.append((-1, self.get(option, section = section)))
00091 for key, value in self.cfg.items(section):
00092 s = key.rsplit(".", 1)
00093 if len(s) == 2 and s[0] == option and s[1].isdigit():
00094 matches.append((int(s[1]), value))
00095 matches.sort()
00096 return [match[1] for match in matches]
00097
00098 def _get_wrapper(self, method, section, option, default):
00099 """
00100 Wrapper method to add default value and default section support to
00101 ConfigParser methods.
00102 """
00103 if section is None:
00104 section = self.default_section
00105
00106 if default is None or self.cfg.has_option(section, option):
00107 return method(section, option)
00108 else:
00109 return default
00110
00111 def get(self, option, default = None, section = None):
00112 """
00113 Get an option, perhaps with a default value.
00114 """
00115 return self._get_wrapper(self.cfg.get, section, option, default)
00116
00117 def getboolean(self, option, default = None, section = None):
00118 """
00119 Get a boolean option, perhaps with a default value.
00120 """
00121 return self._get_wrapper(self.cfg.getboolean, section, option, default)
00122
00123 def getint(self, option, default = None, section = None):
00124 """
00125 Get an integer option, perhaps with a default value.
00126 """
00127 return self._get_wrapper(self.cfg.getint, section, option, default)
00128
00129 def set_global_flags(self):
00130 """
00131 Consolidated control for all the little global control flags
00132 scattered through the libraries. This isn't a particularly good
00133 place for this function to live, but it has to live somewhere and
00134 making it a method of the config parser from which it gets all of
00135 its data is less silly than the available alternatives.
00136 """
00137
00138 import rpki.https, rpki.x509, rpki.sql, rpki.async
00139
00140 try:
00141 rpki.https.debug_http = self.getboolean("debug_http")
00142 except ConfigParser.NoOptionError:
00143 pass
00144
00145 try:
00146 rpki.https.debug_tls_certs = self.getboolean("debug_tls_certs")
00147 except ConfigParser.NoOptionError:
00148 pass
00149
00150 try:
00151 rpki.https.want_persistent_client = self.getboolean("want_persistent_client")
00152 except ConfigParser.NoOptionError:
00153 pass
00154
00155 try:
00156 rpki.https.want_persistent_server = self.getboolean("want_persistent_server")
00157 except ConfigParser.NoOptionError:
00158 pass
00159
00160 try:
00161 rpki.x509.CMS_object.debug_cms_certs = self.getboolean("debug_cms_certs")
00162 except ConfigParser.NoOptionError:
00163 pass
00164
00165 try:
00166 rpki.sql.sql_persistent.sql_debug = self.getboolean("sql_debug")
00167 except ConfigParser.NoOptionError:
00168 pass
00169
00170 try:
00171 rpki.async.timer.gc_debug = self.getboolean("gc_debug")
00172 except ConfigParser.NoOptionError:
00173 pass
00174
00175 try:
00176 rpki.async.timer.run_debug = self.getboolean("timer_debug")
00177 except ConfigParser.NoOptionError:
00178 pass
00179
00180 try:
00181 rpki.x509.XML_CMS_object.dump_outbound_cms = rpki.x509.DeadDrop(self.get("dump_outbound_cms"))
00182 except ConfigParser.NoOptionError:
00183 pass
00184
00185 try:
00186 rpki.x509.XML_CMS_object.dump_inbound_cms = rpki.x509.DeadDrop(self.get("dump_inbound_cms"))
00187 except ConfigParser.NoOptionError:
00188 pass
00189
00190 try:
00191 rpki.async.gc_summary(self.getint("gc_summary"))
00192 except ConfigParser.NoOptionError:
00193 pass