/
util.py
135 lines (116 loc) · 3.31 KB
/
util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import ieeemac
import IPy
import re
def isip(arg):
"""is arg an ip address?"""
try:
x = IPy.IP(arg)
return x.version()
except ValueError:
return False
_hash_re = re.compile("^[0-9a-fA-F]+$")
def ishash(arg):
return bool(_hash_re.match(arg))
def get_type(arg):
"""Return the type of the argument (mac, ip, hostname, or username)"""
ip_types = {
(4, False): "ip",
(6, False): "ip6",
(4, True): "cidr",
(6, True): "cidr6",
}
if ieeemac.ismac(arg):
return 'mac'
#macs can look like hashes, so check them first
if ishash(arg):
return 'hash'
ipver = isip(arg)
if ipver:
return ip_types[(ipver, '/' in arg)]
parts = arg.split(':')
if len(parts) == 2 and parts[1].isdigit():
return 'hostport'
if '.' in arg:
return 'hostname'
return 'username'
def is_local(networks, ip):
"""Return True if `ip` is in `networks`"""
for n in networks:
if ip in n:
return True
return False
def parse_query(s):
"""Split the query up into arguments and options
This should be easy to do using a regex, but I can't figure it out.
so, state machine it is."""
args = []
options = {}
#regex too complicated, state machine easy
#first split the string into components, respecting quotes
parts = []
in_quote = False
p = ""
for l in s:
if l.isspace() and not in_quote:
parts.append(p)
p = ""
elif l in '"\'' and not in_quote:
in_quote = l
elif l == in_quote:
in_quote = False
else:
p += l
if p:
parts.append(p)
#now separate each argument or option
for arg in parts:
if '=' in arg and "//" not in arg: #has a = but doesn't look like a URL
k, v = arg.split("=", 1)
v = v.strip('"') # remove the quotes
options[k] = v
else:
args.append(arg)
return args, options
def fmt_dict_array(ar, order=None, header=True):
#allow for an empty array
#if the array is empty and no order is paseed, return ""
#otherwise generate just the header
if not ar:
if not order:
return ""
first = dict([(x,x) for x in order])
else :
first = ar[0]
if header: #insert a new row of just the keys, the next loop will do the rest
new = dict([(x,str(x).capitalize()) for x in first.keys()])
new = [new]
else :
new = []
#figure out what the longest column in each row is
maxes = dict([(a,len(str(b))) for a,b in first.items()])
for x in new + ar:
for k, v in x.items():
size = len(str(v))
if size > maxes[k]:
maxes[k] = size
maxesfmt = dict([(x, "%%-%ds" % (y+1)) for x,y in maxes.items()])
if order:
it = order
else :
it = first #will iterate over the keys however
table = []
for x in new + ar:
row = []
for c in it:
row.append( maxesfmt[c] % x[c] )
line = " ".join(row).strip()
table.append(line)
return "\n".join(table)
def unique(lst):
out = []
seen = set()
for x in lst:
if x not in seen:
out.append(x)
seen.add(x)
return out