53a593043d611c455dec661739e5a82903e50290
[apps/pfixtools.git] / tools / postgrey_to_postlicyd.py
1 #!/usr/bin/env python
2 # encoding: utf-8
3
4 # Convert the postgrey_whitelist_clients file to a format
5 # suitable for use with the postlicyd Postfix policy daemon
6
7 # Copyright © 2008 Aymeric Augustin
8 # Released under the GPL
9
10 import os, re, sys
11
12
13 def process(infile, outfile):
14
15     re_domain_name = re.compile(r'[a-z0-9.\-]+\.[a-z]+')
16     re_ip_address = re.compile(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
17
18     outfile.write('# Automatically converted for use by postlicyd\n\n')
19
20     # Store each entry to avoid duplicates
21     entries = []
22
23     for line in infile:
24         # Comments: keep them
25         if line == '\n' or line[0] == '#':
26             outfile.write(line)
27         # IP addresses: keep as is
28         elif re_ip_address.match(line):
29             outfile.write(line)
30         # Regexps: extract final constant part
31         elif line[0] == '/':
32             line = line.rstrip(r'$/').replace(r'\.', r'.')
33             host = re_domain_name.findall(line)[-1]
34             result = host + '\n'
35             if result not in entries:
36                 entries.append(result)
37                 outfile.write(result)
38         # Domain names: prepend a dot if the domain name contains only one dot
39         elif re_domain_name.match(line):
40             if line.count('.') < 2:
41                 result = '.' + line
42             else:
43                 result = line
44             if result not in entries:
45                 entries.append(result)
46                 outfile.write(result)
47         # Unrecognized: report on stderr and comment in output
48         else:
49             outfile.write('# IGNORED: ' + line)
50             sys.stderr.write("Couldn't process line: %s" % line)
51
52
53 if __name__ == '__main__':
54
55     # Check number of arguments
56     if len(sys.argv) > 3:
57         print "Usage: %s [input] [output]" % sys.argv[0]
58         print "If input/output is omitted or -, stdin/stdout is used."
59         sys.exit(1)
60
61     # Parse first argument
62     if len(sys.argv) > 1 and sys.argv[1] != '-':
63         infile = open(sys.argv[1], 'r')
64     else:
65         infile = sys.stdin
66
67     # Parse second argument
68     if len(sys.argv) > 2 and sys.argv[2] != '-':
69         if sys.argv[1] == sys.argv[2]:
70             print "Source file and destination file are identical, aborting"
71             sys.exit(1)
72         if os.path.exists(sys.argv[2]):
73             print "Destination file %s already exists, aborting" % sys.argv[2]
74             sys.exit(1)
75         outfile = open(sys.argv[2], 'w')
76     else:
77         outfile = sys.stdout
78
79     # Do the processing
80     process(infile, outfile)