/client/configparserinc.py

https://github.com/Lovestick/fail2ban · Python · 111 lines · 66 code · 7 blank · 38 comment · 2 complexity · 1e2957dbc147056fb9c5ce2244b41d85 MD5 · raw file

  1. # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
  2. # vi: set ft=python sts=4 ts=4 sw=4 noet :
  3. # This file is part of Fail2Ban.
  4. #
  5. # Fail2Ban is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # Fail2Ban is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with Fail2Ban; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. # Author: Yaroslav Halchenko
  19. # Modified: Cyril Jaquier
  20. # $Revision$
  21. __author__ = 'Yaroslav Halhenko'
  22. __revision__ = '$Revision: $'
  23. __date__ = '$Date: $'
  24. __copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko'
  25. __license__ = 'GPL'
  26. import logging, os
  27. from ConfigParser import SafeConfigParser
  28. # Gets the instance of the logger.
  29. logSys = logging.getLogger("fail2ban.client.config")
  30. class SafeConfigParserWithIncludes(SafeConfigParser):
  31. """
  32. Class adds functionality to SafeConfigParser to handle included
  33. other configuration files (or may be urls, whatever in the future)
  34. File should have section [includes] and only 2 options implemented
  35. are 'files_before' and 'files_after' where files are listed 1 per
  36. line.
  37. Example:
  38. [INCLUDES]
  39. before = 1.conf
  40. 3.conf
  41. after = 1.conf
  42. It is a simple implementation, so just basic care is taken about
  43. recursion. Includes preserve right order, ie new files are
  44. inserted to the list of read configs before original, and their
  45. includes correspondingly so the list should follow the leaves of
  46. the tree.
  47. I wasn't sure what would be the right way to implement generic (aka c++
  48. template) so we could base at any *configparser class... so I will
  49. leave it for the future
  50. """
  51. SECTION_NAME = "INCLUDES"
  52. #@staticmethod
  53. def getIncludes(resource, seen = []):
  54. """
  55. Given 1 config resource returns list of included files
  56. (recursively) with the original one as well
  57. Simple loops are taken care about
  58. """
  59. # Use a short class name ;)
  60. SCPWI = SafeConfigParserWithIncludes
  61. parser = SafeConfigParser()
  62. parser.read(resource)
  63. resourceDir = os.path.dirname(resource)
  64. newFiles = [ ('before', []), ('after', []) ]
  65. if SCPWI.SECTION_NAME in parser.sections():
  66. for option_name, option_list in newFiles:
  67. if option_name in parser.options(SCPWI.SECTION_NAME):
  68. newResources = parser.get(SCPWI.SECTION_NAME, option_name)
  69. for newResource in newResources.split('\n'):
  70. if os.path.isabs(newResource):
  71. r = newResource
  72. else:
  73. r = os.path.join(resourceDir, newResource)
  74. if r in seen:
  75. continue
  76. s = seen + [resource]
  77. option_list += SCPWI.getIncludes(r, s)
  78. # combine lists
  79. return newFiles[0][1] + [resource] + newFiles[1][1]
  80. #print "Includes list for " + resource + " is " + `resources`
  81. getIncludes = staticmethod(getIncludes)
  82. def read(self, filenames):
  83. fileNamesFull = []
  84. if not isinstance(filenames, list):
  85. filenames = [ filenames ]
  86. for filename in filenames:
  87. fileNamesFull += SafeConfigParserWithIncludes.getIncludes(filename)
  88. logSys.debug("Reading files: %s" % fileNamesFull)
  89. return SafeConfigParser.read(self, fileNamesFull)