3

I have to modify a config file which has similar structure to an .ini file. But the problem is that config file has multiple lines for single value. How to modify it?

For example here is the configuration I want to modify.

[INCLUDES]

# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf

[Definition]

_daemon = sshd


failregex = ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|error) for .* from <HOST>( via \S+)?\s*$
        ^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
        ^%(__prefix_line)sFailed \S+ for .*? from <HOST>(?: port \d*)?(?: ssh\d*)?(: (ruser .*|(\S+ ID \S+ \(serial \d+\) CA )?\S+ %(__md5hex)s(, client user ".*", client host ".*")?))?\s*$
        ^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
        ^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
        ^%(__prefix_line)sUser .+ from <HOST> not allowed because not listed in AllowUsers\s*$
        ^%(__prefix_line)sUser .+ from <HOST> not allowed because listed in DenyUsers\s*$
        ^%(__prefix_line)sUser .+ from <HOST> not allowed because not in any group\s*$
        ^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
        ^%(__prefix_line)sReceived disconnect from <HOST>: 3: \S+: Auth fail$
        ^%(__prefix_line)sUser .+ from <HOST> not allowed because a group is listed in DenyGroups\s*$
        ^%(__prefix_line)sUser .+ from <HOST> not allowed because none of user's groups are listed in AllowGroups\s*$

ignoreregex =

If I use \n while writing the string it is showing as

before = test1 \n test2 \n test3 \n test4

What could be a solution for this? Is it even possible through ConfigParser?

r_yu
  • 41
  • 1
  • 7
  • Did you read [the documentation](https://docs.python.org/2/library/configparser.html), including its reference to [this document](http://tools.ietf.org/html/rfc822.html)? – BrenBarn Nov 26 '15 at 05:00
  • yes, I read the first documentation. I am using set() method to set values and then write() to write it back to the file. But it is not writing values in multiple line. It is writing it as it is and printing '\n' in file. I am using safeconfigparser object. – r_yu Nov 26 '15 at 05:07
  • Does it read back correctly? It shouldn't matter what it looks like visually in the file as long as it can be parsed correctly. – BrenBarn Nov 26 '15 at 05:09
  • I have yet not tested it. It is a fail2ban filters configuration file. – r_yu Nov 26 '15 at 05:20
  • If you're going to be using the file with some external source (i.e., not reading it back in with Python's own ConfigParser), you'll need to do some research and testing to be sure the formats are compatible. There are many programs out there reading and writing config files that look similar but differ in various edge cases (like the one you're asking about). ConfigParser is just one variation and there's no guarantee it will interoperate properly with any other similar format. – BrenBarn Nov 26 '15 at 05:24
  • Hmm. So how should I approach to this problem? Could you suggest any other library which will be helpful in this situation? Or should I write a program specifically for this? – r_yu Nov 26 '15 at 05:37
  • I don't know anything about fail2ban or its format. Like I said, if you're going to use the data file with some external program, you need to find out what format that program expects the data in. That means you need to ask people who use or make fail2ban what kinds of config it can and can't read. In other words, your question at this point is more about fail2ban than about Python. – BrenBarn Nov 26 '15 at 05:48
  • I'm confused. Writing a multiline value such as `config.set('INCLUDES', 'before', 'test1\ntest2\ntest3\n')` results in a multiline value in the config file. Where do you see `before = test1 \n test2 \n test3 \n test4`? This is one reason why actual examples help. – tdelaney Nov 26 '15 at 05:53
  • @tdelaney: It is working okay if you do it like that. But when I am passing it from the database it is printing '\n'. [here is the code block](http://pastebin.com/TKn4Ut1L) – r_yu Nov 26 '15 at 06:03
  • @r_yu: Maybe that's because the database has `\n` in there instead of an actual newline. Check the data. – BrenBarn Nov 26 '15 at 06:22
  • @tdelaney: yes there is '\n'. But what difference does it make? Isn't '\n' used for an new line? In your example also it is performing the same. – r_yu Nov 26 '15 at 06:27

1 Answers1

0

A workaround:

A way you could do this is add each line to a new option. Like:

[SECTION]
failregex = ...
replace 1 = ...
replace 2 = ...

After that you just open the ini file as a text file and find each replace option and replace "replace 1 =" with a space. According to this post an indent is enough for configparser to handle it as multiline value: New lines with ConfigParser?