1.1 --- a/imip_manager.py Sun Feb 08 18:39:03 2015 +0100
1.2 +++ b/imip_manager.py Sun Feb 08 20:06:37 2015 +0100
1.3 @@ -158,7 +158,12 @@
1.4 uid = "imip-agent-%s-%s" % (utcnow, get_address(self.user))
1.5
1.6 freebusy = self.store.get_freebusy(self.user)
1.7 - parts.append(to_part("PUBLISH", [make_freebusy(freebusy, uid, self.user)]))
1.8 + user_attr = self.messenger and self.messenger.sender != get_address(self.user) and \
1.9 + {"SENT-BY" : get_uri(self.messenger.sender)} or {}
1.10 +
1.11 + parts.append(to_part("PUBLISH", [
1.12 + make_freebusy(freebusy, uid, self.user, user_attr)
1.13 + ]))
1.14
1.15 message = self.messenger.make_outgoing_message(parts, recipients, outgoing_bcc=sender)
1.16 self.messenger.sendmail(recipients, message.as_string(), outgoing_bcc=sender)
2.1 --- a/imiptools/__init__.py Sun Feb 08 18:39:03 2015 +0100
2.2 +++ b/imiptools/__init__.py Sun Feb 08 20:06:37 2015 +0100
2.3 @@ -201,6 +201,8 @@
2.4 organiser = get_uri(recipient)
2.5 preferences = Preferences(organiser)
2.6
2.7 + organiser_attr = self.messenger and {"SENT-BY" : get_uri(self.messenger.sender)} or {}
2.8 +
2.9 if preferences.get("freebusy_sharing") == "share" and \
2.10 preferences.get("freebusy_bundling") == "always":
2.11
2.12 @@ -210,7 +212,7 @@
2.13 uid = "imip-agent-%s-%s" % (utcnow, recipient)
2.14
2.15 freebusy = imip_store.FileStore().get_freebusy(organiser)
2.16 - return to_part("PUBLISH", [make_freebusy(freebusy, uid, organiser)])
2.17 + return to_part("PUBLISH", [make_freebusy(freebusy, uid, organiser, organiser_attr)])
2.18
2.19 return None
2.20
3.1 --- a/imiptools/content.py Sun Feb 08 18:39:03 2015 +0100
3.2 +++ b/imiptools/content.py Sun Feb 08 20:06:37 2015 +0100
3.3 @@ -250,17 +250,36 @@
3.4 else:
3.5 return mapping
3.6
3.7 - def require_organiser_and_attendees(self, from_organiser=True):
3.8 + def require_organiser(self, from_organiser=True):
3.9
3.10 """
3.11 - Return the organiser and attendees for the current object, filtered for
3.12 - the recipient of interest. Return None if no identities are eligible.
3.13 + Return the organiser for the current object, filtered for the sender or
3.14 + recipient of interest. Return None if no identities are eligible.
3.15 +
3.16 + The organiser identity is normalized.
3.17 + """
3.18 +
3.19 + organiser_item = uri_item(self.obj.get_item("ORGANIZER"))
3.20 +
3.21 + # Only provide details for an organiser who sent/receives the message.
3.22 +
3.23 + organiser_filter_fn = from_organiser and self.filter_by_senders or self.filter_by_recipient
3.24
3.25 - Organiser and attendee identities are provided as lower case values.
3.26 + if not organiser_filter_fn(dict([organiser_item])):
3.27 + return None
3.28 +
3.29 + return organiser_item
3.30 +
3.31 + def require_attendees(self, from_organiser=True):
3.32 +
3.33 + """
3.34 + Return the attendees for the current object, filtered for the sender or
3.35 + recipient of interest. Return None if no identities are eligible.
3.36 +
3.37 + The attendee identities are normalized.
3.38 """
3.39
3.40 attendee_map = uri_dict(self.obj.get_value_map("ATTENDEE"))
3.41 - organiser_item = uri_item(self.obj.get_item("ORGANIZER"))
3.42
3.43 # Only provide details for attendees who sent/receive the message.
3.44
3.45 @@ -270,14 +289,21 @@
3.46 for attendee in attendee_filter_fn(attendee_map):
3.47 attendees[attendee] = attendee_map[attendee]
3.48
3.49 - if not attendees or not organiser_item:
3.50 - return None
3.51 + return attendees
3.52 +
3.53 + def require_organiser_and_attendees(self, from_organiser=True):
3.54 +
3.55 + """
3.56 + Return the organiser and attendees for the current object, filtered for
3.57 + the recipient of interest. Return None if no identities are eligible.
3.58
3.59 - # Only provide details for an organiser who sent/receives the message.
3.60 + Organiser and attendee identities are normalized.
3.61 + """
3.62
3.63 - organiser_filter_fn = from_organiser and self.filter_by_senders or self.filter_by_recipient
3.64 + organiser_item = self.require_organiser(from_organiser)
3.65 + attendees = self.require_attendees(from_organiser)
3.66
3.67 - if not organiser_filter_fn(dict([organiser_item])):
3.68 + if not attendees or not organiser_item:
3.69 return None
3.70
3.71 return organiser_item, attendees
4.1 --- a/imiptools/data.py Sun Feb 08 18:39:03 2015 +0100
4.2 +++ b/imiptools/data.py Sun Feb 08 20:06:37 2015 +0100
4.3 @@ -101,21 +101,22 @@
4.4 nodes
4.5 )
4.6
4.7 -def make_freebusy(freebusy, uid, organiser, attendee=None):
4.8 +def make_freebusy(freebusy, uid, organiser, organiser_attr=None, attendee=None, attendee_attr=None):
4.9
4.10 """
4.11 Return a calendar node defining the free/busy details described in the given
4.12 - 'freebusy' list, employing the given 'uid', for the given 'organiser', with
4.13 - the optional 'attendee' providing recipient details.
4.14 + 'freebusy' list, employing the given 'uid', for the given 'organiser' and
4.15 + optional 'organiser_attr', with the optional 'attendee' providing recipient
4.16 + details together with the optional 'attendee_attr'.
4.17 """
4.18
4.19 record = []
4.20 rwrite = record.append
4.21
4.22 - rwrite(("ORGANIZER", {}, organiser))
4.23 + rwrite(("ORGANIZER", organiser_attr or {}, organiser))
4.24
4.25 if attendee:
4.26 - rwrite(("ATTENDEE", {}, attendee))
4.27 + rwrite(("ATTENDEE", attendee_attr or {}, attendee))
4.28
4.29 rwrite(("UID", {}, uid))
4.30
5.1 --- a/imiptools/handlers/common.py Sun Feb 08 18:39:03 2015 +0100
5.2 +++ b/imiptools/handlers/common.py Sun Feb 08 20:06:37 2015 +0100
5.3 @@ -19,7 +19,7 @@
5.4 this program. If not, see <http://www.gnu.org/licenses/>.
5.5 """
5.6
5.7 -from imiptools.data import get_address, make_freebusy, to_part
5.8 +from imiptools.data import get_address, get_uri, make_freebusy, to_part
5.9
5.10 class CommonFreebusy:
5.11
5.12 @@ -47,7 +47,13 @@
5.13
5.14 for attendee, attendee_attr in attendees.items():
5.15 freebusy = self.store.get_freebusy(attendee)
5.16 - rwrite(make_freebusy(freebusy, self.uid, organiser, attendee))
5.17 +
5.18 + # Indicate the actual sender of the reply.
5.19 +
5.20 + if self.messenger:
5.21 + attendee_attr["SENT-BY"] = get_uri(self.messenger.sender)
5.22 +
5.23 + rwrite(make_freebusy(freebusy, self.uid, organiser, organiser_attr, attendee, attendee_attr))
5.24
5.25 # Return the reply.
5.26
6.1 --- a/imiptools/handlers/person.py Sun Feb 08 18:39:03 2015 +0100
6.2 +++ b/imiptools/handlers/person.py Sun Feb 08 20:06:37 2015 +0100
6.3 @@ -79,15 +79,22 @@
6.4
6.5 "Record free/busy information for the received information."
6.6
6.7 - oa = self.require_organiser_and_attendees(from_organiser)
6.8 - if not oa:
6.9 - return
6.10 + if from_organiser:
6.11 + organiser_item = self.require_organiser(from_organiser)
6.12 + if not organiser_item:
6.13 + return
6.14
6.15 - organiser_item, attendees = oa
6.16 - senders = from_organiser and [organiser_item] or attendees
6.17 + senders = [organiser_item]
6.18 + else:
6.19 + oa = self.require_organiser_and_attendees(from_organiser)
6.20 + if not oa:
6.21 + return
6.22
6.23 - if not senders:
6.24 - return
6.25 + organiser_item, attendees = oa
6.26 + senders = attendees.items()
6.27 +
6.28 + if not senders:
6.29 + return
6.30
6.31 freebusy = []
6.32