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 |