2 ##############################################################################
3 # pfixtools: a collection of postfix related tools #
5 # ________________________________________________________________________ #
7 # Redistribution and use in source and binary forms, with or without #
8 # modification, are permitted provided that the following conditions #
11 # 1. Redistributions of source code must retain the above copyright #
12 # notice, this list of conditions and the following disclaimer. #
13 # 2. Redistributions in binary form must reproduce the above copyright #
14 # notice, this list of conditions and the following disclaimer in the #
15 # documentation and/or other materials provided with the distribution. #
16 # 3. The names of its contributors may not be used to endorse or promote #
17 # products derived from this software without specific prior written #
20 # THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS #
21 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED #
22 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE #
23 # DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY #
24 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL #
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS #
26 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) #
27 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, #
28 # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN #
29 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #
30 # POSSIBILITY OF SUCH DAMAGE. #
31 ##############################################################################
33 # Copyright (c) 2008 Aymeric Augustin
36 # Convert the postgrey_whitelist_clients file to a format
37 # suitable for use with the postlicyd Postfix policy daemon
42 def process(infile, outfile):
45 outfile.write("# Do not edit, file autogenerated by %s\n" % sys.argv[0])
46 if len(sys.argv) > 1 and sys.argv[1] != '-':
47 outfile.write("# This file has been generated from %s\n" % sys.argv[1])
49 re_domain_name = re.compile(r'[a-z0-9.\-]+\.[a-z]+')
50 re_ip_address = re.compile(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
52 # Store each entry to avoid duplicates
57 if line == '\n' or line[0] == '#':
59 # IP addresses: keep as is
60 elif re_ip_address.match(line):
62 # Regexps: extract final constant part
64 line = line.rstrip(r'$/').replace(r'\.', r'.')
65 host = re_domain_name.findall(line)[-1]
67 if result not in entries:
68 entries.append(result)
70 # Domain names: prepend a dot if the domain name contains only one dot
71 elif re_domain_name.match(line):
72 if line.count('.') < 2:
76 if result not in entries:
77 entries.append(result)
79 # Unrecognized: report on stderr and comment in output
81 outfile.write('# IGNORED: ' + line)
82 sys.stderr.write("Couldn't process line: %s" % line)
85 if __name__ == '__main__':
87 # Check number of arguments
89 print "Usage: %s [input] [output]" % sys.argv[0]
90 print "If input/output is omitted or -, stdin/stdout is used."
93 # Parse first argument
94 if len(sys.argv) > 1 and sys.argv[1] != '-':
95 infile = open(sys.argv[1], 'r')
99 # Parse second argument
100 if len(sys.argv) > 2 and sys.argv[2] != '-':
101 if sys.argv[1] == sys.argv[2]:
102 print "Source file and destination file are identical, aborting"
104 if os.path.exists(sys.argv[2]):
105 print "Destination file %s already exists, aborting" % sys.argv[2]
107 outfile = open(sys.argv[2], 'w')
112 process(infile, outfile)