mirror of https://github.com/fail2ban/fail2ban
beautifier detect whether it can use unicode chars in stats table; asciified output of beautifier in test suite;
closes gh-3750pull/3776/head
parent
6fce23e7ba
commit
ab9d41e530
|
@ -21,8 +21,10 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko"
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko"
|
||||||
__license__ = "GPL"
|
__license__ = "GPL"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
from ..exceptions import UnknownJailException, DuplicateJailException
|
from ..exceptions import UnknownJailException, DuplicateJailException
|
||||||
from ..helpers import getLogger, logging
|
from ..helpers import getLogger, logging, PREFER_ENC
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
# Gets the instance of the logger.
|
||||||
logSys = getLogger(__name__)
|
logSys = getLogger(__name__)
|
||||||
|
@ -36,6 +38,11 @@ logSys = getLogger(__name__)
|
||||||
|
|
||||||
class Beautifier:
|
class Beautifier:
|
||||||
|
|
||||||
|
stdoutEnc = PREFER_ENC
|
||||||
|
if sys.stdout and sys.stdout.encoding is not None:
|
||||||
|
stdoutEnc = sys.stdout.encoding
|
||||||
|
encUtf = 1 if stdoutEnc.lower() == 'utf-8' else 0
|
||||||
|
|
||||||
def __init__(self, cmd = None):
|
def __init__(self, cmd = None):
|
||||||
self.__inputCmd = cmd
|
self.__inputCmd = cmd
|
||||||
|
|
||||||
|
@ -104,7 +111,11 @@ class Beautifier:
|
||||||
jail_stat(j, " " if i == len(jstat) else " | ")
|
jail_stat(j, " " if i == len(jstat) else " | ")
|
||||||
msg = "\n".join(msg)
|
msg = "\n".join(msg)
|
||||||
elif inC[0:1] == ['stats'] or inC[0:1] == ['statistics']:
|
elif inC[0:1] == ['stats'] or inC[0:1] == ['statistics']:
|
||||||
def _statstable(response):
|
chrTable = [
|
||||||
|
['|', '-', '|', 'x', 'x', '-', '|', '-'], ## ascii
|
||||||
|
["\u2551", "\u2550", "\u255F", "\u256B", "\u256C", "\u2569", "\u2502", "\u2500"] ## utf-8
|
||||||
|
];
|
||||||
|
def _statstable(response, ct):
|
||||||
tophead = ["Jail", "Backend", "Filter", "Actions"]
|
tophead = ["Jail", "Backend", "Filter", "Actions"]
|
||||||
headers = ["", "", "cur", "tot", "cur", "tot"]
|
headers = ["", "", "cur", "tot", "cur", "tot"]
|
||||||
minlens = [8, 8, 3, 3, 3, 3]
|
minlens = [8, 8, 3, 3, 3, 3]
|
||||||
|
@ -120,29 +131,31 @@ class Beautifier:
|
||||||
f = "%%%ds" if ralign[i] else "%%-%ds"
|
f = "%%%ds" if ralign[i] else "%%-%ds"
|
||||||
rfmt.append(f % lens[i])
|
rfmt.append(f % lens[i])
|
||||||
hfmt.append(f % lens[i])
|
hfmt.append(f % lens[i])
|
||||||
rfmt = [rfmt[0], rfmt[1], "%s \u2502 %s" % (rfmt[2], rfmt[3]), "%s \u2502 %s" % (rfmt[4], rfmt[5])]
|
rfmt = [rfmt[0], rfmt[1], "%s %s %s" % (rfmt[2], ct[6], rfmt[3]), "%s %s %s" % (rfmt[4], ct[6], rfmt[5])]
|
||||||
hfmt = [hfmt[0], hfmt[1], "%s \u2502 %s" % (hfmt[2], hfmt[3]), "%s \u2502 %s" % (hfmt[4], hfmt[5])]
|
hfmt = [hfmt[0], hfmt[1], "%s %s %s" % (hfmt[2], ct[6], hfmt[3]), "%s %s %s" % (hfmt[4], ct[6], hfmt[5])]
|
||||||
tlens = [lens[0], lens[1], 3 + lens[2] + lens[3], 3 + lens[4] + lens[5]]
|
tlens = [lens[0], lens[1], 3 + lens[2] + lens[3], 3 + lens[4] + lens[5]]
|
||||||
tfmt = [hfmt[0], hfmt[1], "%%-%ds" % (tlens[2],), "%%-%ds" % (tlens[3],)]
|
tfmt = [hfmt[0], hfmt[1], "%%-%ds" % (tlens[2],), "%%-%ds" % (tlens[3],)]
|
||||||
tsep = tfmt[0:2]
|
tsep = tfmt[0:2]
|
||||||
rfmt = " \u2551 ".join(rfmt)
|
rfmt = (" "+ct[0]+" ").join(rfmt)
|
||||||
hfmt = " \u2551 ".join(hfmt)
|
hfmt = (" "+ct[0]+" ").join(hfmt)
|
||||||
tfmt = " \u2551 ".join(tfmt)
|
tfmt = (" "+ct[0]+" ").join(tfmt)
|
||||||
tsep = " \u2551 ".join(tsep)
|
tsep = (" "+ct[0]+" ").join(tsep)
|
||||||
separator = ((tsep % tuple(tophead[0:2])) + " \u255F\u2500" +
|
separator = ((tsep % tuple(tophead[0:2])) + " "+ct[2]+ct[7] +
|
||||||
("\u2500\u256B\u2500".join(['\u2500' * n for n in tlens[2:]])) + '\u2500')
|
((ct[7]+ct[3]+ct[7]).join([ct[7] * n for n in tlens[2:]])) + ct[7])
|
||||||
ret = []
|
ret = []
|
||||||
ret.append(tfmt % tuple(["", ""]+tophead[2:]))
|
ret.append(" "+tfmt % tuple(["", ""]+tophead[2:]))
|
||||||
ret.append(separator)
|
ret.append(" "+separator)
|
||||||
ret.append(hfmt % tuple(headers))
|
ret.append(" "+hfmt % tuple(headers))
|
||||||
separator = "\u2550\u256C\u2550".join(['\u2550' * n for n in tlens]) + '\u2550'
|
separator = (ct[1]+ct[4]+ct[1]).join([ct[1] * n for n in tlens]) + ct[1]
|
||||||
ret.append(separator)
|
ret.append(ct[1]+separator)
|
||||||
for row in rows:
|
for row in rows:
|
||||||
ret.append(rfmt % tuple(row))
|
ret.append(" "+rfmt % tuple(row))
|
||||||
separator = "\u2550\u2569\u2550".join(['\u2550' * n for n in tlens]) + '\u2550'
|
separator = (ct[1]+ct[5]+ct[1]).join([ct[1] * n for n in tlens]) + ct[1]
|
||||||
ret.append(separator)
|
ret.append(ct[1]+separator)
|
||||||
return ret
|
return ret
|
||||||
msg = "\n".join(_statstable(response))
|
if not response:
|
||||||
|
return "No jails found."
|
||||||
|
msg = "\n".join(_statstable(response, chrTable[self.encUtf]))
|
||||||
elif len(inC) < 2:
|
elif len(inC) < 2:
|
||||||
pass # to few cmd args for below
|
pass # to few cmd args for below
|
||||||
elif inC[1] == "syslogsocket":
|
elif inC[1] == "syslogsocket":
|
||||||
|
|
|
@ -34,6 +34,7 @@ class BeautifierTest(unittest.TestCase):
|
||||||
""" Call before every test case """
|
""" Call before every test case """
|
||||||
super(BeautifierTest, self).setUp()
|
super(BeautifierTest, self).setUp()
|
||||||
self.b = Beautifier()
|
self.b = Beautifier()
|
||||||
|
self.b.encUtf = 0; ## we prefer ascii in test suite (see #3750)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
""" Call after every test case """
|
""" Call after every test case """
|
||||||
|
@ -170,22 +171,25 @@ class BeautifierTest(unittest.TestCase):
|
||||||
|
|
||||||
def testStatusStats(self):
|
def testStatusStats(self):
|
||||||
self.b.setInputCmd(["stats"])
|
self.b.setInputCmd(["stats"])
|
||||||
|
## no jails:
|
||||||
|
self.assertEqual(self.b.beautify({}), "No jails found.")
|
||||||
|
## 3 jails:
|
||||||
response = {
|
response = {
|
||||||
"ssh": ["systemd", (3, 6), (12, 24)],
|
"ssh": ["systemd", (3, 6), (12, 24)],
|
||||||
"exim4": ["pyinotify", (6, 12), (20, 20)],
|
"exim4": ["pyinotify", (6, 12), (20, 20)],
|
||||||
"jail-with-long-name": ["polling", (0, 0), (0, 0)]
|
"jail-with-long-name": ["polling", (0, 0), (0, 0)]
|
||||||
}
|
}
|
||||||
output = (""
|
output = (""
|
||||||
+ " ? ? Filter ? Actions \n"
|
+ " | | Filter | Actions \n"
|
||||||
+ "Jail ? Backend ????????????????????????\n"
|
+ " Jail | Backend |-----------x-----------\n"
|
||||||
+ " ? ? cur ? tot ? cur ? tot\n"
|
+ " | | cur | tot | cur | tot\n"
|
||||||
+ "????????????????????????????????????????????????????????\n"
|
+ "---------------------x-----------x-----------x-----------\n"
|
||||||
+ "ssh ? systemd ? 3 ? 6 ? 12 ? 24\n"
|
+ " ssh | systemd | 3 | 6 | 12 | 24\n"
|
||||||
+ "exim4 ? pyinotify ? 6 ? 12 ? 20 ? 20\n"
|
+ " exim4 | pyinotify | 6 | 12 | 20 | 20\n"
|
||||||
+ "jail-with-long-name ? polling ? 0 ? 0 ? 0 ? 0\n"
|
+ " jail-with-long-name | polling | 0 | 0 | 0 | 0\n"
|
||||||
+ "????????????????????????????????????????????????????????"
|
+ "---------------------------------------------------------"
|
||||||
)
|
)
|
||||||
response = self.b.beautify(response).encode('ascii', 'replace').decode('ascii')
|
response = self.b.beautify(response)
|
||||||
self.assertEqual(response, output)
|
self.assertEqual(response, output)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue