imip-agent

Annotated imiptools/content.py

1465:0c623c86704f
2020-08-03 Paul Boddie Changed diagram font to sans-serif.
paul@48 1
#!/usr/bin/env python
paul@48 2
paul@48 3
"""
paul@596 4
The handler invocation mechanism.
paul@146 5
paul@1210 6
Copyright (C) 2014, 2015, 2017 Paul Boddie <paul@boddie.org.uk>
paul@146 7
paul@146 8
This program is free software; you can redistribute it and/or modify it under
paul@146 9
the terms of the GNU General Public License as published by the Free Software
paul@146 10
Foundation; either version 3 of the License, or (at your option) any later
paul@146 11
version.
paul@146 12
paul@146 13
This program is distributed in the hope that it will be useful, but WITHOUT
paul@146 14
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
paul@146 15
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
paul@146 16
details.
paul@146 17
paul@146 18
You should have received a copy of the GNU General Public License along with
paul@146 19
this program.  If not, see <http://www.gnu.org/licenses/>.
paul@48 20
"""
paul@48 21
paul@1210 22
from imiptools.config import settings
paul@418 23
from imiptools.data import Object, parse_object, get_value
paul@48 24
paul@48 25
try:
paul@48 26
    from cStringIO import StringIO
paul@48 27
except ImportError:
paul@48 28
    from StringIO import StringIO
paul@48 29
paul@1210 30
IMIP_COUNTER_AS_REQUEST = settings["IMIP_COUNTER_AS_REQUEST"]
paul@1210 31
paul@224 32
def handle_itip_part(part, handlers):
paul@48 33
paul@48 34
    """
paul@227 35
    Handle the given iTIP 'part' using the given 'handlers' dictionary.
paul@224 36
paul@224 37
    Return a list of responses, each response being a tuple of the form
paul@224 38
    (outgoing-recipients, message-part).
paul@48 39
    """
paul@48 40
paul@48 41
    method = part.get_param("method")
paul@914 42
    method = method and method.upper()
paul@48 43
paul@48 44
    # Decode the data and parse it.
paul@48 45
paul@48 46
    f = StringIO(part.get_payload(decode=True))
paul@48 47
paul@48 48
    itip = parse_object(f, part.get_content_charset(), "VCALENDAR")
paul@48 49
paul@48 50
    # Ignore the part if not a calendar object.
paul@48 51
paul@48 52
    if not itip:
paul@228 53
        return
paul@48 54
paul@48 55
    # Require consistency between declared and employed methods.
paul@48 56
paul@918 57
    itip_method = get_value(itip, "METHOD")
paul@918 58
paul@918 59
    if itip_method == method or \
paul@918 60
       IMIP_COUNTER_AS_REQUEST and itip_method == "COUNTER" and method == "REQUEST":
paul@918 61
paul@918 62
        # Assert the object's method as the definitive one.
paul@918 63
paul@918 64
        method = itip_method
paul@48 65
paul@48 66
        # Look for different kinds of sections.
paul@48 67
paul@60 68
        all_results = []
paul@48 69
paul@226 70
        for name, items in itip.items():
paul@226 71
paul@226 72
            # Get a handler for the given section.
paul@226 73
paul@226 74
            handler = handlers.get(name)
paul@226 75
            if not handler:
paul@226 76
                continue
paul@226 77
paul@226 78
            for item in items:
paul@48 79
paul@48 80
                # Dispatch to a handler and obtain any response.
paul@48 81
paul@226 82
                handler.set_object(Object({name : item}))
paul@729 83
                handler.set_identity(method)
paul@729 84
paul@727 85
                if handler.is_usable(method):
paul@730 86
paul@730 87
                    # Perform the method in a critical section.
paul@730 88
paul@730 89
                    handler.acquire_lock()
paul@730 90
                    try:
paul@730 91
                        methods[method](handler)()
paul@730 92
                    finally:
paul@730 93
                        handler.release_lock()
paul@48 94
paul@48 95
# Handler registry.
paul@48 96
paul@48 97
methods = {
paul@48 98
    "ADD"            : lambda handler: handler.add,
paul@48 99
    "CANCEL"         : lambda handler: handler.cancel,
paul@48 100
    "COUNTER"        : lambda handler: handler.counter,
paul@48 101
    "DECLINECOUNTER" : lambda handler: handler.declinecounter,
paul@48 102
    "PUBLISH"        : lambda handler: handler.publish,
paul@48 103
    "REFRESH"        : lambda handler: handler.refresh,
paul@48 104
    "REPLY"          : lambda handler: handler.reply,
paul@48 105
    "REQUEST"        : lambda handler: handler.request,
paul@48 106
    }
paul@48 107
paul@48 108
# vim: tabstop=4 expandtab shiftwidth=4