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