1# SPDX-License-Identifier: ISC
2# Copyright (c) Justus Winter <4winter@informatik.uni-hamburg.de>
3
4import os
5import re
6import collections
7import shlex
8
9from afew.configparser import ConfigParser
10from afew.FilterRegistry import all_filters
11
12user_config_dir = os.path.join(os.environ.get('XDG_CONFIG_HOME',
13                                              os.path.expanduser('~/.config')),
14                               'afew')
15user_config_dir = os.path.expandvars(user_config_dir)
16
17settings = ConfigParser()
18# preserve the capitalization of the keys.
19settings.optionxform = str
20
21settings.readfp(open(os.path.join(os.path.dirname(__file__), 'defaults', 'afew.config')))
22settings.read(os.path.join(user_config_dir, 'config'))
23
24# All the values for keys listed here are interpreted as ;-delimited lists
25value_is_a_list = ['tags', 'tags_blacklist']
26mail_mover_section = 'MailMover'
27
28section_re = re.compile(r'^(?P<name>[a-z_][a-z0-9_]*)(\((?P<parent_class>[a-z_][a-z0-9_]*)\)|\.(?P<index>\d+))?$', re.I)
29
30
31def get_filter_chain(database):
32    filter_chain = []
33
34    for section in settings.sections():
35        if section == 'global' or section == mail_mover_section:
36            continue
37
38        match = section_re.match(section)
39        if not match:
40            raise SyntaxError('Malformed section title %r.' % section)
41
42        kwargs = dict(
43            (key, settings.get(section, key))
44            if key not in value_is_a_list else
45            (key, settings.get_list(section, key))
46            for key in settings.options(section)
47        )
48
49        if match.group('parent_class'):
50            try:
51                parent_class = all_filters[match.group('parent_class')]
52            except KeyError:
53                raise NameError(
54                    'Parent class %r not found in filter type definition %r.' % (match.group('parent_class'), section))
55
56            new_type = type(match.group('name'), (parent_class,), kwargs)
57            all_filters[match.group('name')] = new_type
58        else:
59            try:
60                klass = all_filters[match.group('name')]
61            except KeyError:
62                raise NameError('Filter type %r not found.' % match.group('name'))
63            filter_chain.append(klass(database, **kwargs))
64
65    return filter_chain
66
67
68def get_mail_move_rules():
69    rule_pattern = re.compile(r"'(.+?)':((?P<quote>['\"])(.*?)(?P=quote)|\S+)")
70    if settings.has_option(mail_mover_section, 'folders'):
71        all_rules = collections.OrderedDict()
72
73        for folder in shlex.split(settings.get(mail_mover_section, 'folders')):
74            if settings.has_option(mail_mover_section, folder):
75                rules = collections.OrderedDict()
76                raw_rules = re.findall(rule_pattern,
77                                       settings.get(mail_mover_section, folder))
78                for rule in raw_rules:
79                    query = rule[0]
80                    destination = rule[3] or rule[1]
81                    rules[query] = destination
82                all_rules[folder] = rules
83            else:
84                raise NameError("No rules specified for maildir '{}'.".format(folder))
85
86        return all_rules
87    else:
88        raise NameError("No folders defined to move mails from.")
89
90
91def get_mail_move_age():
92    max_age = 0
93    if settings.has_option(mail_mover_section, 'max_age'):
94        max_age = settings.get(mail_mover_section, 'max_age')
95    return max_age
96
97
98def get_mail_move_rename():
99    rename = False
100    if settings.has_option(mail_mover_section, 'rename'):
101        rename = settings.get(mail_mover_section, 'rename').lower() == 'true'
102    return rename
103