1.1 --- a/docs/preferences.txt Sat Sep 12 18:13:10 2015 +0200
1.2 +++ b/docs/preferences.txt Sat Sep 12 18:15:26 2015 +0200
1.3 @@ -73,6 +73,27 @@
1.4
1.5 summary-only deliver only a summary of the message
1.6
1.7 + summary-wraps-message deliver a summary that includes the original message
1.8 + as an attachment
1.9 +
1.10 +organiser_replacement
1.11 +---------------------
1.12 +
1.13 +Default: attendee
1.14 +Alternatives: (see below)
1.15 +
1.16 +Indicate whether the organiser of an event can be replaced and the nature of
1.17 +any replacement:
1.18 +
1.19 + any any identity, regardless of whether it is already
1.20 + present or even previously unknown, may become the
1.21 + organiser
1.22 +
1.23 + attendee any new organiser must be a previously-recognised
1.24 + attendee
1.25 +
1.26 + never forbid the replacement of an event's organiser
1.27 +
1.28 participating
1.29 -------------
1.30
2.1 --- a/imiptools/client.py Sat Sep 12 18:13:10 2015 +0200
2.2 +++ b/imiptools/client.py Sat Sep 12 18:15:26 2015 +0200
2.3 @@ -39,6 +39,13 @@
2.4 default_window_size = 100
2.5
2.6 def __init__(self, user, messenger=None, store=None, publisher=None, preferences_dir=None):
2.7 +
2.8 + """
2.9 + Initialise a calendar client with the current 'user', plus any
2.10 + 'messenger', 'store' and 'publisher' objects, indicating any specific
2.11 + 'preferences_dir'.
2.12 + """
2.13 +
2.14 self.user = user
2.15 self.messenger = messenger
2.16 self.store = store or imip_store.FileStore()
2.17 @@ -90,6 +97,10 @@
2.18 prefs = self.get_preferences()
2.19 return prefs and prefs.get("event_refreshing") == "always" or False
2.20
2.21 + def allow_organiser_replacement(self):
2.22 + prefs = self.get_preferences()
2.23 + return prefs and prefs.get("organiser_replacement", "attendee") or False
2.24 +
2.25 def have_manager(self):
2.26 return MANAGER_INTERFACE
2.27
2.28 @@ -337,6 +348,36 @@
2.29
2.30 # Object-related tests.
2.31
2.32 + def is_recognised_organiser(self, organiser):
2.33 +
2.34 + """
2.35 + Return whether the given 'organiser' is recognised from
2.36 + previously-received details. If no stored details exist, True is
2.37 + returned.
2.38 + """
2.39 +
2.40 + obj = self.get_stored_object_version()
2.41 + if obj:
2.42 + stored_organiser = get_uri(obj.get_value("ORGANIZER"))
2.43 + return stored_organiser == organiser
2.44 + else:
2.45 + return True
2.46 +
2.47 + def is_recognised_attendee(self, attendee):
2.48 +
2.49 + """
2.50 + Return whether the given 'attendee' is recognised from
2.51 + previously-received details. If no stored details exist, True is
2.52 + returned.
2.53 + """
2.54 +
2.55 + obj = self.get_stored_object_version()
2.56 + if obj:
2.57 + stored_attendees = uri_dict(obj.get_value_map("ATTENDEE"))
2.58 + return stored_attendees.has_key(attendee)
2.59 + else:
2.60 + return True
2.61 +
2.62 def get_attendance(self, user=None, obj=None):
2.63
2.64 """
3.1 --- a/imiptools/handlers/__init__.py Sat Sep 12 18:13:10 2015 +0200
3.2 +++ b/imiptools/handlers/__init__.py Sat Sep 12 18:15:26 2015 +0200
3.3 @@ -157,10 +157,17 @@
3.4
3.5 # Test against any previously-received organiser details.
3.6
3.7 - obj = self.get_stored_object_version()
3.8 - if obj:
3.9 - stored_organiser = get_uri(obj.get_value("ORGANIZER"))
3.10 - if stored_organiser != organiser:
3.11 + if not self.is_recognised_organiser(organiser):
3.12 + replacement = self.allow_organiser_replacement()
3.13 +
3.14 + # Allow any organiser as a replacement where indicated.
3.15 +
3.16 + if replacement == "any":
3.17 + pass
3.18 +
3.19 + # Allow any recognised attendee as a replacement where indicated.
3.20 +
3.21 + elif replacement != "attendee" or not self.is_recognised_attendee(organiser):
3.22 return None
3.23
3.24 return organiser_item
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/tests/templates/event-request-imposter-attendee.txt Sat Sep 12 18:15:26 2015 +0200
4.3 @@ -0,0 +1,36 @@
4.4 +Content-Type: multipart/alternative; boundary="===============0047278175=="
4.5 +MIME-Version: 1.0
4.6 +From: harvey.horse@example.com
4.7 +To: resource-room-confroom@example.com
4.8 +Subject: Invitation!
4.9 +
4.10 +--===============0047278175==
4.11 +Content-Type: text/plain; charset="us-ascii"
4.12 +MIME-Version: 1.0
4.13 +Content-Transfer-Encoding: 7bit
4.14 +
4.15 +This message contains an event. The organiser is not the real organiser but is an attendee.
4.16 +
4.17 +--===============0047278175==
4.18 +MIME-Version: 1.0
4.19 +Content-Transfer-Encoding: 7bit
4.20 +Content-Type: text/calendar; charset="us-ascii"; method="REQUEST"
4.21 +
4.22 +BEGIN:VCALENDAR
4.23 +PRODID:-//imip-agent/test//EN
4.24 +METHOD:REQUEST
4.25 +VERSION:2.0
4.26 +BEGIN:VEVENT
4.27 +ORGANIZER:mailto:harvey.horse@example.com
4.28 +ATTENDEE;ROLE=CHAIR:mailto:paul.boddie@example.com
4.29 +ATTENDEE;RSVP=TRUE:mailto:resource-room-confroom@example.com
4.30 +ATTENDEE;RSVP=TRUE:mailto:harvey.horse@example.com
4.31 +DTSTAMP:20141125T004600Z
4.32 +DTSTART;TZID=Europe/Oslo:20141126T161500
4.33 +DTEND;TZID=Europe/Oslo:20141126T170000
4.34 +SUMMARY:Meeting at 4:30pm
4.35 +UID:event1@example.com
4.36 +END:VEVENT
4.37 +END:VCALENDAR
4.38 +
4.39 +--===============0047278175==--
5.1 --- a/tests/templates/event-request-imposter.txt Sat Sep 12 18:13:10 2015 +0200
5.2 +++ b/tests/templates/event-request-imposter.txt Sat Sep 12 18:15:26 2015 +0200
5.3 @@ -24,6 +24,7 @@
5.4 ORGANIZER:mailto:vincent.vole@example.com
5.5 ATTENDEE;ROLE=CHAIR:mailto:paul.boddie@example.com
5.6 ATTENDEE;RSVP=TRUE:mailto:resource-room-confroom@example.com
5.7 +ATTENDEE;RSVP=TRUE:mailto:harvey.horse@example.com
5.8 DTSTAMP:20141125T004600Z
5.9 DTSTART;TZID=Europe/Oslo:20141126T163000
5.10 DTEND;TZID=Europe/Oslo:20141126T170000
6.1 --- a/tests/templates/event-request.txt Sat Sep 12 18:13:10 2015 +0200
6.2 +++ b/tests/templates/event-request.txt Sat Sep 12 18:15:26 2015 +0200
6.3 @@ -22,6 +22,7 @@
6.4 BEGIN:VEVENT
6.5 ORGANIZER:mailto:paul.boddie@example.com
6.6 ATTENDEE;ROLE=CHAIR:mailto:paul.boddie@example.com
6.7 +ATTENDEE;RSVP=TRUE:mailto:harvey.horse@example.com
6.8 ATTENDEE;RSVP=TRUE:mailto:resource-room-confroom@example.com
6.9 DTSTAMP:20141125T004600Z
6.10 DTSTART;TZID=Europe/Oslo:20141126T160000
7.1 --- a/tests/test_resource_invitation.sh Sat Sep 12 18:13:10 2015 +0200
7.2 +++ b/tests/test_resource_invitation.sh Sat Sep 12 18:15:26 2015 +0200
7.3 @@ -58,24 +58,6 @@
7.4 && echo "Success" \
7.5 || echo "Failed"
7.6
7.7 - "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter.txt" 2>> $ERROR \
7.8 -| "$SHOWMAIL" \
7.9 -> out2i.tmp
7.10 -
7.11 - ! grep -q 'METHOD:REPLY' out2i.tmp \
7.12 -&& echo "Success" \
7.13 -|| echo "Failed"
7.14 -
7.15 - "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \
7.16 -| "$SHOWMAIL" \
7.17 -> out3i.tmp
7.18 -
7.19 - grep -q 'METHOD:REPLY' out3i.tmp \
7.20 -&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out3i.tmp \
7.21 -&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out3i.tmp \
7.22 -&& echo "Success" \
7.23 -|| echo "Failed"
7.24 -
7.25 "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-conflict.txt" 2>> $ERROR \
7.26 | "$SHOWMAIL" \
7.27 > out4.tmp
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/tests/test_resource_invitation_imposter.sh Sat Sep 12 18:15:26 2015 +0200
8.3 @@ -0,0 +1,194 @@
8.4 +#!/bin/sh
8.5 +
8.6 +THIS_DIR=`dirname $0`
8.7 +
8.8 +TEMPLATES="$THIS_DIR/templates"
8.9 +RESOURCE_SCRIPT="$THIS_DIR/../imip_resource.py"
8.10 +SHOWMAIL="$THIS_DIR/../tools/showmail.py"
8.11 +STORE=/tmp/store
8.12 +STATIC=/tmp/static
8.13 +PREFS=/tmp/prefs
8.14 +ARGS="-S $STORE -P $STATIC -p $PREFS -d"
8.15 +USER="mailto:resource-room-confroom@example.com"
8.16 +ERROR=err.tmp
8.17 +
8.18 +rm -r $STORE
8.19 +rm -r $STATIC
8.20 +rm -r $PREFS
8.21 +rm $ERROR
8.22 +rm out*.tmp
8.23 +
8.24 +mkdir -p "$PREFS/$USER"
8.25 +echo 'Europe/Oslo' > "$PREFS/$USER/TZID"
8.26 +echo 'share' > "$PREFS/$USER/freebusy_sharing"
8.27 +echo 'never' > "$PREFS/$USER/organiser_replacement"
8.28 +
8.29 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request-all.txt" 2>> $ERROR \
8.30 +| "$SHOWMAIL" \
8.31 +> out0.tmp
8.32 +
8.33 + grep -q 'METHOD:REPLY' out0.tmp \
8.34 +&& ! grep -q '^FREEBUSY' out0.tmp \
8.35 +&& echo "Success" \
8.36 +|| echo "Failed"
8.37 +
8.38 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \
8.39 +| "$SHOWMAIL" \
8.40 +> out1.tmp
8.41 +
8.42 + grep -q 'METHOD:REPLY' out1.tmp \
8.43 +&& ! grep -q '^FREEBUSY' out1.tmp \
8.44 +&& echo "Success" \
8.45 +|| echo "Failed"
8.46 +
8.47 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request.txt" 2>> $ERROR \
8.48 +| "$SHOWMAIL" \
8.49 +> out2.tmp
8.50 +
8.51 + grep -q 'METHOD:REPLY' out2.tmp \
8.52 +&& grep -q 'ATTENDEE;PARTSTAT=ACCEPTED' out2.tmp \
8.53 +&& echo "Success" \
8.54 +|| echo "Failed"
8.55 +
8.56 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \
8.57 +| "$SHOWMAIL" \
8.58 +> out3.tmp
8.59 +
8.60 + grep -q 'METHOD:REPLY' out3.tmp \
8.61 +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out3.tmp \
8.62 +&& echo "Success" \
8.63 +|| echo "Failed"
8.64 +
8.65 +# Try to change to an unrecognised organiser.
8.66 +
8.67 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter.txt" 2>> $ERROR \
8.68 +| "$SHOWMAIL" \
8.69 +> out4.tmp
8.70 +
8.71 + ! grep -q 'METHOD:REPLY' out4.tmp \
8.72 +&& echo "Success" \
8.73 +|| echo "Failed"
8.74 +
8.75 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \
8.76 +| "$SHOWMAIL" \
8.77 +> out5.tmp
8.78 +
8.79 + grep -q 'METHOD:REPLY' out5.tmp \
8.80 +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out5.tmp \
8.81 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out5.tmp \
8.82 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out5.tmp \
8.83 +&& echo "Success" \
8.84 +|| echo "Failed"
8.85 +
8.86 +# Try to change to an attendee as organiser.
8.87 +
8.88 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter-attendee.txt" 2>> $ERROR \
8.89 +| "$SHOWMAIL" \
8.90 +> out6.tmp
8.91 +
8.92 + ! grep -q 'METHOD:REPLY' out6.tmp \
8.93 +&& echo "Success" \
8.94 +|| echo "Failed"
8.95 +
8.96 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \
8.97 +| "$SHOWMAIL" \
8.98 +> out7.tmp
8.99 +
8.100 + grep -q 'METHOD:REPLY' out7.tmp \
8.101 +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out7.tmp \
8.102 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out7.tmp \
8.103 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out7.tmp \
8.104 +&& echo "Success" \
8.105 +|| echo "Failed"
8.106 +
8.107 +# Change the policy.
8.108 +
8.109 +echo 'attendee' > "$PREFS/$USER/organiser_replacement"
8.110 +
8.111 +# Try to change to an attendee as organiser.
8.112 +
8.113 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter-attendee.txt" 2>> $ERROR \
8.114 +| "$SHOWMAIL" \
8.115 +> out8.tmp
8.116 +
8.117 + grep -q 'METHOD:REPLY' out8.tmp \
8.118 +&& echo "Success" \
8.119 +|| echo "Failed"
8.120 +
8.121 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \
8.122 +| "$SHOWMAIL" \
8.123 +> out9.tmp
8.124 +
8.125 + grep -q 'METHOD:REPLY' out9.tmp \
8.126 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out9.tmp \
8.127 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out9.tmp \
8.128 +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out9.tmp \
8.129 +&& echo "Success" \
8.130 +|| echo "Failed"
8.131 +
8.132 +# Try to change to an unrecognised organiser.
8.133 +
8.134 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter.txt" 2>> $ERROR \
8.135 +| "$SHOWMAIL" \
8.136 +> out10.tmp
8.137 +
8.138 + ! grep -q 'METHOD:REPLY' out10.tmp \
8.139 +&& echo "Success" \
8.140 +|| echo "Failed"
8.141 +
8.142 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \
8.143 +| "$SHOWMAIL" \
8.144 +> out11.tmp
8.145 +
8.146 + grep -q 'METHOD:REPLY' out11.tmp \
8.147 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out11.tmp \
8.148 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out11.tmp \
8.149 +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out11.tmp \
8.150 +&& echo "Success" \
8.151 +|| echo "Failed"
8.152 +
8.153 +# Change the policy.
8.154 +
8.155 +echo 'any' > "$PREFS/$USER/organiser_replacement"
8.156 +
8.157 +# Try to change to an unrecognised organiser.
8.158 +
8.159 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter.txt" 2>> $ERROR \
8.160 +| "$SHOWMAIL" \
8.161 +> out12.tmp
8.162 +
8.163 + grep -q 'METHOD:REPLY' out12.tmp \
8.164 +&& echo "Success" \
8.165 +|| echo "Failed"
8.166 +
8.167 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \
8.168 +| "$SHOWMAIL" \
8.169 +> out13.tmp
8.170 +
8.171 + grep -q 'METHOD:REPLY' out13.tmp \
8.172 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out13.tmp \
8.173 +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out13.tmp \
8.174 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out13.tmp \
8.175 +&& echo "Success" \
8.176 +|| echo "Failed"
8.177 +
8.178 +# Try to change to an attendee as organiser.
8.179 +
8.180 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter-attendee.txt" 2>> $ERROR \
8.181 +| "$SHOWMAIL" \
8.182 +> out14.tmp
8.183 +
8.184 + grep -q 'METHOD:REPLY' out14.tmp \
8.185 +&& echo "Success" \
8.186 +|| echo "Failed"
8.187 +
8.188 + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \
8.189 +| "$SHOWMAIL" \
8.190 +> out15.tmp
8.191 +
8.192 + grep -q 'METHOD:REPLY' out15.tmp \
8.193 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out15.tmp \
8.194 +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out15.tmp \
8.195 +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out15.tmp \
8.196 +&& echo "Success" \
8.197 +|| echo "Failed"