# HG changeset patch # User Paul Boddie # Date 1507059418 -7200 # Node ID f3c276a3ed693dbc40657eae6bc575b57c056eea # Parent cee37b136bac67e0bd4b221c8b2221f98e8c7d0e Reorganised iTIP message processing slightly, exposing useful functionality. diff -r cee37b136bac -r f3c276a3ed69 imiptools/__init__.py --- a/imiptools/__init__.py Tue Oct 03 21:36:04 2017 +0200 +++ b/imiptools/__init__.py Tue Oct 03 21:36:58 2017 +0200 @@ -362,12 +362,10 @@ # Handle parts. for part in msg.walk(): - if have_itip_part(part): - if self.debug: - print >>sys.stderr, "Handle method %s..." % part.get_param("method") + if self.debug and have_itip_part(part): + print >>sys.stderr, "Handle method %s..." % part.get_param("method") - handle_itip_part(part, handlers) - handled = True + handled = handle_itip_part(part, handlers) or handled # When processing outgoing messages, no replies or deliveries are # performed. diff -r cee37b136bac -r f3c276a3ed69 imiptools/content.py --- a/imiptools/content.py Tue Oct 03 21:36:04 2017 +0200 +++ b/imiptools/content.py Tue Oct 03 21:36:58 2017 +0200 @@ -70,12 +70,16 @@ """ Parse the given message 'part' and return a dictionary mapping calendar - object type names to lists of fragments, along with the method employed by - the parsed calendar object. + object type names to lists of fragments. If no iTIP content is found, None is returned. """ + # Ignore the part if not iTIP-related. + + if not have_itip_part(part): + return None + # Decode the data and parse it. f = StringIO(part.get_payload(decode=True)) @@ -95,51 +99,62 @@ if not consistent_methods(itip_method, method): return None - # Assert the object's method as the definitive one. + return itip + +def get_objects_from_itip(itip, handlers): + + """ + Return all objects provided by the given 'itip' mapping supported by the + given 'handlers'. + """ - return itip, itip_method + objects = [] + + # Look for different kinds of sections. + + if itip: + for name, items in itip.items(): + if name in handlers: + for item in items: + objects.append(Object({name : item})) + + return objects def handle_itip_part(part, handlers): """ Handle the given iTIP 'part' using the given 'handlers' dictionary. - Responses are set in each handler used to handle a message. + Responses are set in each handler used to handle a message. Return whether + the part could be handled. """ - itip_details = parse_itip_part(part) - if not itip_details: - return - - itip, method = itip_details - - # Look for different kinds of sections. + itip = parse_itip_part(part) + method = itip and get_value(itip, "METHOD") - all_results = [] - - for name, items in itip.items(): + for obj in get_objects_from_itip(itip, handlers): - # Get a handler for the given section. + # Get a handler for the given object type. - handler = handlers.get(name) + handler = handlers.get(obj.objtype) if not handler: continue - for item in items: + # Dispatch to a handler and obtain any response. - # Dispatch to a handler and obtain any response. + handler.set_object(obj) + handler.set_identity(method) - handler.set_object(Object({name : item})) - handler.set_identity(method) + if handler.is_usable(method): - if handler.is_usable(method): - - # Perform the method in a critical section. + # Perform the method in a critical section. - handler.acquire_lock() - try: - methods[method](handler)() - finally: - handler.release_lock() + handler.acquire_lock() + try: + methods[method](handler)() + finally: + handler.release_lock() + + return not not itip # Handler registry.