[CalendarServer-changes] [12142] CalendarServer/branches/users/gaya/sharedgroupfixes

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 12 11:19:25 PDT 2014


Revision: 12142
          http://trac.calendarserver.org//changeset/12142
Author:   gaya at apple.com
Date:     2013-12-18 20:51:29 -0800 (Wed, 18 Dec 2013)
Log Message:
-----------
merge in 12017 to 12131 from trunk

Modified Paths:
--------------
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/calendaruserproxy.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/privatecomments.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/sharing-create.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/sharing-invites.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/verifiers/multistatusItems.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/bin/proxyclean
    CalendarServer/branches/users/gaya/sharedgroupfixes/bin/trial
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/__init__.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/accesslog.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/provision/root.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/provision/test/test_root.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/push/applepush.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/caldav.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/test/test_caldav.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/util.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/agent.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/anonymize.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/backup_pg.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/config.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/dkimtool.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/gateway.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/principals.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/gateway/caldavd.plist
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_gateway.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_purge.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_purge_old_events.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webadmin/resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webadmin/test/test_resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webcal/resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/conf/auth/augments-test.xml
    CalendarServer/branches/users/gaya/sharedgroupfixes/conf/auth/resources-test.xml
    CalendarServer/branches/users/gaya/sharedgroupfixes/conf/caldavd-apple.plist
    CalendarServer/branches/users/gaya/sharedgroupfixes/conf/caldavd-test.plist
    CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/loadtest/sim.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/invite.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/multiget.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/put.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/query.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/sync.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/sqlusage.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/stats.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/pyflakes
    CalendarServer/branches/users/gaya/sharedgroupfixes/setup.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/support/build.sh
    CalendarServer/branches/users/gaya/sharedgroupfixes/support/py.sh
    CalendarServer/branches/users/gaya/sharedgroupfixes/test
    CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/caldav.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/__init__.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/authkerb.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/backup.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/bind.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/cache.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/__init__.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/pool.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/reverseproxy.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/test/test_reverseproxy.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/peruserdata.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/privateevents.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/test/test_privateevents.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/addressbook.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/augment.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/cachingdirectory.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/calendar.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/calendaruserproxy.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/common.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/digest.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/directory.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/internal.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/ldapdirectory.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/opendirectorybacker.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/principal.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_aggregate.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_digest.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_guidchange.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_ldapdirectory.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_opendirectory.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_principal.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_wiki.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_xmlfile.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/util.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/util.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/wiki.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/xmlaccountsparser.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/xmlfile.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directorybackedaddressbook.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/dropbox.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/extensions.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/freebusyurl.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/ical.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/icaldav.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/linkresource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcachepool.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcacheprops.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/acl.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/get.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/mkcalendar.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/mkcol.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/post.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/propfind.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_addressbook_query.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_calendar_query.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_common.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_freebusy.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_multiget_common.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_sync_collection.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/notifications.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/scheduling_store/caldav/resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/scheduling_store/caldav/test/test_resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/sharing.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/simpleresource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/stdconfig.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/storebridge.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_accounting.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_addressbookmultiget.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_addressbookquery.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_cache.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_calendarquery.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_collectioncontents.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_config.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_extensions.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_freebusyquery.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_icalendar.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_kerberos.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_link.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_memcachelock.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_memcacheprops.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_mkcalendar.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_multiget.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_options.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_props.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_sharing.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_util.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_wrapping.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/util.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/timezoneservice.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/timezonestdservice.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/upgrade.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/util.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/vcard.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/__init__.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/datastore/file.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/datastore/subpostgres.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/propertystore/base.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/propertystore/xattr.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/file.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/caldav/delivery.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/caldav/scheduler.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/delivery.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/scheduler.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/implicit.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/delivery.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/dkim.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/scheduler.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/itip.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/processing.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/scheduler.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/test/test_implicit.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/common.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_attachments.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_file.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_sql.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_util.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/util.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/util.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/icalendarstore.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/resource.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/file.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/test/common.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/file.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/test/util.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/upgrade/test/test_migrate.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/idirectoryservice.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/idav.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/base.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/rfc2518.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/test/test_xml_rfc3744.py

Added Paths:
-----------
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/CalDAV/implicit/auto11/
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/CalDAV/privatecomments/44.ics
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/CalDAV-pod/
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/MKCALENDAR/vevent.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/MKCALENDAR/vtodo.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharedas.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingdecline2-pod.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite1.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite2-pod.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite2-ro-pod.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite23-pod.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingremove2-pod.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingreply2-pod.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingreply3-pod.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/invite.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/notificationtype.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/props.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/implicitauto11.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-cache.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-calendars.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-create.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-direct.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-dropbox.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-freebusy.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-invites.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-moves.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-multiple.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-notification-sync.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-peruser-data.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-peruser-properties.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-propfind.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-proxies.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-replies.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-reports-multiget.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-sync.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-unshare.xml
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-webcal.xml
    CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webcal/test/
    CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcacheclient.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/txweb2/

Removed Paths:
-------------
    CalendarServer/branches/users/gaya/sharedgroupfixes/twext/
    CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/kqueuereactor.py
    CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/masterchild.py

Property Changed:
----------------
    CalDAVTester/branches/users/gaya/sharedgroupfixestester/
    CalendarServer/branches/users/gaya/sharedgroupfixes/
    CalendarServer/branches/users/gaya/sharedgroupfixes/txweb2/auth/
    CalendarServer/branches/users/gaya/sharedgroupfixes/txweb2/channel/
    CalendarServer/branches/users/gaya/sharedgroupfixes/txweb2/client/
    CalendarServer/branches/users/gaya/sharedgroupfixes/txweb2/dav/
    CalendarServer/branches/users/gaya/sharedgroupfixes/txweb2/dav/method/
    CalendarServer/branches/users/gaya/sharedgroupfixes/txweb2/filter/


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupfixestester
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev:7584
/CalDAVTester/branches/release/CalDAVTester-4.3-dev:10193
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes:8221-8346
/CalDAVTester/branches/users/cdaboo/conditional-4466:4467-4469
/CalDAVTester/branches/users/cdaboo/implicitauto-2948:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574:3575-3581
/CalDAVTester/branches/users/cdaboo/managed-attachments:9986-10145
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228:5229-5440
/CalDAVTester/branches/users/gaya/sharedgroupstester-3:11181-11204
/CalDAVTester/trunk:11742-12016
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev:7584
/CalDAVTester/branches/release/CalDAVTester-4.3-dev:10193
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes:8221-8346
/CalDAVTester/branches/users/cdaboo/conditional-4466:4467-4469
/CalDAVTester/branches/users/cdaboo/implicitauto-2948:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574:3575-3581
/CalDAVTester/branches/users/cdaboo/managed-attachments:9986-10145
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228:5229-5440
/CalDAVTester/branches/users/gaya/sharedgroupstester-3:11181-11204
/CalDAVTester/trunk:11742-12016,12018-12132

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/CalDAV/privatecomments/44.ics (from rev 12132, CalDAVTester/trunk/Resource/CalDAV/privatecomments/44.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/CalDAV/privatecomments/44.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/CalDAV/privatecomments/44.ics	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,38 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VTIMEZONE
+TZID:US/Eastern
+LAST-MODIFIED:20040110T032845Z
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:event3 at ninevah.local
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;RSVP=TRUE:$cuaddr2:
+CREATED:20060101T150000Z
+DTSTAMP:20051222T205953Z
+ORGANIZER;CN=$username1::$cuaddr1:
+SUMMARY:event 3
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="$cuaddrurn2:
+ ";X-CALENDARSERVER-DTSTAMP=20080827T171052Z:I have accepted.
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="$cuaddrurn2:
+ ";X-CALENDARSERVER-DTSTAMP=20080828T171052Z:I have accepted again.
+END:VEVENT
+END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/MKCALENDAR/vevent.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/MKCALENDAR/vevent.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/MKCALENDAR/vevent.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/MKCALENDAR/vevent.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<C:mkcalendar xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
+<D:set>
+<D:prop>
+<C:supported-calendar-component-set>
+<C:comp name="VEVENT"/>
+</C:supported-calendar-component-set>
+</D:prop>
+</D:set>
+</C:mkcalendar>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/MKCALENDAR/vtodo.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/MKCALENDAR/vtodo.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/MKCALENDAR/vtodo.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/MKCALENDAR/vtodo.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<C:mkcalendar xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
+<D:set>
+<D:prop>
+<C:supported-calendar-component-set>
+<C:comp name="VTODO"/>
+</C:supported-calendar-component-set>
+</D:prop>
+</D:set>
+</C:mkcalendar>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharedas.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/POST/sharedas.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharedas.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharedas.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<shared-as xmlns='http://calendarserver.org/ns/'>
+  <href xmlns='DAV:'></href>
+</shared-as>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingdecline2-pod.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/POST/sharingdecline2-pod.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingdecline2-pod.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingdecline2-pod.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<invite-reply xmlns='http://calendarserver.org/ns/'>
+  <href xmlns='DAV:'>mailto:$pemail2:</href>
+  <invite-declined/>
+  <hosturl>
+    <href xmlns='DAV:'>$calendarhome1:/shared</href>
+  </hosturl>
+  <in-reply-to>$inviteuid2:</in-reply-to>
+  <summary>The Shared Calendar</summary>
+  <common-name>$pusername2:</common-name>
+  <first-name>$pfirstname2:</first-name>
+  <last-name>$plastname2:</last-name>
+</invite-reply>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite1.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/POST/sharinginvite1.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite1.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite1.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+    <CS:set>
+        <D:href>$cuaddr1:</D:href>
+        <CS:summary>My Shared Calendar</CS:summary>
+        <CS:read-write/>
+    </CS:set>
+</CS:share>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite2-pod.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/POST/sharinginvite2-pod.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite2-pod.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite2-pod.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+    <CS:set>
+        <D:href>$pcuaddr2:</D:href>
+        <CS:summary>My Shared Calendar</CS:summary>
+        <CS:read-write/>
+    </CS:set>
+</CS:share>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite2-ro-pod.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/POST/sharinginvite2-ro-pod.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite2-ro-pod.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite2-ro-pod.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+    <CS:set>
+        <D:href>$pcuaddr2:</D:href>
+        <CS:summary>My Shared Calendar</CS:summary>
+        <CS:read/>
+    </CS:set>
+</CS:share>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite23-pod.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/POST/sharinginvite23-pod.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite23-pod.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharinginvite23-pod.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+    <CS:set>
+        <D:href>$pcuaddr2:</D:href>
+        <CS:summary>My Shared Calendar</CS:summary>
+        <CS:read-write/>
+    </CS:set>
+    <CS:set>
+        <D:href>$pcuaddr3:</D:href>
+        <CS:summary>My Shared Calendar</CS:summary>
+        <CS:read/>
+    </CS:set>
+</CS:share>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingremove2-pod.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/POST/sharingremove2-pod.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingremove2-pod.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingremove2-pod.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+    <CS:remove>
+        <D:href>$pcuaddr2:</D:href>
+        <CS:read-write/>
+    </CS:remove>
+</CS:share>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingreply2-pod.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/POST/sharingreply2-pod.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingreply2-pod.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingreply2-pod.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<invite-reply xmlns='http://calendarserver.org/ns/'>
+  <href xmlns='DAV:'>mailto:$pemail2:</href>
+  <invite-accepted/>
+  <hosturl>
+    <href xmlns='DAV:'>$hosturl2:</href>
+  </hosturl>
+  <in-reply-to>$inviteuid2:</in-reply-to>
+  <summary>The Shared Calendar</summary>
+  <common-name>$pusername2:</common-name>
+  <first-name>$pfirstname2:</first-name>
+  <last-name>$plastname2:</last-name>
+</invite-reply>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingreply3-pod.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/POST/sharingreply3-pod.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingreply3-pod.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/POST/sharingreply3-pod.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<invite-reply xmlns='http://calendarserver.org/ns/'>
+  <href xmlns='DAV:'>mailto:$pemail3:</href>
+  <invite-accepted/>
+  <hosturl>
+    <href xmlns='DAV:'>$hosturl3:</href>
+  </hosturl>
+  <in-reply-to>$inviteuid3:</in-reply-to>
+  <summary>The Shared Calendar</summary>
+  <common-name>$pusername3:</common-name>
+  <first-name>$pfirstname3:</first-name>
+  <last-name>$plastname3:</last-name>
+</invite-reply>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/invite.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/PROPFIND/invite.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/invite.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/invite.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<D:propfind xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+<D:prop>
+<CS:invite/>
+</D:prop>
+</D:propfind>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/notificationtype.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/PROPFIND/notificationtype.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/notificationtype.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/notificationtype.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<D:propfind xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+<D:prop>
+<CS:notificationtype/>
+</D:prop>
+</D:propfind>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/props.xml (from rev 12132, CalDAVTester/trunk/Resource/Common/PROPFIND/props.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/props.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/Resource/Common/PROPFIND/props.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<D:propfind xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+<D:prop>
+<D:creationdate/>
+<D:current-user-privilege-set/>
+<D:displayname/>
+<D:getcontenttype/>
+<CS:getctag/>
+<D:getetag/>
+<D:getlastmodified/>
+<D:resource-id/>
+<D:resourcetype/>
+<D:supported-report-set/>
+<D:sync-token/>
+</D:prop>
+</D:propfind>

Modified: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/calendaruserproxy.xml
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/calendaruserproxy.xml	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/calendaruserproxy.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -148,11 +148,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -171,11 +171,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -223,11 +223,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value><![CDATA[{DAV:}group-member-set$<D:href xmlns:D="DAV:">$principaluri2:</D:href>]]></value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set/{DAV:}href[=$principaluri2:]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -246,11 +246,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -269,11 +269,10 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value><![CDATA[{DAV:}group-membership$<D:href xmlns:D="DAV:">$principaluri1:calendar-proxy-read/</D:href>]]></value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-membership/{DAV:}href[=$principaluri1:calendar-proxy-read/]</value>
 					</arg>
 				</verify>
 			</request>
@@ -339,11 +338,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -362,11 +361,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -385,11 +384,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -437,11 +436,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value><![CDATA[{DAV:}group-member-set$<D:href xmlns:D="DAV:">$principaluri2:</D:href>]]></value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set/{DAV:}href[=$principaluri2:]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -460,11 +459,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -483,11 +482,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value><![CDATA[{DAV:}group-membership$<D:href xmlns:D="DAV:">$principaluri1:calendar-proxy-write/</D:href>]]></value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership/{DAV:}href[$principaluri1:calendar-proxy-write/]</value>
 					</arg>
 				</verify>
 			</request>
@@ -581,11 +580,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -604,11 +603,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -627,11 +626,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set$</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set[|]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -700,11 +699,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value><![CDATA[{DAV:}group-member-set$<D:href xmlns:D="DAV:">$principaluri1:</D:href>]]></value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set/{DAV:}href[$principaluri1:]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -723,10 +722,10 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>dataString</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>contains</name>
-						<value>&lt;href&gt;$rprincipaluri1:calendar-proxy-write/&lt;/href&gt;</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-membership/{DAV:}href[$rprincipaluri1:calendar-proxy-write/]</value>
 					</arg>
 				</verify>
 			</request>
@@ -745,11 +744,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value><![CDATA[{DAV:}group-member-set$<D:href xmlns:D="DAV:">$principaluri3:</D:href>]]></value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set/{DAV:}href[=$principaluri3:]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -768,10 +767,10 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>dataString</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>contains</name>
-						<value>&lt;href&gt;$rprincipaluri1:calendar-proxy-read/&lt;/href&gt;</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-membership/{DAV:}href[=$rprincipaluri1:calendar-proxy-read/]</value>
 					</arg>
 				</verify>
 			</request>
@@ -808,21 +807,14 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/2.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{DAV:}group-member-set</value>
-						<value>{DAV:}group-membership$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}group-member-set/{DAV:}href[=$principaluri2:]</value>
+						<value>$verify-property-prefix:/{DAV:}group-member-set/{DAV:}href[=$principaluri3:]</value>
+						<value>$verify-property-prefix:/{DAV:}group-membership[|]</value>
 					</arg>
 				</verify>
-				<verify>
-					<callback>dataString</callback>
-					<arg>
-						<name>contains</name>
-						<value>&lt;href&gt;$principaluri2:&lt;/href&gt;</value>
-						<value>&lt;href&gt;$principaluri3:&lt;/href&gt;</value>
-					</arg>
-				</verify>
 			</request>
 		</test>
 		<test name='2'>
@@ -873,7 +865,7 @@
 			<description>Default setup</description>
 			<request print-response="no">
 				<method>PROPFIND</method>
-				<ruri>$principal1:/</ruri>
+				<ruri>$principal1:</ruri>
 				<header>
 					<name>Depth</name>
 					<value>0</value>
@@ -883,11 +875,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/10.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{http://calendarserver.org/ns/}calendar-proxy-read-for$</value>
-						<value>{http://calendarserver.org/ns/}calendar-proxy-write-for$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}calendar-proxy-read-for[|]</value>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}calendar-proxy-write-for[|]</value>
 					</arg>
 				</verify>
 			</request>
@@ -926,7 +918,7 @@
 			</request>
 			<request print-response="no">
 				<method>PROPFIND</method>
-				<ruri>$principal1:/</ruri>
+				<ruri>$principal1:</ruri>
 				<header>
 					<name>Depth</name>
 					<value>0</value>
@@ -936,11 +928,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/10.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindValues</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value><![CDATA[{http://calendarserver.org/ns/}calendar-proxy-read-for$<D:href xmlns:D="DAV:">$principaluri2:</D:href>]]></value>
-						<value><![CDATA[{http://calendarserver.org/ns/}calendar-proxy-write-for$<D:href xmlns:D="DAV:">$principaluri3:</D:href>]]></value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}calendar-proxy-read-for/{DAV:}href[=$principaluri2:]</value>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}calendar-proxy-write-for/{DAV:}href[=$principaluri3:]</value>
 					</arg>
 				</verify>
 			</request>
@@ -979,7 +971,7 @@
 			</request>
 			<request print-response="no">
 				<method>PROPFIND</method>
-				<ruri>$principal1:/</ruri>
+				<ruri>$principal1:</ruri>
 				<header>
 					<name>Depth</name>
 					<value>0</value>
@@ -989,11 +981,11 @@
 					<filepath>Resource/CalDAV/calendaruserproxy/10.xml</filepath>
 				</data>
 				<verify>
-					<callback>propfindItems</callback>
+					<callback>xmlElementMatch</callback>
 					<arg>
-						<name>okprops</name>
-						<value>{http://calendarserver.org/ns/}calendar-proxy-read-for$</value>
-						<value>{http://calendarserver.org/ns/}calendar-proxy-write-for$</value>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}calendar-proxy-read-for[|]</value>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}calendar-proxy-write-for[|]</value>
 					</arg>
 				</verify>
 			</request>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/implicitauto11.xml (from rev 12132, CalDAVTester/trunk/scripts/tests/CalDAV/implicitauto11.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/implicitauto11.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/implicitauto11.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,256 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test implicit scheduling for auto-accept location where hidden instances are used</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>auto-accept</feature>
+		<feature>implicit-scheduling</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>GET</method>
+			<ruri>$calendarpath1:/</ruri>
+		</request>
+		<request user="$userid2:" pswd="$pswd2:">
+			<method>GET</method>
+			<ruri>$calendarpath2:/</ruri>
+		</request>
+		<request>
+			<method>DELETEALL</method>
+			<ruri>$inboxpath1:/</ruri>
+		</request>
+		<request user="$userid2:" pswd="$pswd2:">
+			<method>DELETEALL</method>
+			<ruri>$inboxpath2:/</ruri>
+		</request>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$rinboxpath1:/</ruri>
+		</request>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$rcalendarpath1:/</ruri>
+		</request>
+	</start>
+	
+	<test-suite name='#1 Non-recurring' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>Create recurring event - resource invited to two instances only</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/auto11/suite1/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>One item in user01 Inbox</description>
+			<request print-response="no">
+				<method>WAITDELETEALL 1</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>One item in user01 Calendar</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto11/suite1/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>No items in resource01 Inbox</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$rinboxpath1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>0</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>One item in resource01 Calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GETNEW</method>
+				<ruri>$rcalendarpath1:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto11/suite1/3.ics</value>
+					</arg>
+				</verify>
+				<graburi>$r1:</graburi>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Proxy removes first instance to decline it</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$r1:</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/auto11/suite1/4.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>One item in resource01 Calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GET</method>
+				<ruri>$r1:</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto11/suite1/4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8' ignore='no'>
+			<description>One item in user01 Inbox</description>
+			<request print-response="no">
+				<method>WAITDELETEALL 1</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+		</test>
+		<test name='9' ignore='no'>
+			<description>One item in user01 Calendar</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto11/suite1/5.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='10' ignore='no'>
+			<description>Organizer cancels second instance</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/auto11/suite1/6.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='11' ignore='no'>
+			<description>One item in user01 Calendar</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto11/suite1/7.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='12' ignore='no'>
+			<description>No item in resource01 Calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GET</method>
+				<ruri>$r1:</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>404</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='-1' ignore='no'>
+			<description>Clean-up inboxes</description>
+			<request>
+				<method>DELETEALL</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>DELETEALL</method>
+				<ruri>$inboxpath2:/</ruri>
+			</request>
+			<request user="$useradmin:" pswd="$pswdadmin:">
+				<method>DELETEALL</method>
+				<ruri>$rinboxpath1:/</ruri>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request>
+			<method>DELETEALL</method>
+			<ruri>$inboxpath1:/</ruri>
+			<ruri>$calendarpath1:/</ruri>
+		</request>
+		<request user="$userid2:" pswd="$pswd2:">
+			<method>DELETEALL</method>
+			<ruri>$inboxpath2:/</ruri>
+			<ruri>$calendarpath2:/</ruri>
+		</request>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$rinboxpath1:/</ruri>
+			<ruri>$rcalendarpath1:/</ruri>
+		</request>
+	</end>
+	
+</caldavtest>

Modified: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/privatecomments.xml
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/privatecomments.xml	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/privatecomments.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -1124,8 +1124,175 @@
 				</verify>
 			</request>
 		</test>
+		<test name='-1'>
+			<description>Clean-up</description>
+			<request user="$userid1:" pswd="$pswd1:">
+				<method>DELETEALL</method>
+				<ruri>$calendarpath1:/</ruri>
+			</request>
+			<request user="$userid1:" pswd="$pswd1:">
+				<method>DELETEALL</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>DELETEALL</method>
+				<ruri>$calendarpath2:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>DELETEALL</method>
+				<ruri>$inboxpath2:/</ruri>
+			</request>
+			<request user="$userid3:" pswd="$pswd3:">
+				<method>DELETEALL</method>
+				<ruri>$calendarpath3:/</ruri>
+			</request>
+			<request user="$userid3:" pswd="$pswd3:">
+				<method>DELETEALL</method>
+				<ruri>$inboxpath3:/</ruri>
+			</request>
+		</test>
 	</test-suite>
 
+	<test-suite name='No duplicates' ignore='no'>
+		<test name='1'>
+			<description>Organizer invites Attendee</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/3.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/privatecomments/26.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Organizer checks data</description>
+			<request print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarpath1:/3.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/privatecomments/27.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Attendee Inbox Item</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>WAITDELETEALL 1</method>
+				<ruri>$inboxpath2:/</ruri>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Attendee has data</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$calendarpath2:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/privatecomments/28.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Attendee -> Accepts with comment</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$calendarpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/privatecomments/29.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='7'>
+			<description>Attendee has data</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$calendarpath2:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/privatecomments/30.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8'>
+			<description>Organizer Inbox Item</description>
+			<request print-response='no'>
+				<method>WAITDELETEALL 1</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+		</test>
+		<test name='9'>
+			<description>Organizer data changed</description>
+			<request print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarpath1:/3.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/privatecomments/35.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='10'>
+			<description>Organizer duplicates comment</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/3.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/privatecomments/44.ics</filepath>
+				</data>
+				<verify>
+					<callback>prepostcondition</callback>
+					<arg>
+						<name>error</name>
+						<value>{http://calendarserver.org/ns/}no-duplicate-private-comments</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='11'>
+			<description>Organizer checks data</description>
+			<request print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarpath1:/3.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/privatecomments/35.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
 	<end>
 		<request user="$userid1:" pswd="$pswd1:">
 			<method>DELETEALL</method>

Modified: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/sharing-create.xml
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/sharing-create.xml	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/sharing-create.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -18,7 +18,7 @@
  limitations under the License.
  -->
 
-<caldavtest ignore-all='yes'>
+<caldavtest>
 	<description>Test calendar sharing replies</description>
 
 	<require-feature>

Modified: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/sharing-invites.xml
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/sharing-invites.xml	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests/CalDAV/sharing-invites.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -526,10 +526,6 @@
 			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
 				<method>DELETE</method>
 				<ruri>$shareecalendar2:/</ruri>
-				<data substitutions='yes'>
-					<content-type>application/xml; charset=utf-8</content-type>
-					<filepath>Resource/CalDAV/sharing/invites/double/5.xml</filepath>
-				</data>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-cache.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-cache.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-cache.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-cache.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,412 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest ignore-all='yes'>
+	<description>Test calendar sharing interaction with cache</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</start>
+	
+	<test-suite name='Generate invite' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>Create</description>
+			<request end-delete="yes">
+				<method>MKCALENDAR</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>PROPFIND Home to cache it</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>dataString</callback>
+					<arg>
+						<name>notcontains</name>
+						<value>user02</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>PROPFIND Home check</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>dataString</callback>
+					<arg>
+						<name>contains</name>
+						<value>puser02</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>POST uninvite</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingremove2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>PROPFIND Home check</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>dataString</callback>
+					<arg>
+						<name>notcontains</name>
+						<value>puser02</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Send first reply'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>PROPFIND Home check</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/sharedas.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{DAV:}href</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>PROPFIND Home check</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>$shareecalendar:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Delete shared</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$shareecalendar:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>PROPFIND Home check</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>nohrefs</name>
+						<value>$shareecalendar:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8'>
+			<description>Sharee replies ACCEPTED - need to do this cycle of accept/delete twice to regress properly</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/sharedas.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{DAV:}href</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='9' ignore='no'>
+			<description>PROPFIND Home check</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>$shareecalendar:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='10' ignore='no'>
+			<description>Delete shared</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$shareecalendar:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='11' ignore='no'>
+			<description>PROPFIND Home check</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>nohrefs</name>
+						<value>$shareecalendar:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-calendars.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-calendars.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-calendars.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-calendars.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,574 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test calendar sharing calendars</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request>
+			<method>PROPPATCH</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
+			</data>
+		</request>
+	</start>
+	
+	<test-suite name='Read-write calendar'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Shared calendar exists</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{DAV:}collection</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{urn:ietf:params:xml:ns:caldav}calendar</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4a'>
+			<description>Shared calendar exists Depth:1</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>parent</name>
+						<value>$multistatus-response-prefix:[^{DAV:}href=$sharedcalendar:/]</value>
+					</arg>
+					<arg>
+						<name>exists</name>
+						<value>$verify-response-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-response-prefix:/{DAV:}resourcetype/{DAV:}collection</value>
+						<value>$verify-response-prefix:/{DAV:}resourcetype/{urn:ietf:params:xml:ns:caldav}calendar</value>
+						<value>$verify-response-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+						<value>$verify-response-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+						<value>$verify-response-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4b'>
+			<description>Shared calendar has invite property</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{http://calendarserver.org/ns/}invite</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite</value>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}organizer</value>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}organizer/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}organizer/{http://calendarserver.org/ns/}common-name[=$username1:]</value>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}user</value>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}user/{DAV:}href[=$pcuaddrurn2:]</value>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}user/{http://calendarserver.org/ns/}access/{http://calendarserver.org/ns/}read-write</value>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}invite/{http://calendarserver.org/ns/}user/{http://calendarserver.org/ns/}invite-accepted</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Original calendar unchanged</description>
+			<request>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}opaque</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Sharee creates event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PUT</method>
+				<ruri>$sharedcalendar:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='7'>
+			<description>Sharer sees event</description>
+			<request>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/calendars/read-write/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8'>
+			<description>Sharer changes event</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='9'>
+			<description>Sharee sees changed event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GET</method>
+				<ruri>$sharedcalendar:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/calendars/read-write/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='10'>
+			<description>Sharer creates event</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/4.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='11'>
+			<description>Sharee sees new event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GET</method>
+				<ruri>$sharedcalendar:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/calendars/read-write/4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='12'>
+			<description>Sharee changes event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PUT</method>
+				<ruri>$sharedcalendar:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/5.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='13'>
+			<description>Sharer sees changed event</description>
+			<request>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/calendars/read-write/5.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Default calendar cannot be shared calendar' ignore='no'>
+		<test name='1'>
+			<description>Set property on Inbox</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPPATCH</method>
+				<ruri>$pinboxpath2:/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/defaultcalendar/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>badprops</name>
+						<value>{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Verify property on inbox</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$pinboxpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/defaultcalendar/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value><![CDATA[{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL$<href xmlns="DAV:">$pcalendarpath2:</href>]]></value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Change to read-only calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-ro-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/calendars/read-only/1.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Shared calendar exists</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Create event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PUT</method>
+				<ruri>$sharedcalendar:/3.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-only/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Sharer creates event</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/4.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-only/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='7'>
+			<description>Sharee sees new event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GET</method>
+				<ruri>$sharedcalendar:/4.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/calendars/read-only/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8'>
+			<description>Sharee cannot change event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PUT</method>
+				<ruri>$sharedcalendar:/4.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-only/4.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+	
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-create.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-create.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-create.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-create.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,220 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test calendar sharing replies</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</start>
+	
+	<test-suite name='Create calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request end-delete="yes">
+				<method>MKCALENDAR</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>Change the color</description>
+			<request print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/direct/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{http://apple.com/ns/ical/}calendar-color</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Generate invite' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Accept' ignore='no'>
+		<test name='1'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>Check accept status</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Check Sharer notification collection</description>
+			<request>
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationreply2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Shared calendar exists without color</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/direct/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>badprops</name>
+						<value>{http://apple.com/ns/ical/}calendar-color</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-direct.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-direct.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-direct.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-direct.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,762 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test calendar sharing calendars</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request print-response='no'>
+			<method>PROPPATCH</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
+			</data>
+		</request>
+	</start>
+	
+	<test-suite name='Read-write calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>Add puser02 as read write for user01</description>
+			<request print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$principal1:calendar-proxy-write/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/direct/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}group-member-set</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Sharee does direct share</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/?action=share</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Shared calendar exists</description>
+			<pause/>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Original calendar unchanged</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}opaque</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharee creates event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$sharedcalendar:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Sharer sees event</description>
+			<request print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/calendars/read-write/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='7'>
+			<description>Sharer changes event</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='8'>
+			<description>Sharee sees changed event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$sharedcalendar:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/calendars/read-write/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='9'>
+			<description>Sharer creates event</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/4.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='10'>
+			<description>Sharee sees new event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$sharedcalendar:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/calendars/read-write/4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='11'>
+			<description>Sharee changes event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$sharedcalendar:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/5.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='12'>
+			<description>Sharer sees changed event</description>
+			<request print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/calendars/read-write/5.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='13'>
+			<description>Sharee does direct share again</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/?action=share</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='14'>
+			<description>Shared calendar exists</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Change to read-only calendar' ignore='yes'>
+		<test name='1' ignore='no'>
+			<description>Clear user02 as read-write proxy for user01</description>
+			<request print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$principal1:calendar-proxy-write/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/calendaruserproxy/4.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}group-member-set</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>Add user02 as read-only for user01</description>
+			<request print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$principal1:calendar-proxy-read/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/calendaruserproxy/3.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}group-member-set</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Shared calendar exists</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/calendars/read-only/4.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Create event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$sharedcalendar:/3.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/calendars/read-only/5.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharer creates event</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/4.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/calendars/read-only/6.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Sharee sees new event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$sharedcalendar:/4.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/calendars/read-only/6.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='7'>
+			<description>Sharee cannot change event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$sharedcalendar:/4.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/calendars/read-only/7.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Removal of direct share' ignore='yes'>
+		<test name='1' ignore='no'>
+			<description>Remove direct share</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>DELETE</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Shared calendar does not exist</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/calendars/read-only/4.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>404</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharer calendar does exist</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/calendars/read-only/4.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>3</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Direct share not allowed' ignore='yes'>
+		<test name='1' ignore='no'>
+			<description>Clear user02 as read-only proxy for user01</description>
+			<request print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$principal1:calendar-proxy-read/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/calendaruserproxy/4.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}group-member-set</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Sharee does direct share</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/?action=share</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Using non __uids__ path' ignore='yes'>
+		<test name='1' ignore='no'>
+			<description>Add user02 as read write for user01</description>
+			<request print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$principal1:calendar-proxy-write/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/calendaruserproxy/3.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}group-member-set</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Sharee does direct share</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarhomealt1:/shared/?action=share</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Shared calendar exists</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/calendars/read-write/4.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp/{urn:ietf:params:xml:ns:caldav}transparent</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Sharee creates event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$sharedcalendar2:/9.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/calendars/read-write/9.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharer sees event</description>
+			<request print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/9.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/calendars/read-write/9.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Remove direct share</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>DELETE</method>
+				<ruri>$sharedcalendar2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>Clear user02 as read-write proxy for user01</description>
+			<request print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$principal1:calendar-proxy-write/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/calendaruserproxy/4.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}group-member-set</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Calendar color' ignore='yes'>
+		<test name='1' ignore='no'>
+			<description>Add user02 as read write for user01</description>
+			<request print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$principal1:calendar-proxy-write/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/calendaruserproxy/3.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}group-member-set</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>Change the color</description>
+			<request print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$calendarhomealt1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/direct/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{http://apple.com/ns/ical/}calendar-color</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee does direct share</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarhomealt1:/shared/?action=share</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Shared calendar exists with color</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/direct/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{http://apple.com/ns/ical/}calendar-color[=#00112233]</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>Remove direct share</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>DELETE</method>
+				<ruri>$sharedcalendar2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Clear user02 as read-write proxy for user01</description>
+			<request print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$principal1:calendar-proxy-write/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/calendaruserproxy/4.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}group-member-set</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end/>
+	
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-dropbox.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-dropbox.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-dropbox.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-dropbox.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,323 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest ignore-all="no">
+	<description>Test Quota support on the server for shared calendars</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>dropbox</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid2:" pswd="$pswd2:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath2:/</ruri>
+		</request>
+		<request user="$userid3:" pswd="$pswd3:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath3:/</ruri>
+		</request>
+		<request user="$userid4:" pswd="$pswd4:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath4:/</ruri>
+		</request>
+		<request user="$userid2:" pswd="$pswd2:" end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome2:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+	</start>
+	
+	<test-suite name='Setup two sharees'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome2:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite234.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee 2 notification collection</description>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath3:/</ruri>
+			</request>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$notificationpath3:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid23:</variable>
+				</grabelement>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+					<variable>$hosturl23:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee 2 replies ACCEPTED</description>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome3:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply23.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar3:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Check Sharee 3 notification collection</description>
+			<request user="$userid4:" pswd="$pswd4:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath4:/</ruri>
+			</request>
+			<request user="$userid4:" pswd="$pswd4:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$notificationpath4:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid24:</variable>
+				</grabelement>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+					<variable>$hosturl24:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharee 3 replies ACCEPTED</description>
+			<request user="$userid4:" pswd="$pswd4:" print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome4:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply24.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar4:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Clean out notifications</description>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>DELETEALL</method>
+				<ruri>$notificationpath2:/</ruri>
+			</request>
+			<request user="$userid3:" pswd="$pswd3:">
+				<method>DELETEALL</method>
+				<ruri>$notificationpath3:/</ruri>
+			</request>
+			<request user="$userid4:" pswd="$pswd4:">
+				<method>DELETEALL</method>
+				<ruri>$notificationpath4:/</ruri>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='PUT by User 2' ignore='no'>
+		<test name='1'>
+			<description>PUT event by user 2</description>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>PUT</method>
+				<ruri>$calendarhome2:/shared/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/dropbox/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>PUT attachment by user 2</description>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>PUT</method>
+				<ruri>$dropboxpath2:/54E181BC7CCC373042B28842/2.xml</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/dropbox/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>Attachment exists for User 2</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$dropboxpath2:/54E181BC7CCC373042B28842/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Attachment exists for User 3</description>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$dropboxpath2:/54E181BC7CCC373042B28842/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>PUT attachment by user 3</description>
+			<request user="$userid3:" pswd="$pswd3:">
+				<method>PUT</method>
+				<ruri>$dropboxpath2:/54E181BC7CCC373042B28842/3.xml</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/dropbox/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Attachments exists for User 4</description>
+			<request user="$userid4:" pswd="$pswd4:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$dropboxpath2:/54E181BC7CCC373042B28842/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>2</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='7'>
+			<description>PUT attachment by user 4</description>
+			<request user="$userid4:" pswd="$pswd4:">
+				<method>PUT</method>
+				<ruri>$dropboxpath2:/54E181BC7CCC373042B28842/3.xml</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/dropbox/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8'>
+			<description>DELETE attachment by user 2</description>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>DELETE</method>
+				<ruri>$dropboxpath2:/54E181BC7CCC373042B28842/2.xml</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='9'>
+			<description>DELETE attachment by user 2</description>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>DELETE</method>
+				<ruri>$dropboxpath2:/54E181BC7CCC373042B28842/3.xml</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+			<ruri>$notificationpath2:/</ruri>
+			<ruri>$notificationpath3:/</ruri>
+			<ruri>$notificationpath4:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-freebusy.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-freebusy.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-freebusy.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-freebusy.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,419 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest ignore-all='no'>
+	<description>Test calendar sharing per-user data</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+		</request>
+		<request>
+			<method>POST</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/POST/sharinginvite23-pod.xml</filepath>
+			</data>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>WAITCOUNT 1</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>GETNEW</method>
+			<ruri>$pnotificationpath2:/</ruri>
+			<grabelement>
+				<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+				<variable>$inviteuid2:</variable>
+			</grabelement>
+			<grabelement>
+				<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+				<variable>$hosturl2:</variable>
+			</grabelement>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>POST</method>
+			<ruri>$pcalendarhome2:/</ruri>
+			<data substitutions='yes'>
+				<content-type>application/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+			</data>
+			<grabelement>
+				<name>{DAV:}href</name>
+				<variable>$sharedcalendar2:</variable>
+			</grabelement>
+		</request>
+		<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+			<method>WAITCOUNT 1</method>
+			<ruri>$pnotificationpath3:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+			<method>GETNEW</method>
+			<ruri>$pnotificationpath3:/</ruri>
+			<grabelement>
+				<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+				<variable>$inviteuid3:</variable>
+			</grabelement>
+			<grabelement>
+				<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+				<variable>$hosturl3:</variable>
+			</grabelement>
+		</request>
+		<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+			<method>POST</method>
+			<ruri>$pcalendarhome3:/</ruri>
+			<data substitutions='yes'>
+				<content-type>application/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/POST/sharingreply3-pod.xml</filepath>
+			</data>
+			<grabelement>
+				<name>{DAV:}href</name>
+				<variable>$sharedcalendar3:</variable>
+			</grabelement>
+		</request>
+		<request>
+			<method>PROPPATCH</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
+			</data>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>PROPPATCH</method>
+			<ruri>$sharedcalendar2:/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
+			</data>
+		</request>
+		<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+			<method>PROPPATCH</method>
+			<ruri>$sharedcalendar3:/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
+			</data>
+		</request>
+	</start>
+	
+	<test-suite name='Initial event'>
+		<test name='1'>
+			<description>User01 store to shared</description>
+			<request user="$userid1:" pswd="$pswd1:" print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<data substitutions='yes'>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/freebusy/1.ics</filepath>
+				</data>
+			</request>
+		</test>
+		<test name='2'>
+			<description>User01 freebusy</description>
+			<request>
+				<method>POST</method>
+				<ruri>$outboxpath1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/freebusy/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.0:T230000Z/$now.1:T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.0:T230000Z/$now.1:T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.0:T230000Z/$now.1:T000000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>User02 freebusy</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>POST</method>
+				<ruri>$poutboxpath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/freebusy/4.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.0:T230000Z/$now.1:T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.0:T230000Z/$now.1:T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.0:T230000Z/$now.1:T000000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>User03 freebusy</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response="no">
+				<method>POST</method>
+				<ruri>$poutboxpath3:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/freebusy/5.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.0:T230000Z/$now.1:T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.0:T230000Z/$now.1:T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.0:T230000Z/$now.1:T000000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Changed event'>
+		<test name='1'>
+			<description>User02 store to shared</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PUT</method>
+				<ruri>$sharedcalendar2:/1.ics</ruri>
+				<data substitutions='yes'>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/freebusy/2.ics</filepath>
+				</data>
+			</request>
+		</test>
+		<test name='2'>
+			<description>User01 freebusy</description>
+			<request>
+				<method>POST</method>
+				<ruri>$outboxpath1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/freebusy/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.1:T230000Z/$now.2:T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.1:T230000Z/$now.2:T000000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>User02 freebusy</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>POST</method>
+				<ruri>$poutboxpath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/freebusy/4.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.1:T230000Z/$now.2:T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.1:T230000Z/$now.2:T000000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>User03 freebusy</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response="no">
+				<method>POST</method>
+				<ruri>$poutboxpath3:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/freebusy/5.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.1:T230000Z/$now.2:T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.1:T230000Z/$now.2:T000000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+			<ruri>$pnotificationpath3:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-invites.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-invites.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-invites.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-invites.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,575 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test calendar sharing invitations</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared2/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared3/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+	</start>
+	
+	<test-suite name='Send new invite'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Notification type property</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/notificationtype.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}notificationtype/{http://calendarserver.org/ns/}invite-notification[@shared-type="calendar"]</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Update new invite'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-ro-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2-ro.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Notification type property</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/notificationtype.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{http://calendarserver.org/ns/}notificationtype/{http://calendarserver.org/ns/}invite-notification[@shared-type="calendar"]</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Uninvite new invite'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingremove2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>0</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Attempt broken invite'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/invites/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>424</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+					<arg>
+						<name>403</name>
+						<value>mailto:bogus at example.net</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>0</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Delete new invite'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>DELETE collection</description>
+			<request print-response='no'>
+				<method>DELETE</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>0</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Uninvite invalid invite'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request end-delete="yes">
+				<method>MKCALENDAR</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>POST valid invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>POST single invalid uninvitate</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/invites/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>POST invalid and valid uninvitate</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/invites/3.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>200</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+					<arg>
+						<name>403</name>
+						<value>mailto:bogus at example.com</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>DELETE collection</description>
+			<request print-response='no'>
+				<method>DELETE</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Double invites'>
+		<test name='1' ignore='no'>
+			<description>POST invitation #2</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared2/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2-2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>POST invitation #3</description>
+			<request print-response='no'>
+				<method>DELAY</method>
+				<ruri>1</ruri>
+			</request>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared3/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 2</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2-3.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharee replies ACCEPTED #2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/sharedas.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{DAV:}href</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Sharee deletes shared calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$shareecalendar2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>Remove invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared2/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingremove2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='8' ignore='no'>
+			<description>Remove invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared3/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingremove2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-moves.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-moves.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-moves.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-moves.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,546 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest ignore-all='no'>
+	<description>Test calendar sharing and MOVE</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+		</request>
+		<request print-response='no'>
+			<method>POST</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/POST/sharinginvite2.xml</filepath>
+			</data>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+			<method>WAITCOUNT 1</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+			<method>GETNEW</method>
+			<ruri>$pnotificationpath2:/</ruri>
+			<grabelement>
+				<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+				<variable>$inviteuid2:</variable>
+			</grabelement>
+			<grabelement>
+				<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+				<variable>$hosturl2:</variable>
+			</grabelement>
+		</request>
+		<request user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+			<method>POST</method>
+			<ruri>$pcalendarhome2:/</ruri>
+			<data substitutions='yes'>
+				<content-type>application/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/POST/sharingreply2.xml</filepath>
+			</data>
+			<grabelement>
+				<name>{DAV:}href</name>
+				<variable>$sharedcalendar2:</variable>
+			</grabelement>
+		</request>
+	</start>
+	
+	<test-suite name='OK event to shared calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User02 store to personal calendar</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarpath2:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/moves/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User02 moves event to shared calendar</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>MOVE</method>
+				<ruri>$calendarpath2:/1.ics</ruri>
+				<header>
+					<name>Destination</name>
+					<value>$host:$sharedcalendar2:/1.ics</value>
+				</header>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User02 sees event</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar2:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/moves/1.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>User01 sees event</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/moves/1.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	
+	<test-suite name='Bad event to shared calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User02 store to personal calendar</description>
+			<request user="$puserid2:" pswd="$ppswd2:" end-delete="yes" print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarpath2:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/moves/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User02 moves event to shared calendar</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>MOVE</method>
+				<ruri>$calendarpath2:/2.ics</ruri>
+				<header>
+					<name>Destination</name>
+					<value>$host:$sharedcalendar2:/2.ics</value>
+				</header>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='OK event from shared calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 store to shared calendar</description>
+			<request print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/3.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/moves/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User02 moves event from shared calendar</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>MOVE</method>
+				<ruri>$sharedcalendar2:/3.ics</ruri>
+				<header>
+					<name>Destination</name>
+					<value>$host:$calendarpath2:/3.ics</value>
+				</header>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User02 sees event</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>GET</method>
+				<ruri>$calendarpath2:/3.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/moves/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>DELETE</method>
+				<ruri>$calendarpath2:/3.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>User01 sees no event</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/3.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>404</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	
+	<test-suite name='Bad event to shared calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 store to shared calendar</description>
+			<request end-delete="yes" print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/4.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/moves/4.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User02 moves event from shared calendar</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>MOVE</method>
+				<ruri>$sharedcalendar2:/4.ics</ruri>
+				<header>
+					<name>Destination</name>
+					<value>$host:$calendarpath2:/4.ics</value>
+				</header>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='OK owner event to shared calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 store to personal calendar</description>
+			<request print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarpath1:/5.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/moves/5.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User01 moves event to shared calendar</description>
+			<request print-response="no">
+				<method>MOVE</method>
+				<ruri>$calendarpath1:/5.ics</ruri>
+				<header>
+					<name>Destination</name>
+					<value>$host:$calendarhome1:/shared/5.ics</value>
+				</header>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User02 sees event</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar2:/5.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/moves/5.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>User01 sees event</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/5.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/moves/5.ics</value>
+					</arg>
+				</verify>
+			</request>
+			<request print-response="no">
+				<method>DELETE</method>
+				<ruri>$calendarhome1:/shared/5.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	
+	<test-suite name='OK owner event with organizer to shared calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 store to personal calendar</description>
+			<request print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarpath1:/6.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/moves/6.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User01 moves event to shared calendar</description>
+			<request print-response="no">
+				<method>MOVE</method>
+				<ruri>$calendarpath1:/6.ics</ruri>
+				<header>
+					<name>Destination</name>
+					<value>$host:$calendarhome1:/shared/6.ics</value>
+				</header>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User02 sees event</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar2:/6.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/moves/6.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>User01 sees event</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/6.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/moves/6.ics</value>
+					</arg>
+				</verify>
+			</request>
+			<request print-response="no">
+				<method>DELETE</method>
+				<ruri>$calendarhome1:/shared/6.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='OK owner event from shared calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 store to shared calendar</description>
+			<request print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/7.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/moves/7.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User01 moves event from shared calendar</description>
+			<request print-response="no">
+				<method>MOVE</method>
+				<ruri>$calendarhome1:/shared/7.ics</ruri>
+				<header>
+					<name>Destination</name>
+					<value>$host:$calendarpath1:/7.ics</value>
+				</header>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User02 does not see event</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar2:/7.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>404</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>User01 sees event</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarpath1:/7.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/moves/7.ics</value>
+					</arg>
+				</verify>
+			</request>
+			<request print-response="no">
+				<method>DELETE</method>
+				<ruri>$calendarpath1:/7.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	
+	<test-suite name='OK owner event with organizer from shared calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 store to shared calendar</description>
+			<request print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/8.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/moves/8.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User01 moves event from shared calendar</description>
+			<request print-response="no">
+				<method>MOVE</method>
+				<ruri>$calendarhome1:/shared/8.ics</ruri>
+				<header>
+					<name>Destination</name>
+					<value>$host:$calendarpath1:/8.ics</value>
+				</header>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User02 does not see event</description>
+			<request user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar2:/8.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>404</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>User01 sees event</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarpath1:/8.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/moves/8.ics</value>
+					</arg>
+				</verify>
+			</request>
+			<request print-response="no">
+				<method>DELETE</method>
+				<ruri>$calendarpath1:/8.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-multiple.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-multiple.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-multiple.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-multiple.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,429 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test calendar sharing invitations</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared1/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared2/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+	</start>
+	
+	<test-suite name='Send new invite #1'>
+		<test name='1' ignore='no'>
+			<description>Initial collection count</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabcount>$calendarhome2count:</grabcount>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared1/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+					<variable>$hosturl2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>One more calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>$calendarhome2count:+1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>One more calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>0</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Send new invite #2'>
+		<test name='1' ignore='no'>
+			<description>Initial collection count</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabcount>$calendarhome2count:</grabcount>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared2/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 2</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+					<variable>$hosturl2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>One more calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>$calendarhome2count:+1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>One more calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>0</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Uninvite #2'>
+		<test name='1' ignore='no'>
+			<description>Initial collection count</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabcount>$calendarhome2count:</grabcount>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared2/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingremove2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>2</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>One less calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>$calendarhome2count:-1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>One less calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>404</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Existing calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>0</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-notification-sync.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-notification-sync.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-notification-sync.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-notification-sync.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,1410 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test calendar sharing calendars</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+		<feature>sync-report</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request print-response='no'>
+			<method>PROPPATCH</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
+			</data>
+		</request>
+	</start>
+	
+	<test-suite name='initial tokens - depth 1' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>initial query - grab token</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$notificationpath1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>totalcount</name>
+						<value>0</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>initial query - grab token</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>totalcount</name>
+						<value>0</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Read-write calendar - depth 1' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>new resource</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>totalcount</name>
+						<value>1</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}response/{DAV:}href</name>
+					<variable>$href2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Remove notification</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETEALL</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>new resource</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$href2:</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='initial tokens - depth infinity' ignore='no'>
+		<test name='1' ignore='no'>
+			<require-feature>
+				<feature>sync-report-home</feature>
+			</require-feature>
+			<description>initial query - grab token</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>$notification:/</value>
+						<value>shared/</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$dropbox:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<require-feature>
+				<feature>sync-report-home</feature>
+			</require-feature>
+			<description>initial query - grab token</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>$notification:/</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$dropbox:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Read-write calendar - depth infinity - sharee delete'>
+		<require-feature>
+			<feature>sync-report-home</feature>
+		</require-feature>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>new resource</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<graburi>basename($notification2:)</graburi>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>totalcount</name>
+						<value>2</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Remove notification</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETEALL</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>deleted resource</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>$notification:/</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$notification:/$notification2:</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>new calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='7'>
+			<description>Sharee removes calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='8' ignore='no'>
+			<description>removed calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Read-write calendar - depth infinity - sharer removes'>
+		<require-feature>
+			<feature>sync-report-home</feature>
+		</require-feature>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>new resource</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<graburi>basename($notification2:)</graburi>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>totalcount</name>
+						<value>2</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Remove notification</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETEALL</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>deleted resource</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>$notification:/</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$notification:/$notification2:</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>new calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingremove2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETEALL</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+		</test>
+		<test name='8' ignore='no'>
+			<description>removed calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>ignoremissing</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='9' ignore='no'>
+			<description>no calendar change</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>totalcount</name>
+						<value>0</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Shared calendar data - depth infinity'>
+		<require-feature>
+			<feature>sync-report-home</feature>
+		</require-feature>
+		<test name='1'>
+			<description>Sharer creates event</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/notification-sync/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>new resource</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Remove notification</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETEALL</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>new calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>Grab sharer's sync token'</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='8'>
+			<description>Sharer creates event</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/notification-sync/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='9' ignore='no'>
+			<description>Sharer change</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+						<value>shared/2.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='10' ignore='no'>
+			<description>Sharee change</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='11'>
+			<description>Sharee creates event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PUT</method>
+				<ruri>$sharedcalendar:/3.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/notification-sync/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='12' ignore='no'>
+			<description>Sharer change</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+						<value>shared/3.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='13' ignore='no'>
+			<description>Sharee change</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='14'>
+			<description>Sharer deletes event</description>
+			<request>
+				<method>DELETE</method>
+				<ruri>$calendarhome1:/shared/3.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='15' ignore='no'>
+			<description>Sharer change</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>shared/3.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='16' ignore='no'>
+			<description>Sharee change</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='17'>
+			<description>Sharee deletes event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>DELETE</method>
+				<ruri>$sharedcalendar:/2.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='18' ignore='no'>
+			<description>Sharer change</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>shared/2.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='19' ignore='no'>
+			<description>Sharee change</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='20'>
+			<description>Sharee removes calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='21' ignore='no'>
+			<description>removed calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Response cache' ignore='no'>
+		<require-feature>
+			<feature>sync-report-home</feature>
+		</require-feature>
+		<test name='1' ignore='no'>
+			<description>PROPFIND of current sync-token - direct</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/sync-token.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>$verify-property-prefix:/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>PROPFIND of home</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/sync-token.xml</filepath>
+				</data>
+				<verify>
+					<callback>dataString</callback>
+					<arg>
+						<name>contains</name>
+						<value>$synctoken1:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>PROPFIND of home again - to cache it</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/sync-token.xml</filepath>
+				</data>
+				<verify>
+					<callback>dataString</callback>
+					<arg>
+						<name>contains</name>
+						<value>$synctoken1:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>PROPFIND of home - token changed</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/sync-token.xml</filepath>
+				</data>
+				<verify>
+					<callback>dataString</callback>
+					<arg>
+						<name>notcontains</name>
+						<value>$synctoken1:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>PROPFIND of new sync-token - direct</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/sync-token.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>$verify-property-prefix:/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>PROPFIND of home</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/sync-token.xml</filepath>
+				</data>
+				<verify>
+					<callback>dataString</callback>
+					<arg>
+						<name>contains</name>
+						<value>$synctoken2:</value>
+					</arg>
+					<arg>
+						<name>notcontains</name>
+						<value>$synctoken1:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8' ignore='no'>
+			<description>PROPFIND of home again - to cache it</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/sync-token.xml</filepath>
+				</data>
+				<verify>
+					<callback>dataString</callback>
+					<arg>
+						<name>contains</name>
+						<value>$synctoken2:</value>
+					</arg>
+					<arg>
+						<name>notcontains</name>
+						<value>$synctoken1:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='9'>
+			<description>Remove notification</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETEALL</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+		</test>
+		<test name='10' ignore='no'>
+			<description>PROPFIND of home - token changed</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/sync-token.xml</filepath>
+				</data>
+				<verify>
+					<callback>dataString</callback>
+					<arg>
+						<name>notcontains</name>
+						<value>$synctoken1:</value>
+						<value>$synctoken2:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-peruser-data.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-peruser-data.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-peruser-data.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-peruser-data.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,711 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest ignore-all='no'>
+	<description>Test calendar sharing per-user data</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+		</request>
+		<request print-response='no'>
+			<method>POST</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/POST/sharinginvite23-pod.xml</filepath>
+			</data>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+			<method>WAITCOUNT 1</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+			<method>GETNEW</method>
+			<ruri>$pnotificationpath2:/</ruri>
+			<grabelement>
+				<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+				<variable>$inviteuid2:</variable>
+			</grabelement>
+			<grabelement>
+				<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+				<variable>$hosturl2:</variable>
+			</grabelement>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+			<method>POST</method>
+			<ruri>$pcalendarhome2:/</ruri>
+			<data substitutions='yes'>
+				<content-type>application/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+			</data>
+			<grabelement>
+				<name>{DAV:}href</name>
+				<variable>$sharedcalendar2:</variable>
+			</grabelement>
+		</request>
+		<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+			<method>WAITCOUNT 1</method>
+			<ruri>$pnotificationpath3:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+			<method>GETNEW</method>
+			<ruri>$pnotificationpath3:/</ruri>
+			<grabelement>
+				<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+				<variable>$inviteuid3:</variable>
+			</grabelement>
+			<grabelement>
+				<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+				<variable>$hosturl3:</variable>
+			</grabelement>
+		</request>
+		<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+			<method>POST</method>
+			<ruri>$pcalendarhome3:/</ruri>
+			<data substitutions='yes'>
+				<content-type>application/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/POST/sharingreply3-pod.xml</filepath>
+			</data>
+			<grabelement>
+				<name>{DAV:}href</name>
+				<variable>$sharedcalendar3:</variable>
+			</grabelement>
+		</request>
+	</start>
+	
+	<test-suite name='Initial event' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 store to shared</description>
+			<request user="$userid1:" pswd="$pswd1:" print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-data/simple-put/1.ics</filepath>
+				</data>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User02 sees event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar2:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/peruser-data/simple-put/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User03 sees event</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar3:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/peruser-data/simple-put/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='User01 changed event' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 store to shared</description>
+			<request user="$userid1:" pswd="$pswd1:" print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-data/simple-change01/1.ics</filepath>
+				</data>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User02 sees event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar2:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/peruser-data/simple-change01/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User03 sees event</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar3:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/peruser-data/simple-change01/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='User02 changed event' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User02 store to shared</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PUT</method>
+				<ruri>$sharedcalendar2:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-data/simple-change02/1.ics</filepath>
+				</data>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User01 sees event</description>
+			<request user="$userid1:" pswd="$pswd1:" print-response="no">
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/peruser-data/simple-change02/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User03 sees event</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar3:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/peruser-data/simple-change02/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Different freebusy' ignore='no'>
+		<test name='1'>
+			<description>Set properties on new calendars</description>
+			<request print-response='no'>
+				<method>PROPPATCH</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp</value>
+					</arg>
+				</verify>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$sharedcalendar2:/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp</value>
+					</arg>
+				</verify>
+			</request>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$sharedcalendar3:/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User01 freebusy</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$outboxpath1:/</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/peruser-data/simple-freebusy/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User02 freebusy</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>POST</method>
+				<ruri>$poutboxpath2:/</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/peruser-data/simple-freebusy/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>User03 freebusy</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response="no">
+				<method>POST</method>
+				<ruri>$poutboxpath3:/</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/peruser-data/simple-freebusy/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='User01 complex recurring store' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 store to shared</description>
+			<request user="$userid1:" pswd="$pswd1:" print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-data/complex-put/1.ics</filepath>
+				</data>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User02 sees event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar2:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/peruser-data/complex-put/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User03 sees event</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar3:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/peruser-data/complex-put/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='User02 complex recurring store' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User02 store to shared</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PUT</method>
+				<ruri>$sharedcalendar2:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-data/complex-change02/1.ics</filepath>
+				</data>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User01 sees event</description>
+			<request user="$userid1:" pswd="$pswd1:" print-response="no">
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/peruser-data/complex-change02/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User03 sees event</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response="no">
+				<method>GET</method>
+				<ruri>$sharedcalendar3:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/peruser-data/complex-change02/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Complex freebusy' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 freebusy</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$outboxpath1:/</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/peruser-data/simple-freebusy/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T130000Z/$now.year.1:0101T140000Z</value>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+						<value>$now.year.1:0103T140000Z/$now.year.1:0103T150000Z</value>
+						<value>$now.year.1:0104T130000Z/$now.year.1:0104T140000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T130000Z/$now.year.1:0101T140000Z</value>
+						<value>$now.year.1:0102T130000Z/$now.year.1:0102T140000Z</value>
+						<value>$now.year.1:0104T130000Z/$now.year.1:0104T140000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T130000Z/$now.year.1:0101T140000Z</value>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+						<value>$now.year.1:0102T130000Z/$now.year.1:0102T140000Z</value>
+						<value>$now.year.1:0103T140000Z/$now.year.1:0103T150000Z</value>
+						<value>$now.year.1:0104T130000Z/$now.year.1:0104T140000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User02 freebusy</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>POST</method>
+				<ruri>$poutboxpath2:/</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/peruser-data/simple-freebusy/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T130000Z/$now.year.1:0101T140000Z</value>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+						<value>$now.year.1:0103T140000Z/$now.year.1:0103T150000Z</value>
+						<value>$now.year.1:0104T130000Z/$now.year.1:0104T140000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T130000Z/$now.year.1:0101T140000Z</value>
+						<value>$now.year.1:0102T130000Z/$now.year.1:0102T140000Z</value>
+						<value>$now.year.1:0104T130000Z/$now.year.1:0104T140000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T130000Z/$now.year.1:0101T140000Z</value>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+						<value>$now.year.1:0102T130000Z/$now.year.1:0102T140000Z</value>
+						<value>$now.year.1:0103T140000Z/$now.year.1:0103T150000Z</value>
+						<value>$now.year.1:0104T130000Z/$now.year.1:0104T140000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User03 freebusy</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response="no">
+				<method>POST</method>
+				<ruri>$poutboxpath3:/</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/peruser-data/simple-freebusy/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$cuaddr1:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T130000Z/$now.year.1:0101T140000Z</value>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+						<value>$now.year.1:0103T140000Z/$now.year.1:0103T150000Z</value>
+						<value>$now.year.1:0104T130000Z/$now.year.1:0104T140000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr2:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T130000Z/$now.year.1:0101T140000Z</value>
+						<value>$now.year.1:0102T130000Z/$now.year.1:0102T140000Z</value>
+						<value>$now.year.1:0104T130000Z/$now.year.1:0104T140000Z</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>postFreeBusy</callback>
+					<arg>
+						<name>attendee</name>
+						<value>$pcuaddr3:</value>
+					</arg>
+					<arg>
+						<name>busy</name>
+						<value>$now.year.1:0101T130000Z/$now.year.1:0101T140000Z</value>
+						<value>$now.year.1:0101T230000Z/$now.year.1:0102T000000Z</value>
+						<value>$now.year.1:0102T130000Z/$now.year.1:0102T140000Z</value>
+						<value>$now.year.1:0103T140000Z/$now.year.1:0103T150000Z</value>
+						<value>$now.year.1:0104T130000Z/$now.year.1:0104T140000Z</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Prevent per-user data injection' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>User01 new event with injected per-user data</description>
+			<request user="$userid1:" pswd="$pswd1:" end-delete="yes" print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-data/inject/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>prepostcondition</callback>
+					<arg>
+						<name>error</name>
+						<value>{urn:ietf:params:xml:ns:caldav}valid-calendar-data</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>User01 new event with valid data</description>
+			<request user="$userid1:" pswd="$pswd1:" end-delete="yes" print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-data/inject/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>User01 existing event with injected per-user data</description>
+			<request user="$userid1:" pswd="$pswd1:" print-response="no">
+				<method>PUT</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-data/inject/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>prepostcondition</callback>
+					<arg>
+						<name>error</name>
+						<value>{urn:ietf:params:xml:ns:caldav}valid-calendar-data</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+			<ruri>$pnotificationpath3:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-peruser-properties.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-peruser-properties.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-peruser-properties.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-peruser-properties.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,394 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test per-user WebDAV properties</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+	</start>
+	
+	<test-suite name='Read-write calendar'>
+		<test name='1' ignore='no'>
+			<description>PROPPATCH of displayname before share</description>
+			<request print-response='no'>
+				<method>PROPPATCH</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/nonglobal/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname</value>
+					</arg>
+				</verify>
+			</request>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/nonglobal/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname$Changed Name #1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>PROPPATCH of calendar-description before share</description>
+			<request print-response='no'>
+				<method>PROPPATCH</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/shadowable/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{urn:ietf:params:xml:ns:caldav}calendar-description</value>
+					</arg>
+				</verify>
+			</request>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/shadowable/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{urn:ietf:params:xml:ns:caldav}calendar-description$Description #1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$sharedcalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Shared calendar exists</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/calendars/read-write/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}owner/{DAV:}href[=$principaluri1:]</value>
+						<value>$verify-property-prefix:/{DAV:}resourcetype/{http://calendarserver.org/ns/}shared</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}read</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}write</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}bind</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}unbind</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}admin</value>
+						<value>$verify-property-prefix:/{DAV:}current-user-privilege-set/{DAV:}privilege/{DAV:}all</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='prop patches - non-global' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>PROPFIND of shared displayname</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/nonglobal/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname$The Shared Calendar</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>PROPPATCH of displayname</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPPATCH</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/nonglobal/3.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname</value>
+					</arg>
+				</verify>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/nonglobal/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname$Shared Name #2</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>PROPFIND of shared displayname</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/nonglobal/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname$Changed Name #1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='prop patches - shadowable' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>PROPFIND of shared calendar-description</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/shadowable/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{urn:ietf:params:xml:ns:caldav}calendar-description$Description #1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>PROPPATCH of calendar-description</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPPATCH</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/shadowable/3.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{urn:ietf:params:xml:ns:caldav}calendar-description</value>
+					</arg>
+				</verify>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$sharedcalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/shadowable/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{urn:ietf:params:xml:ns:caldav}calendar-description$Sharee Description #2</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>PROPFIND of shared calendar-description</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/peruser-properties/shadowable/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{urn:ietf:params:xml:ns:caldav}calendar-description$Description #1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-propfind.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-propfind.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-propfind.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-propfind.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,371 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request end-delete="yes">
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/1.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/1.txt</filepath>
+			</data>
+		</request>
+		<request end-delete="yes">
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/2.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/2.txt</filepath>
+			</data>
+		</request>
+		<request end-delete="yes">
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/3.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/3.txt</filepath>
+			</data>
+		</request>
+		<request end-delete="yes">
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/4.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/4.txt</filepath>
+			</data>
+		</request>
+		<request end-delete="yes">
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/5.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/5.txt</filepath>
+			</data>
+		</request>
+	</start>
+	
+	<test-suite name='Set up share'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>basename($shareecalendar2:)</variable>
+				</grabelement>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendarpath2:</variable>
+				</grabelement>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='regular home prop finds'>
+		<test name='1'>
+			<description>PROPFIND of basic properties depth=0</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/props.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>PROPFIND of basic properties depth=1</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/props.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>$calendar:/</value>
+						<value>$shareecalendar2:/</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>PROPFIND of basic properties depth=infinity</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>infinity</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/props.xml</filepath>
+				</data>
+				<verify>
+					<callback>prepostcondition</callback>
+					<arg>
+						<name>error</name>
+						<value>{DAV:}propfind-finite-depth</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='regular calendar prop finds'>
+		<test name='1'>
+			<description>PROPFIND of basic properties depth=0</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/props.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>PROPFIND of basic properties depth=1</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/props.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value></value>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+						<value>5.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>PROPFIND of basic properties depth=infinity</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>infinity</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/props.xml</filepath>
+				</data>
+				<verify>
+					<callback>prepostcondition</callback>
+					<arg>
+						<name>error</name>
+						<value>{DAV:}propfind-finite-depth</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='regular calendar resource prop finds'>
+		<test name='1'>
+			<description>PROPFIND of basic properties depth=0</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$shareecalendarpath2:/1.ics</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/props.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value></value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}creationdate</value>
+						<value>$verify-property-prefix:/{DAV:}getcontenttype</value>
+						<value>$verify-property-prefix:/{DAV:}getetag</value>
+						<value>$verify-property-prefix:/{DAV:}getlastmodified</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>PROPFIND of basic properties depth=1</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$shareecalendarpath2:/1.ics</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/props.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value></value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>PROPFIND of basic properties depth=infinity</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPFIND</method>
+				<ruri>$shareecalendarpath2:/1.ics</ruri>
+				<header>
+					<name>Depth</name>
+					<value>infinity</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/props.xml</filepath>
+				</data>
+				<verify>
+					<callback>prepostcondition</callback>
+					<arg>
+						<name>error</name>
+						<value>{DAV:}propfind-finite-depth</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+	
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-proxies.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-proxies.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-proxies.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-proxies.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,569 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test calendar sharing with proxies</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+		<feature>proxy</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request host2="yes" user="$userid4:" pswd="$pswd4:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+	</start>
+	
+	<test-suite name='Setup proxies' ignore="no">
+		<test name='1'>
+			<description>Add user03 as read proxy for user02</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$pprincipal2:calendar-proxy-read/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/proxies/setupproxies/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}group-member-set</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Add user04 as write proxy for user02</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+				<method>PROPPATCH</method>
+				<ruri>$pprincipal2:calendar-proxy-write/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/proxies/setupproxies/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}group-member-set</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Set up share'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/Common/POST/sharedas.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{DAV:}href</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Check accept status</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/proxies/setupproxies/4.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Check Sharer notification collection</description>
+			<request>
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationreply2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Sharer adds event</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/proxies/setupproxies/5.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Proxies see calendar and contents'>
+		<test name='1'>
+			<description>Read proxy lists calendar home</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>$shareecalendar:/</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Write proxy lists calendar home</description>
+			<request host2="yes" user="$puserid4:" pswd="$ppswd4:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>prefix</name>
+						<value/>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>$shareecalendar:/</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Read proxy lists calendar</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$shareecalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Write proxy lists calendar</description>
+			<request host2="yes" user="$puserid4:" pswd="$ppswd4:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$shareecalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Proxy data changes'>
+		<test name='1'>
+			<description>Read proxy cannot write new data</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$shareecalendar:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/proxies/put/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Read proxy cannot write existing data</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$shareecalendar:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/proxies/setupproxies/5.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Write proxy can write new data</description>
+			<request host2="yes" user="$puserid4:" pswd="$ppswd4:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$shareecalendar:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/proxies/put/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Sharer sees new data</description>
+			<request print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/proxies/put/1.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharee sees new data</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$shareecalendar:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/proxies/put/1.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Write proxy can write existing data with per-user alarm</description>
+			<request host2="yes" user="$puserid4:" pswd="$ppswd4:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$shareecalendar:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/proxies/put/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='7'>
+			<description>Sharer sees new data without alarm</description>
+			<request print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/proxies/put/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8'>
+			<description>Sharee sees new data with alarm</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$shareecalendar:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/proxies/put/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Proxy property changes'>
+		<test name='1'>
+			<description>Read proxy cannot write properties</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>PROPPATCH</method>
+				<ruri>$shareecalendar:/</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/proxies/properties/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>403</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Write proxy can write properties</description>
+			<request host2="yes" user="$puserid4:" pswd="$ppswd4:" print-response='no'>
+				<method>PROPPATCH</method>
+				<ruri>$shareecalendar:/</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/proxies/properties/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>Sharer sees original displayname</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/displayname.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname$</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Sharee sees new displayname</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$shareecalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/displayname.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname$Changed Name #1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+			<ruri>$pnotificationpath3:/</ruri>
+			<ruri>$pnotificationpath4:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+			<method>PROPPATCH</method>
+			<ruri>$pprincipal2:calendar-proxy-read/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV-pod/sharing/proxies/setupproxies/3.xml</filepath>
+			</data>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response="no">
+			<method>PROPPATCH</method>
+			<ruri>$pprincipal2:calendar-proxy-write/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV-pod/sharing/proxies/setupproxies/3.xml</filepath>
+			</data>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-replies.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-replies.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-replies.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-replies.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,286 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test calendar sharing replies</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+	</start>
+	
+	<test-suite name='Send first reply'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/Common/POST/sharedas.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{DAV:}href</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Check accept status</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/replies/accept/1.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Check Sharer notification collection</description>
+			<request>
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationreply2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Check sharee calendar displyname/shared-url</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$shareecalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/replies/accept/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindValues</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname$The Shared Calendar</value>
+						<value>{http://calendarserver.org/ns/}sharedurl$$calendarhome1:/shared</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>Check sharer calendar displyname</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/displayname.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname$shared</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Update reply'>
+		<test name='1'>
+			<description>Sharee replies DECLINED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingdecline2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>Check declined status</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/replies/decline/1.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Check Sharer notification collection</description>
+			<request>
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationdecline2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-reports-multiget.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-reports-multiget.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-reports-multiget.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-reports-multiget.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,730 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<require-feature>
+		<feature>caldav</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared-tasks/</ruri>
+			<data>
+				<content-type>application/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/MKCALENDAR/vtodo.xml</filepath>
+			</data>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/1.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/1.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/2.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/2.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/3.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/3.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/4.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/4.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/5.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/5.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/6.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/6.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/7.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/7.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/8.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/8.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/9.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/9.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/10.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/10.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/11.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/11.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/12.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/12.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/13.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/13.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/14.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/14.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<exclude-feature>
+				<feature>split-calendars</feature>
+			</exclude-feature>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/15.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/15.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/18.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/18.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/19.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/19.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/20.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/20.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/21.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/21.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/22.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/22.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared/27.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/27.ics</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared-tasks/101.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/101.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared-tasks/102.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/102.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared-tasks/103.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/103.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared-tasks/104.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/104.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared-tasks/105.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/105.txt</filepath>
+			</data>
+		</request>
+		<request>
+			<method>PUT</method>
+			<ruri>$calendarhome1:/shared-tasks/106.ics</ruri>
+			<data>
+				<content-type>text/calendar; charset=utf-8</content-type>
+				<filepath>Resource/CalDAV/reports/put/106.txt</filepath>
+			</data>
+		</request>
+	</start>
+	
+	<test-suite name='Set up share'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>basename($shareecalendar2:)</variable>
+				</grabelement>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendarpath2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>POST invitation</description>
+			<request>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared-tasks/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>WAITCOUNT 2</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>basename($shareetasks2:)</variable>
+				</grabelement>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareetaskspath2:</variable>
+				</grabelement>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='multiget reports' ignore='no'>
+		<test name='1a' ignore='no'>
+			<description>basic multiget of 4 resources returning etag and entire ics data</description>
+			<pause/>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/1.xml</filepath>
+				</data>
+				<verify>
+					<exclude-feature>
+						<feature>split-calendars</feature>
+					</exclude-feature>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+						<value>101.ics</value>
+						<value>102.ics</value>
+					</arg>
+				</verify>
+				<verify>
+					<require-feature>
+						<feature>split-calendars</feature>
+					</require-feature>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>101.ics</value>
+						<value>102.ics</value>
+					</arg>
+				</verify>
+			</request>
+			<pause/>
+		</test>
+		<test name='1b' ignore='no'>
+			<require-feature>
+				<feature>split-calendars</feature>
+			</require-feature>
+			<description>basic multiget of 4 resources returning etag and entire ics data</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareetaskspath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/1b.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>101.ics</value>
+						<value>102.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>basic multiget of 4 resources returning etag and only VCALENDAR property data (no embedded components)</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/2.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>basic multiget of 4 resources returning etag and only VTIMEZONE components</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/3.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4a' ignore='no'>
+			<description>basic multiget of 4 resources returning etag and only SUMMARY/UID properties inside VEVENT components and VALARMs</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/4.xml</filepath>
+				</data>
+				<verify>
+					<exclude-feature>
+						<feature>split-calendars</feature>
+					</exclude-feature>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+						<value>101.ics</value>
+						<value>102.ics</value>
+					</arg>
+				</verify>
+				<verify>
+					<require-feature>
+						<feature>split-calendars</feature>
+					</require-feature>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>101.ics</value>
+						<value>102.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4b' ignore='no'>
+			<require-feature>
+				<feature>split-calendars</feature>
+			</require-feature>
+			<description>basic multiget of 4 resources returning etag and only SUMMARY/UID properties inside VEVENT components and VALARMs</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareetaskspath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/4b.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>101.ics</value>
+						<value>102.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5a' ignore='no'>
+			<description>as 4.xml except that the SUMMARY property value is not returned</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/5.xml</filepath>
+				</data>
+				<verify>
+					<exclude-feature>
+						<feature>split-calendars</feature>
+					</exclude-feature>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+						<value>101.ics</value>
+						<value>102.ics</value>
+					</arg>
+				</verify>
+				<verify>
+					<require-feature>
+						<feature>split-calendars</feature>
+					</require-feature>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>101.ics</value>
+						<value>102.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5b' ignore='no'>
+			<require-feature>
+				<feature>split-calendars</feature>
+			</require-feature>
+			<description>as 4.xml except that the SUMMARY property value is not returned</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareetaskspath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/5b.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>101.ics</value>
+						<value>102.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Does allprop</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/6.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>Does propname</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/7.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+						<value>2.ics</value>
+						<value>3.ics</value>
+						<value>4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8' ignore='no'>
+			<description>Single non-existent query</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>REPORT</method>
+				<ruri>$shareecalendarpath2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/multiget/8.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>bogus-resource.ics</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-bad-response:[*404]</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+	
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-sync.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-sync.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-sync.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-sync.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,1810 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test calendar sharing and cached home sync tokens</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+		<feature>sync-report</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+		<request print-response='no'>
+			<method>PROPPATCH</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<data>
+				<content-type>text/xml; charset=utf-8</content-type>
+				<filepath>Resource/Common/PROPPATCH/calendar-transp-opaque.xml</filepath>
+			</data>
+		</request>
+	</start>
+	
+	<test-suite name='Read-write calendar'>
+		<test name='1' ignore='no'>
+			<description>Initial sync tokens</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken3:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken4:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken5:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+					<variable>$hosturl2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>basename($sharedcalendar:)</variable>
+				</grabelement>
+			</request>
+			<request>
+				<method>DELETEALL</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>DELETEALL</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>Updated tokens</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+						<value>$notification:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+						<value>1</value>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+						<value>$notification:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token3-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken3:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token4-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>$sharedcalendar:/</value>
+						<value>$notification:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken4:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token5-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+						<value>1</value>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>$notification:/</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken5:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken6:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Sharee creates event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/sync/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>Updated tokens</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+						<value>shared/1.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token3-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken3:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token4-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken4:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token5-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken5:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token6-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken6:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='8'>
+			<description>Sharer changes event</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/sync/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='9' ignore='no'>
+			<description>Updated tokens</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+						<value>shared/1.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token3-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken3:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token4-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken4:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token5-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken5:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token6-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>1.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken6:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='10'>
+			<description>Sharee deletes event</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/1.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='11' ignore='no'>
+			<description>Updated tokens</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>shared/1.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token3-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>1.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken3:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token4-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken4:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token5-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken5:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token6-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>1.ics</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken6:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='12'>
+			<description>Sharer unshares</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingremove2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='13' ignore='no'>
+			<description>Updated tokens</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token3-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken3:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token4-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>$notification:/</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken4:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token5-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>ignoremissing</name>
+						<value>1</value>
+					</arg>
+					<arg>
+						<name>okhrefs</name>
+						<value>$notification:/</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken5:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token6-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>404</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+
+	<test-suite name='calendar webdav property change - home depth:infinity' ignore='no'>
+		<require-feature>
+			<feature>sync-report-home</feature>
+		</require-feature>
+		<test name='1' ignore='no'>
+			<description>POST invitation and accept</description>
+			<request>
+				<method>DELETEALL</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>DELETEALL</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+					<variable>$hosturl2:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>basename($sharedcalendar:)</variable>
+				</grabelement>
+			</request>
+			<request>
+				<method>DELETEALL</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>DELETEALL</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>initial query - grab token</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>$calendar:/</value>
+						<value>shared/</value>
+					</arg>
+					<arg>
+						<name>ignoremissing</name>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>initial query - grab token for user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>$calendar:/</value>
+					</arg>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+					<arg>
+						<name>ignoremissing</name>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Change a property by user 1</description>
+			<request>
+				<method>PROPPATCH</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/reports/sync/17.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>Sync for user 1</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[!$synctoken1:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Sync for user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[$synctoken2:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>Remove a property by user 1</description>
+			<request>
+				<method>PROPPATCH</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/reports/sync/18.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='8' ignore='no'>
+			<description>Sync for user 1</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[!$synctoken1:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='9' ignore='no'>
+			<description>Sync for user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[$synctoken2:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='10' ignore='no'>
+			<description>Change a property by user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPPATCH</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/reports/sync/17.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='11' ignore='no'>
+			<description>Sync for user 1</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[$synctoken1:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='12' ignore='no'>
+			<description>Sync for user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[$synctoken2:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='13' ignore='no'>
+			<description>Remove a property by user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPPATCH</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/reports/sync/18.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='14' ignore='no'>
+			<description>Sync for user 1</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[$synctoken1:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='15' ignore='no'>
+			<description>Sync for user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-infinite.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>badhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[$synctoken2:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='16'>
+			<description>Sharer unshares</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingremove2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='calendar webdav property change - home depth:1' ignore='no'>
+		<require-feature>
+			<feature>sync-report-home</feature>
+		</require-feature>
+		<test name='1' ignore='no'>
+			<description>POST invitation and accept</description>
+			<request user="$useradmin:" pswd="$pswdadmin:">
+				<method>DELETEALL</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>DELETEALL</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+					<variable>$hosturl2:</variable>
+				</grabelement>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>basename($sharedcalendar:)</variable>
+				</grabelement>
+			</request>
+			<request user="$useradmin:" pswd="$pswdadmin:">
+				<method>DELETEALL</method>
+				<ruri>$notificationpath1:/</ruri>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>initial query - grab token</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>$calendar:/</value>
+						<value>shared/</value>
+					</arg>
+					<arg>
+						<name>ignoremissing</name>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>initial query - grab token for user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-init-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>$calendar:/</value>
+						<value>$sharedcalendar:/</value>
+					</arg>
+					<arg>
+						<name>ignoremissing</name>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Change a property by user 1</description>
+			<request>
+				<method>PROPPATCH</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/reports/sync/17.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>Sync for user 1</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[!$synctoken1:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Sync for user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[$synctoken2:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>Remove a property by user 1</description>
+			<request>
+				<method>PROPPATCH</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/reports/sync/18.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='8' ignore='no'>
+			<description>Sync for user 1</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>shared/</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[!$synctoken1:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='9' ignore='no'>
+			<description>Sync for user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[$synctoken2:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='10' ignore='no'>
+			<description>Change a property by user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPPATCH</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/reports/sync/17.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='11' ignore='no'>
+			<description>Sync for user 1</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[$synctoken1:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='12' ignore='no'>
+			<description>Sync for user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[!$synctoken2:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='13' ignore='no'>
+			<description>Remove a property by user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PROPPATCH</method>
+				<ruri>$pcalendarhome2:/$sharedcalendar:/</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/reports/sync/18.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='14' ignore='no'>
+			<description>Sync for user 1</description>
+			<request print-response='no'>
+				<method>REPORT</method>
+				<ruri>$calendarhome1:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token1-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[$synctoken1:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken1:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='15' ignore='no'>
+			<description>Sync for user 2</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>REPORT</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/REPORT/sync-token2-level-1.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>okhrefs</name>
+						<value>$sharedcalendar:/</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>/{DAV:}multistatus/{DAV:}sync-token[!$synctoken2:]</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>/{DAV:}multistatus/{DAV:}sync-token</name>
+					<variable>$synctoken2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='16'>
+			<description>Sharer unshares</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingremove2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+	</end>
+	
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-unshare.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-unshare.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-unshare.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-unshare.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,500 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test calendar sharing unshare/delete behavior</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+	</start>
+	
+	<test-suite name='Set up share' ignore="no">
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/Common/POST/sharedas.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{DAV:}href</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Check accept status</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/invited2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Check Sharer notification collection</description>
+			<request>
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationreply2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='Delete' ignore="no">
+		<test name='1'>
+			<description>Sharer adds event</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/unshare/shareedelete/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>Sharee deletes shared calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$shareecalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>infinity</value>
+				</header>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>No more shared calendar</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$shareecalendar:/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/resourcetype.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>404</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Sharer still has calendar data</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>1</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/count.xml</filepath>
+				</data>
+				<verify>
+					<callback>multistatusItems</callback>
+					<arg>
+						<name>count</name>
+						<value>1</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='Reshare after sharee DELETE shared calendar' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationinvite2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/Common/POST/sharedas.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{DAV:}href</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Check accept status</description>
+			<request print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<header>
+					<name>Depth</name>
+					<value>0</value>
+				</header>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/PROPFIND/invite.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/invited2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Check Sharer notification collection</description>
+			<request>
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/common/notificationreply2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+
+	<test-suite name='Invite, display name change, uninvite' ignore="no">
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/unshare/shareruninvite/1.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath3:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath3:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/unshare/shareruninvite/2.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee replies ACCEPTED</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome3:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/unshare/shareruninvite/3.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/unshare/shareruninvite/4.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{DAV:}href</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Sharee changes name</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>PROPPATCH</method>
+				<ruri>$shareecalendar:/</ruri>
+				<data>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/unshare/shareruninvite/5.xml</filepath>
+				</data>
+				<verify>
+					<callback>propfindItems</callback>
+					<arg>
+						<name>okprops</name>
+						<value>{DAV:}displayname</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>POST uninvitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV-pod/sharing/unshare/shareruninvite/6.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Check Sharee notification collection</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath3:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath3:/</ruri>
+				<verify>
+					<callback>xmlDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV-pod/sharing/unshare/shareruninvite/7.xml</value>
+					</arg>
+					<arg>
+						<name>filter</name>
+						<value>{http://calendarserver.org/ns/}dtstamp</value>
+						<value>{http://calendarserver.org/ns/}uid</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid:</variable>
+				</grabelement>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+			<ruri>$pnotificationpath3:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-webcal.xml (from rev 12132, CalDAVTester/trunk/scripts/tests-pod/CalDAV/sharing-webcal.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-webcal.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/scripts/tests-pod/CalDAV/sharing-webcal.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,498 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test internet calendar subscription behavior with sharing</description>
+
+	<require-feature>
+		<feature>caldav</feature>
+		<feature>webcal</feature>
+		<feature>shared-calendars</feature>
+	</require-feature>
+
+	<start>
+		<request user="$userid1:" pswd="$pswd1:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+		</request>
+		<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath3:/</ruri>
+		</request>
+		<request end-delete="yes">
+			<method>MKCALENDAR</method>
+			<ruri>$calendarhome1:/shared/</ruri>
+			<verify>
+				<callback>statusCode</callback>
+			</verify>
+		</request>
+	</start>
+	
+	<test-suite name='Setup two sharees'>
+		<test name='1' ignore='no'>
+			<description>POST invitation</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharinginvite23-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>Check Sharee 2 notification collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath2:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid2:</variable>
+				</grabelement>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+					<variable>$hosturl2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Sharee 2 replies ACCEPTED</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply2-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Check Sharee 3 notification collection</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$pnotificationpath3:/</ruri>
+			</request>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$pnotificationpath3:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid3:</variable>
+				</grabelement>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}hosturl/{DAV:}href</name>
+					<variable>$hosturl3:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Sharee 3 replies ACCEPTED</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:" print-response='no'>
+				<method>POST</method>
+				<ruri>$pcalendarhome3:/</ruri>
+				<data substitutions='yes'>
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/Common/POST/sharingreply3-pod.xml</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<grabelement>
+					<name>{DAV:}href</name>
+					<variable>$shareecalendar3:</variable>
+				</grabelement>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='GET on empty calendar collection'>
+		<test name='1'>
+			<description>GET on empty calendar collection</description>
+			<request>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/1.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>GET on empty calendar collection - 2nd time from cache</description>
+			<request>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/1.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>GET on empty calendar collection</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GET</method>
+				<ruri>$shareecalendar2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/1.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>GET on empty calendar collection - 2nd time from cache</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GET</method>
+				<ruri>$shareecalendar2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/1.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>GET on empty calendar collection</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+				<method>GET</method>
+				<ruri>$shareecalendar3:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/1.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>GET on empty calendar collection - 2nd time from cache</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+				<method>GET</method>
+				<ruri>$shareecalendar3:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/1.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='GET on calendar collection after initial PUT'>
+		<test name='1'>
+			<description>GET on calendar collection after initial PUT</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarhome1:/shared/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/webcal/rolled/2.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>GET on calendar collection after initial PUT - 2nd time from cache</description>
+			<request>
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>GET on calendar collection after initial PUT</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GET</method>
+				<ruri>$shareecalendar2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>GET on calendar collection after initial PUT - 2nd time from cache</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GET</method>
+				<ruri>$shareecalendar2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>GET on calendar collection after initial PUT</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+				<method>GET</method>
+				<ruri>$shareecalendar3:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>GET on calendar collection after initial PUT - 2nd time from cache</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+				<method>GET</method>
+				<ruri>$shareecalendar3:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='GET on calendar collection after sharee PUT'>
+		<test name='1'>
+			<description>GET on calendar collection after sharee PUT</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>PUT</method>
+				<ruri>$shareecalendar2:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/sharing/webcal/rolled/4.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/5.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='2'>
+			<description>GET on calendar collection after sharee PUT - 2nd time from cache</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarhome1:/shared/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/5.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>GET on calendar collection after sharee PUT</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GET</method>
+				<ruri>$shareecalendar2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/6.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>GET on calendar collection after sharee PUT - 2nd time from cache</description>
+			<request host2="yes" user="$puserid2:" pswd="$ppswd2:">
+				<method>GET</method>
+				<ruri>$shareecalendar2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/6.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>GET on calendar collection after sharee PUT</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+				<method>GET</method>
+				<ruri>$shareecalendar3:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/7.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>GET on calendar collection after sharee PUT - 2nd time from cache</description>
+			<request host2="yes" user="$puserid3:" pswd="$ppswd3:">
+				<method>GET</method>
+				<ruri>$shareecalendar3:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/sharing/webcal/rolled/7.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$notificationpath1:/</ruri>
+		</request>
+		<request host2="yes" user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$pnotificationpath2:/</ruri>
+			<ruri>$pnotificationpath3:/</ruri>
+		</request>
+	</end>
+
+</caldavtest>

Modified: CalDAVTester/branches/users/gaya/sharedgroupfixestester/verifiers/multistatusItems.py
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupfixestester/verifiers/multistatusItems.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalDAVTester/branches/users/gaya/sharedgroupfixestester/verifiers/multistatusItems.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -47,9 +47,9 @@
             prefix = prefix[0] if prefix[0] != "-" else ""
         else:
             prefix = uri
-        okhrefs = [prefix + i for i in okhrefs]
-        nohrefs = [prefix + i for i in nohrefs]
-        badhrefs = [prefix + i for i in badhrefs]
+        okhrefs = [(prefix + i).rstrip("/") for i in okhrefs]
+        nohrefs = [(prefix + i).rstrip("/") for i in nohrefs]
+        badhrefs = [(prefix + i).rstrip("/") for i in badhrefs]
         for k, v in args.items():
             v = [prefix + i for i in v]
             args[k] = v
@@ -86,7 +86,7 @@
             href = response.findall("{DAV:}href")
             if href is None or len(href) != 1:
                 return False, "        Incorrect/missing DAV:Href element in response"
-            href = urllib.unquote(href[0].text)
+            href = urllib.unquote(href[0].text).rstrip("/")
 
             # Verify status
             status = response.findall("{DAV:}status")


Property changes on: CalendarServer/branches/users/gaya/sharedgroupfixes
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/trunk:11193-11198
/CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/json:11622-11912
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/reverse-proxy-pods:11875-11900
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/sharing-in-the-store:11935-12016
/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
/CalendarServer/branches/users/glyph/hang-fix:11465-11491
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
/CalendarServer/branches/users/glyph/whenNotProposed:11881-11897
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations:5515-5593
/CalendarServer/trunk:11632-11860,11862-12017
   + /CalDAVTester/trunk:11193-11198
/CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/json:11622-11912
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/reverse-proxy-pods:11875-11900
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/sharing-in-the-store:11935-12016
/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
/CalendarServer/branches/users/glyph/hang-fix:11465-11491
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
/CalendarServer/branches/users/glyph/whenNotProposed:11881-11897
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
/CalendarServer/branches/users/wsanchez/transations:5515-5593
/CalendarServer/trunk:11632-11860,11862-12132

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/bin/proxyclean
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/bin/proxyclean	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/bin/proxyclean	2013-12-19 04:51:29 UTC (rev 12142)
@@ -26,7 +26,7 @@
 except ImportError:
     sys.exc_clear()
 
-from twext.python.plistlib import readPlist
+from plistlib import readPlist
 
 try:
     import opendirectory

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/bin/trial
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/bin/trial	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/bin/trial	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,7 +16,10 @@
 # limitations under the License.
 ##
 
+from __future__ import print_function
+
 import sys
+import os
 
 #PYTHONPATH
 
@@ -29,5 +32,8 @@
         except ImportError:
             sys.exc_clear()
 
+    for name, value in os.environ.items():
+        print("{0}={1}".format(name, value))
+
     from twisted.scripts.trial import run
     run()

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/__init__.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/__init__.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -19,13 +19,10 @@
 CalendarServer application code.
 """
 
-# Make sure we have twext's required Twisted patches loaded before we do
-# anything at all.
-__import__("twext")
-
 #
 # setuptools is annoying
 #
+
 from warnings import filterwarnings
 filterwarnings("ignore", "Module (.*) was already imported (.*)")
 del filterwarnings
@@ -38,3 +35,11 @@
     from calendarserver.version import version as __version__
 except ImportError:
     __version__ = None
+
+
+#
+# Get imap4 module to STFU
+#
+
+# from twisted.mail.imap4 import Command
+# Command._1_RESPONSES += tuple(['BYE'])

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/accesslog.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/accesslog.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/accesslog.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -40,9 +40,9 @@
     getAdjustedClientName
 
 from twext.python.log import Logger
-from twext.web2 import iweb
-from twext.web2.log import BaseCommonAccessLoggingObserver
-from twext.web2.log import LogWrapperResource
+from txweb2 import iweb
+from txweb2.log import BaseCommonAccessLoggingObserver
+from txweb2.log import LogWrapperResource
 
 from twisted.internet import protocol, task
 from twisted.protocols import amp

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/provision/root.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/provision/root.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/provision/root.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -20,11 +20,11 @@
 ]
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.auth.wrapper import UnauthorizedResponse
+from txweb2 import responsecode
+from txweb2.auth.wrapper import UnauthorizedResponse
 from txdav.xml import element as davxml
-from twext.web2.dav.xattrprops import xattrPropertyStore
-from twext.web2.http import HTTPError, StatusResponse, RedirectResponse
+from txweb2.dav.xattrprops import xattrPropertyStore
+from txweb2.http import HTTPError, StatusResponse, RedirectResponse
 
 from twisted.cred.error import LoginFailed, UnauthorizedLogin
 from twisted.internet.defer import inlineCallbacks, returnValue
@@ -91,7 +91,7 @@
             self.responseCache = DisabledCache()
 
         if config.ResponseCompression:
-            from twext.web2.filter import gzip
+            from txweb2.filter import gzip
             self.contentFilters.append((gzip.gzipfilter, True))
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/provision/test/test_root.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/provision/test/test_root.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/provision/test/test_root.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -19,15 +19,15 @@
 from twisted.cred.portal import Portal
 from twisted.internet.defer import inlineCallbacks, maybeDeferred, returnValue
 
-from twext.web2 import http_headers
-from twext.web2 import responsecode
-from twext.web2 import server
-from twext.web2.auth import basic
-from twext.web2.dav import auth
+from txweb2 import http_headers
+from txweb2 import responsecode
+from txweb2 import server
+from txweb2.auth import basic
+from txweb2.dav import auth
 from txdav.xml import element as davxml
-from twext.web2.http import HTTPError
-from twext.web2.iweb import IResponse
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.http import HTTPError
+from txweb2.iweb import IResponse
+from txweb2.test.test_server import SimpleRequest
 
 from twistedcaldav.test.util import TestCase
 from twistedcaldav.directory.principal import DirectoryPrincipalProvisioningResource

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/push/applepush.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/push/applepush.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/push/applepush.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -18,12 +18,12 @@
 from twext.internet.ssl import ChainingOpenSSLContextFactory
 from twext.python.log import Logger
 
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
-from twext.web2.dav.noneprops import NonePropertyStore
-from twext.web2.http import Response
-from twext.web2.http_headers import MimeType
-from twext.web2.server import parsePOSTData
+from txweb2.dav.noneprops import NonePropertyStore
+from txweb2.http import Response
+from txweb2.http_headers import MimeType
+from txweb2.server import parsePOSTData
 from twisted.application import service
 from twisted.internet import protocol
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
@@ -888,7 +888,7 @@
         to add a subscription entry to the database.
 
         @param request: The request to process
-        @type request: L{twext.web2.server.Request}
+        @type request: L{txweb2.server.Request}
         """
 
         token = request.args.get("token", ("",))[0].replace(" ", "").lower()

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/caldav.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/caldav.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -52,15 +52,15 @@
 from twisted.application.service import Service
 from twisted.protocols.amp import AMP
 
-from twext.web2.server import Site
+from txweb2.server import Site
 from twext.python.log import Logger, LogLevel, replaceTwistedLoggers
 from twext.python.filepath import CachingFilePath
 from twext.internet.ssl import ChainingOpenSSLContextFactory
 from twext.internet.tcp import MaxAcceptTCPServer, MaxAcceptSSLServer
 from twext.internet.fswatch import DirectoryChangeListener, IDirectoryChangeListenee
-from twext.web2.channel.http import LimitingHTTPFactory, SSLRedirectRequest, \
+from txweb2.channel.http import LimitingHTTPFactory, SSLRedirectRequest, \
     HTTPChannel
-from twext.web2.metafd import ConnectionLimiter, ReportingHTTPService
+from txweb2.metafd import ConnectionLimiter, ReportingHTTPService
 from twext.enterprise.ienterprise import POSTGRES_DIALECT
 from twext.enterprise.ienterprise import ORACLE_DIALECT
 from twext.enterprise.adbapi2 import ConnectionPool
@@ -119,7 +119,7 @@
     from version import version as getVersion
     version = "%s (%s*)" % getVersion()
 
-from twext.web2.server import VERSION as TWISTED_VERSION
+from txweb2.server import VERSION as TWISTED_VERSION
 TWISTED_VERSION = "CalendarServer/%s %s" % (
     version.replace(" ", ""), TWISTED_VERSION,
 )

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/test/test_caldav.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/test/test_caldav.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/test/test_caldav.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -42,9 +42,9 @@
 
 from twext.python.log import Logger
 from twext.python.filepath import CachingFilePath as FilePath
-from twext.python.plistlib import writePlist #@UnresolvedImport
-from twext.web2.dav import auth
-from twext.web2.log import LogWrapperResource
+from plistlib import writePlist #@UnresolvedImport
+from txweb2.dav import auth
+from txweb2.log import LogWrapperResource
 from twext.internet.tcp import MaxAcceptTCPServer, MaxAcceptSSLServer
 
 from twistedcaldav.config import config, ConfigDict, ConfigurationError

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/util.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tap/util.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -34,11 +34,11 @@
 
 from twext.python.filepath import CachingFilePath as FilePath
 from twext.python.log import Logger
-from twext.web2.auth.basic import BasicCredentialFactory
-from twext.web2.dav import auth
-from twext.web2.http_headers import Headers
-from twext.web2.resource import Resource
-from twext.web2.static import File as FileResource
+from txweb2.auth.basic import BasicCredentialFactory
+from txweb2.dav import auth
+from txweb2.http_headers import Headers
+from txweb2.resource import Resource
+from txweb2.static import File as FileResource
 
 from twisted.application.service import Service
 from twisted.cred.portal import Portal
@@ -130,7 +130,7 @@
         databaseName=config.Postgres.DatabaseName,
         clusterName=config.Postgres.ClusterName,
         logFile=config.Postgres.LogFile,
-        socketDir=config.RunRoot,
+        socketDir=config.Postgres.SocketDirectory,
         listenAddresses=config.Postgres.ListenAddresses,
         sharedBuffers=config.Postgres.SharedBuffers,
         maxConnections=config.Postgres.MaxConnections,

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/agent.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/agent.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/agent.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -30,7 +30,7 @@
 import socket
 
 from calendarserver.tap.util import getRootResource
-from twext.python.plistlib import readPlistFromString, writePlistToString
+from plistlib import readPlistFromString, writePlistToString
 from twisted.application.internet import StreamServerEndpointService
 from twisted.cred.checkers import ICredentialsChecker
 from twisted.cred.credentials import IUsernameHashedPassword

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/anonymize.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/anonymize.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/anonymize.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -31,7 +31,7 @@
 import xattr
 import zlib
 
-from twext.python.plistlib import readPlistFromString
+from plistlib import readPlistFromString
 
 from pycalendar.icalendar.calendar import Calendar
 from pycalendar.parameter import Parameter

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/backup_pg.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/backup_pg.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/backup_pg.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -35,7 +35,7 @@
 
 PSQL          = "%s/usr/bin/psql" % (SIPP,)
 PGDUMP        = "%s/usr/bin/pg_dump" % (SIPP,)
-PGSOCKETDIR   = "/Library/Server/PostgreSQL For Server Services/Socket"
+PGSOCKETDIR   = "/var/run/caldavd/PostgresSocket"
 
 def usage(e=None):
     name = os.path.basename(sys.argv[0])

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/config.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/config.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/config.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -28,7 +28,7 @@
 import sys
 import xml
 
-from twext.python.plistlib import readPlistFromString, writePlistToString
+from plistlib import readPlistFromString, writePlistToString
 from twistedcaldav.config import config, ConfigDict, ConfigurationError, mergeData
 from twistedcaldav.stdconfig import DEFAULT_CONFIG_FILE
 WRITABLE_CONFIG_KEYS = [

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/dkimtool.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/dkimtool.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/dkimtool.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -24,9 +24,9 @@
 from twisted.python.usage import Options
 
 from twext.python.log import Logger, LogLevel, StandardIOObserver
-from twext.web2.client.http import ClientRequest
-from twext.web2.http_headers import Headers
-from twext.web2.stream import MemoryStream
+from txweb2.client.http import ClientRequest
+from txweb2.http_headers import Headers
+from txweb2.stream import MemoryStream
 
 from txdav.caldav.datastore.scheduling.ischedule.dkim import RSA256, DKIMRequest, \
     PublicKeyLookup, DKIMVerifier, DKIMVerificationError

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/gateway.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/gateway.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/gateway.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -22,7 +22,7 @@
 import sys
 import xml
 
-from twext.python.plistlib import readPlistFromString, writePlistToString
+from plistlib import readPlistFromString, writePlistToString
 
 from twisted.internet.defer import inlineCallbacks, succeed
 from twistedcaldav.directory.directory import DirectoryError
@@ -32,7 +32,9 @@
     principalForPrincipalID, proxySubprincipal, addProxy, removeProxy,
     ProxyError, ProxyWarning, autoDisableMemcached
 )
-from calendarserver.tools.principals import getProxies, setProxies, updateRecord
+from calendarserver.tools.principals import (
+    getProxies, setProxies, updateRecord, attrMap
+)
 from calendarserver.tools.purge import WorkerService, PurgeOldEventsService, DEFAULT_BATCH_SIZE, DEFAULT_RETAIN_DAYS
 from calendarserver.tools.cmdline import utilityMain
 
@@ -140,26 +142,6 @@
     utilityMain(configFileName, RunnerService, verbose=debug)
 
 
-attrMap = {
-    'GeneratedUID' : { 'attr' : 'guid', },
-    'RealName' : { 'attr' : 'fullName', },
-    'RecordName' : { 'attr' : 'shortNames', },
-    'Comment' : { 'extras' : True, 'attr' : 'comment', },
-    'Description' : { 'extras' : True, 'attr' : 'description', },
-    'Type' : { 'extras' : True, 'attr' : 'type', },
-    'Capacity' : { 'extras' : True, 'attr' : 'capacity', },
-    'Building' : { 'extras' : True, 'attr' : 'building', },
-    'Floor' : { 'extras' : True, 'attr' : 'floor', },
-    'Street' : { 'extras' : True, 'attr' : 'street', },
-    'City' : { 'extras' : True, 'attr' : 'city', },
-    'State' : { 'extras' : True, 'attr' : 'state', },
-    'ZIP' : { 'extras' : True, 'attr' : 'zip', },
-    'Country' : { 'extras' : True, 'attr' : 'country', },
-    'Phone' : { 'extras' : True, 'attr' : 'phone', },
-    'Geo' : { 'extras' : True, 'attr' : 'geo', },
-    'AutoSchedule' : { 'attr' : 'autoSchedule', },
-    'AutoAcceptGroup' : { 'attr' : 'autoAcceptGroup', },
-}
 
 class Runner(object):
 
@@ -218,9 +200,9 @@
             self.respondWithError("Command failed: '%s'" % (str(e),))
             raise
 
+
     # Locations
 
-
     def command_getLocationList(self, command):
         self.respondWithRecordsOfTypes(self.dir, command, ["locations"])
 
@@ -266,6 +248,7 @@
 
     command_getResourceAttributes = command_getLocationAttributes
 
+
     @inlineCallbacks
     def command_setLocationAttributes(self, command):
 
@@ -306,9 +289,9 @@
             return
         self.respondWithRecordsOfTypes(self.dir, command, ["locations"])
 
+
     # Resources
 
-
     def command_getResourceList(self, command):
         self.respondWithRecordsOfTypes(self.dir, command, ["resources"])
 
@@ -379,6 +362,67 @@
         self.respondWithRecordsOfTypes(self.dir, command, ["locations", "resources"])
 
 
+    # Addresses
+
+    def command_getAddressList(self, command):
+        self.respondWithRecordsOfTypes(self.dir, command, ["addresses"])
+
+
+    @inlineCallbacks
+    def command_createAddress(self, command):
+        kwargs = {}
+        for key, info in attrMap.iteritems():
+            if key in command:
+                kwargs[info['attr']] = command[key]
+
+        try:
+            yield updateRecord(True, self.dir, "addresses", **kwargs)
+        except DirectoryError, e:
+            self.respondWithError(str(e))
+            return
+
+        self.respondWithRecordsOfTypes(self.dir, command, ["addresses"])
+
+
+    def command_getAddressAttributes(self, command):
+        guid = command['GeneratedUID']
+        record = self.dir.recordWithGUID(guid)
+        if record is None:
+            self.respondWithError("Principal not found: %s" % (guid,))
+            return
+        recordDict = recordToDict(record)
+        self.respond(command, recordDict)
+        return succeed(None)
+
+
+    @inlineCallbacks
+    def command_setAddressAttributes(self, command):
+        kwargs = {}
+        for key, info in attrMap.iteritems():
+            if key in command:
+                kwargs[info['attr']] = command[key]
+        try:
+            yield updateRecord(False, self.dir, "addresses", **kwargs)
+        except DirectoryError, e:
+            self.respondWithError(str(e))
+            return
+
+        yield self.command_getAddressAttributes(command)
+
+
+    def command_deleteAddress(self, command):
+        kwargs = {}
+        for key, info in attrMap.iteritems():
+            if key in command:
+                kwargs[info['attr']] = command[key]
+        try:
+            self.dir.destroyRecord("addresses", **kwargs)
+        except DirectoryError, e:
+            self.respondWithError(str(e))
+            return
+        self.respondWithRecordsOfTypes(self.dir, command, ["addresses"])
+
+
     # Config
 
     def command_readConfig(self, command):

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/principals.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/principals.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -87,8 +87,14 @@
     print("  --get-auto-schedule-mode: read auto-schedule mode")
     print("  --set-auto-accept-group=principal: set auto-accept-group")
     print("  --get-auto-accept-group: read auto-accept-group")
-    print("  --add {locations|resources} 'full name' [record name] [GUID]: add a principal")
+    print("  --add {locations|resources|addresses} 'full name' [record name] [GUID]: add a principal")
     print("  --remove: remove a principal")
+    print("  --set-geo=url: set the geo: url for an address (e.g. geo:37.331741,-122.030333)")
+    print("  --get-geo: get the geo: url for an address")
+    print("  --set-street-address=streetaddress: set the street address string for an address")
+    print("  --get-street-address: get the street address string for an address")
+    print("  --set-address=guid: associate principal with an address (by guid)")
+    print("  --get-address: get the associated address's guid")
 
     if e:
         sys.exit(64)
@@ -116,8 +122,29 @@
             directory = rootResource.getDirectory()
             yield self.function(rootResource, directory, self.store, *self.params)
 
+attrMap = {
+    'GeneratedUID' : { 'attr' : 'guid', },
+    'RealName' : { 'attr' : 'fullName', },
+    'RecordName' : { 'attr' : 'shortNames', },
+    'AutoSchedule' : { 'attr' : 'autoSchedule', },
+    'AutoAcceptGroup' : { 'attr' : 'autoAcceptGroup', },
 
+    'Comment' : { 'extras' : True, 'attr' : 'comment', },
+    'Description' : { 'extras' : True, 'attr' : 'description', },
+    'Type' : { 'extras' : True, 'attr' : 'type', },
 
+    # For "Locations", i.e. scheduled spaces
+    'Capacity' : { 'extras' : True, 'attr' : 'capacity', },
+    'Floor' : { 'extras' : True, 'attr' : 'floor', },
+    'AssociatedAddress' : { 'extras' : True, 'attr' : 'associatedAddress', },
+
+    # For "Addresses", i.e. nonscheduled areas containing Locations
+    'AbbreviatedName' : { 'extras' : True, 'attr' : 'abbreviatedName', },
+    'StreetAddress' : { 'extras' : True, 'attr' : 'streetAddress', },
+    'Geo' : { 'extras' : True, 'attr' : 'geo', },
+}
+
+
 def main():
     try:
         (optargs, args) = getopt(
@@ -142,6 +169,12 @@
                 "get-auto-schedule-mode",
                 "set-auto-accept-group=",
                 "get-auto-accept-group",
+                "set-geo=",
+                "get-geo",
+                "set-address=",
+                "get-address",
+                "set-street-address=",
+                "get-street-address",
                 "verbose",
             ],
         )
@@ -258,6 +291,24 @@
         elif opt in ("", "--get-auto-accept-group"):
             principalActions.append((action_getAutoAcceptGroup,))
 
+        elif opt in ("", "--set-geo"):
+            principalActions.append((action_setValue, "Geo", arg))
+
+        elif opt in ("", "--get-geo"):
+            principalActions.append((action_getValue, "Geo"))
+
+        elif opt in ("", "--set-street-address"):
+            principalActions.append((action_setValue, "StreetAddress", arg))
+
+        elif opt in ("", "--get-street-address"):
+            principalActions.append((action_getValue, "StreetAddress"))
+
+        elif opt in ("", "--set-address"):
+            principalActions.append((action_setValue, "AssociatedAddress", arg))
+
+        elif opt in ("", "--get-address"):
+            principalActions.append((action_getValue, "AssociatedAddress"))
+
         else:
             raise NotImplementedError(opt)
 
@@ -274,7 +325,7 @@
     elif addType:
 
         try:
-            addType = matchStrings(addType, ["locations", "resources"])
+            addType = matchStrings(addType, ["locations", "resources", "addresses"])
         except ValueError, e:
             print(e)
             return
@@ -296,7 +347,7 @@
     elif listPrincipals:
         try:
             listPrincipals = matchStrings(listPrincipals, ["users", "groups",
-                "locations", "resources"])
+                "locations", "resources", "addresses"])
         except ValueError, e:
             print(e)
             return
@@ -393,6 +444,7 @@
                  "groups" : "Group",
                  "locations" : "Place",
                  "resources" : "Resource",
+                 "addresses" : "Address",
                 }.get(record.recordType),
             ))
             print("   GUID: %s" % (record.guid,))
@@ -667,7 +719,30 @@
         print("No auto-accept-group assigned to %s" % (prettyPrincipal(principal),))
 
 
+ at inlineCallbacks
+def action_setValue(rootResource, directory, store, principal, name, value):
+    print("Setting %s to %s for %s" % (
+        name, value, prettyPrincipal(principal),
+    ))
 
+    principal.record.extras[attrMap[name]["attr"]] = value
+    (yield updateRecord(False, directory,
+        principal.record.recordType,
+        guid=principal.record.guid,
+        shortNames=principal.record.shortNames,
+        fullName=principal.record.fullName,
+        **principal.record.extras
+    ))
+
+
+def action_getValue(rootResource, directory, store, principal, name):
+    print("%s for %s is %s" % (
+        name,
+        prettyPrincipal(principal),
+        principal.record.extras[attrMap[name]["attr"]]
+    ))
+
+
 def abort(msg, status=1):
     sys.stdout.write("%s\n" % (msg,))
     try:

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/gateway/caldavd.plist
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/gateway/caldavd.plist	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/gateway/caldavd.plist	2013-12-19 04:51:29 UTC (rev 12142)
@@ -176,6 +176,7 @@
         <array>
             <string>resources</string>
             <string>locations</string>
+            <string>addresses</string>
         </array>
       </dict>
     </dict>

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_gateway.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_gateway.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_gateway.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -17,7 +17,7 @@
 
 import os
 import sys
-from twext.python.plistlib import readPlistFromString
+from plistlib import readPlistFromString
 import xml
 
 from twext.python.filepath import CachingFilePath as FilePath
@@ -127,15 +127,9 @@
     def test_getLocationAttributes(self):
         yield self.runCommand(command_createLocation)
         results = yield self.runCommand(command_getLocationAttributes)
-        self.assertEquals(results["result"]["Building"], "Test Building")
-        self.assertEquals(results["result"]["City"], "Cupertino")
         self.assertEquals(results["result"]["Capacity"], "40")
         self.assertEquals(results["result"]["Description"], "Test Description")
-        self.assertEquals(results["result"]["ZIP"], "95014")
-        self.assertEquals(results["result"]["Floor"], "First")
         self.assertEquals(results["result"]["RecordName"], ["createdlocation01"])
-        self.assertEquals(results["result"]["State"], "CA")
-        self.assertEquals(results["result"]["Street"], "1 Infinite Loop")
         self.assertEquals(results["result"]["RealName"],
             "Created Location 01 %s %s" % (unichr(208), u"\ud83d\udca3"))
         self.assertEquals(results["result"]["Comment"], "Test Comment")
@@ -162,6 +156,45 @@
 
 
     @inlineCallbacks
+    def test_createAddress(self):
+        directory = getDirectory()
+
+        record = directory.recordWithUID("C701069D-9CA1-4925-A1A9-5CD94767B74B")
+        self.assertEquals(record, None)
+        yield self.runCommand(command_createAddress)
+
+        directory.flushCaches()
+
+        record = directory.recordWithUID("C701069D-9CA1-4925-A1A9-5CD94767B74B")
+        self.assertEquals(record.fullName.decode("utf-8"),
+            "Created Address 01 %s %s" % (unichr(208), u"\ud83d\udca3"))
+
+        self.assertNotEquals(record, None)
+
+        self.assertEquals(record.extras["abbreviatedName"], "Addr1")
+        self.assertEquals(record.extras["streetAddress"], "1 Infinite Loop\nCupertino, 95014\nCA")
+        self.assertEquals(record.extras["geo"], "geo:37.331,-122.030")
+
+        results = yield self.runCommand(command_getAddressList)
+        self.assertEquals(len(results["result"]), 1)
+
+        results = yield self.runCommand(command_getAddressAttributes)
+        self.assertEquals(results["result"]["RealName"], u'Created Address 01 \xd0 \U0001f4a3')
+
+        results = yield self.runCommand(command_setAddressAttributes)
+
+        results = yield self.runCommand(command_getAddressAttributes)
+        self.assertEquals(results["result"]["RealName"], u'Updated Address')
+        self.assertEquals(results["result"]["StreetAddress"], u'Updated Street Address')
+        self.assertEquals(results["result"]["Geo"], u'Updated Geo')
+        
+        results = yield self.runCommand(command_deleteAddress)
+
+        results = yield self.runCommand(command_getAddressList)
+        self.assertEquals(len(results["result"]), 0)
+
+
+    @inlineCallbacks
     def test_createLocation(self):
         directory = getDirectory()
 
@@ -184,16 +217,8 @@
         self.assertEquals(record.autoSchedule, True)
 
         self.assertEquals(record.extras["comment"], "Test Comment")
-        self.assertEquals(record.extras["building"], "Test Building")
         self.assertEquals(record.extras["floor"], "First")
         self.assertEquals(record.extras["capacity"], "40")
-        self.assertEquals(record.extras["street"], "1 Infinite Loop")
-        self.assertEquals(record.extras["city"], "Cupertino")
-        self.assertEquals(record.extras["state"], "CA")
-        self.assertEquals(record.extras["zip"], "95014")
-        self.assertEquals(record.extras["country"], "USA")
-        self.assertEquals(record.extras["phone"], "(408) 555-1212")
-        self.assertEquals(record.extras["geo"], "geo:37.331,-122.030")
 
         results = yield self.runCommand(command_getLocationAttributes)
         self.assertEquals(set(results["result"]["ReadProxies"]), set(['user03', 'user04']))
@@ -216,15 +241,9 @@
         record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
 
         self.assertEquals(record.extras["comment"], "Updated Test Comment")
-        self.assertEquals(record.extras["building"], "Updated Test Building")
         self.assertEquals(record.extras["floor"], "Second")
         self.assertEquals(record.extras["capacity"], "41")
-        self.assertEquals(record.extras["street"], "2 Infinite Loop")
-        self.assertEquals(record.extras["city"], "Updated Cupertino")
-        self.assertEquals(record.extras["state"], "Updated CA")
-        self.assertEquals(record.extras["zip"], "95015")
-        self.assertEquals(record.extras["country"], "Updated USA")
-        self.assertEquals(record.extras["phone"], "(408) 555-1213")
+        self.assertEquals(record.extras["streetAddress"], "2 Infinite Loop\nCupertino, 95014\nCA")
         self.assertEquals(record.autoSchedule, True)
         self.assertEquals(record.autoAcceptGroup, "F5A6142C-4189-4E9E-90B0-9CD0268B314B")
 
@@ -385,6 +404,31 @@
 </plist>
 """
 
+command_createAddress = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>command</key>
+        <string>createAddress</string>
+        <key>GeneratedUID</key>
+        <string>C701069D-9CA1-4925-A1A9-5CD94767B74B</string>
+        <key>RealName</key>
+        <string>Created Address 01 %s %s</string>
+        <key>AbbreviatedName</key>
+        <string>Addr1</string>
+        <key>RecordName</key>
+        <array>
+                <string>createdaddress01</string>
+        </array>
+        <key>StreetAddress</key>
+        <string>1 Infinite Loop\nCupertino, 95014\nCA</string>
+        <key>Geo</key>
+        <string>geo:37.331,-122.030</string>
+</dict>
+</plist>
+""" % (unichr(208), u"\ud83d\udca3")
+
+
 command_createLocation = """<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
@@ -407,26 +451,12 @@
         <string>Test Comment</string>
         <key>Description</key>
         <string>Test Description</string>
-        <key>Building</key>
-        <string>Test Building</string>
         <key>Floor</key>
         <string>First</string>
         <key>Capacity</key>
         <string>40</string>
-        <key>Street</key>
-        <string>1 Infinite Loop</string>
-        <key>City</key>
-        <string>Cupertino</string>
-        <key>State</key>
-        <string>CA</string>
-        <key>ZIP</key>
-        <string>95014</string>
-        <key>Country</key>
-        <string>USA</string>
-        <key>Phone</key>
-        <string>(408) 555-1212</string>
-        <key>Geo</key>
-        <string>geo:37.331,-122.030</string>
+        <key>AssociatedAddress</key>
+        <string>C701069D-9CA1-4925-A1A9-5CD94767B74B</string>
         <key>ReadProxies</key>
         <array>
             <string>users:user03</string>
@@ -454,14 +484,16 @@
         <string>AF575A61-CFA6-49E1-A0F6-B5662C9D9801</string>
         <key>RealName</key>
         <string>Laptop 1</string>
+        <key>Comment</key>
+        <string>Test Comment</string>
+        <key>Description</key>
+        <string>Test Description</string>
         <key>Type</key>
         <string>Computer</string>
         <key>RecordName</key>
         <array>
                 <string>laptop1</string>
         </array>
-        <key>Comment</key>
-        <string>Test Comment</string>
         <key>ReadProxies</key>
         <array>
             <string>users:user03</string>
@@ -500,6 +532,19 @@
 </plist>
 """
 
+
+command_deleteAddress = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>command</key>
+        <string>deleteAddress</string>
+        <key>GeneratedUID</key>
+        <string>C701069D-9CA1-4925-A1A9-5CD94767B74B</string>
+</dict>
+</plist>
+"""
+
 command_getLocationAndResourceList = """<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
@@ -530,6 +575,17 @@
 </plist>
 """
 
+command_getAddressList = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>command</key>
+        <string>getAddressList</string>
+</dict>
+</plist>
+"""
+
+
 command_listReadProxies = """<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
@@ -604,24 +660,12 @@
         <string>Updated Test Comment</string>
         <key>Description</key>
         <string>Updated Test Description</string>
-        <key>Building</key>
-        <string>Updated Test Building</string>
         <key>Floor</key>
         <string>Second</string>
         <key>Capacity</key>
         <string>41</string>
-        <key>Street</key>
-        <string>2 Infinite Loop</string>
-        <key>City</key>
-        <string>Updated Cupertino</string>
-        <key>State</key>
-        <string>Updated CA</string>
-        <key>ZIP</key>
-        <string>95015</string>
-        <key>Country</key>
-        <string>Updated USA</string>
-        <key>Phone</key>
-        <string>(408) 555-1213</string>
+        <key>StreetAddress</key>
+        <string>2 Infinite Loop\nCupertino, 95014\nCA</string>
         <key>ReadProxies</key>
         <array>
             <string>users:user03</string>
@@ -648,6 +692,38 @@
 </plist>
 """
 
+command_getAddressAttributes = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>command</key>
+        <string>getAddressAttributes</string>
+        <key>GeneratedUID</key>
+        <string>C701069D-9CA1-4925-A1A9-5CD94767B74B</string>
+</dict>
+</plist>
+"""
+
+command_setAddressAttributes = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>command</key>
+        <string>setAddressAttributes</string>
+        <key>GeneratedUID</key>
+        <string>C701069D-9CA1-4925-A1A9-5CD94767B74B</string>
+        <key>RealName</key>
+        <string>Updated Address</string>
+        <key>StreetAddress</key>
+        <string>Updated Street Address</string>
+        <key>Geo</key>
+        <string>Updated Geo</string>
+
+</dict>
+</plist>
+"""
+
+
 command_setResourceAttributes = """<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_purge.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_purge.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_purge.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -28,7 +28,7 @@
 from txdav.common.datastore.test.util import populateCalendarsFrom
 from txdav.common.datastore.sql_tables import _BIND_MODE_WRITE
 
-from twext.web2.http_headers import MimeType
+from txweb2.http_headers import MimeType
 
 import os
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_purge_old_events.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_purge_old_events.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/tools/test/test_purge_old_events.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -25,7 +25,7 @@
 from pycalendar.timezone import Timezone
 
 from twext.enterprise.dal.syntax import Update, Delete
-from twext.web2.http_headers import MimeType
+from txweb2.http_headers import MimeType
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webadmin/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webadmin/resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webadmin/resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -36,12 +36,12 @@
 from twistedcaldav.extensions import DAVFile, ReadOnlyResourceMixIn
 
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
-from twext.web2.http import Response
+from txweb2.http import Response
 from twisted.python.modules import getModule
-from twext.web2.http_headers import MimeType
+from txweb2.http_headers import MimeType
 from zope.interface.declarations import implements
-from twext.web2.stream import MemoryStream
-from twext.web2.http import HTTPError
+from txweb2.stream import MemoryStream
+from txweb2.http import HTTPError
 from txdav.xml import element as davxml
 
 from twisted.web.iweb import ITemplateLoader

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webadmin/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webadmin/test/test_resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webadmin/test/test_resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -37,8 +37,8 @@
 from txdav.xml.rfc3744 import GroupMemberSet
 from txdav.xml.rfc2518 import DisplayName
 
-from twext.web2.http import HTTPError
-from twext.web2.responsecode import CONFLICT
+from txweb2.http import HTTPError
+from txweb2.responsecode import CONFLICT
 from txdav.xml.rfc2518 import HRef
 from twistedcaldav.directory.directory import DirectoryRecord
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webcal/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webcal/resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/calendarserver/webcal/resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -28,19 +28,21 @@
 from urlparse import urlparse
 from cgi import parse_qs
 
-from twext.web2 import responsecode
-from twext.web2.http import Response
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import MemoryStream
+from twisted.internet.defer import succeed
+
+from txweb2 import responsecode
+from txweb2.http import Response
+from txweb2.http_headers import MimeType
+from txweb2.stream import MemoryStream
 from txdav.xml import element as davxml
-from twext.web2.dav.resource import TwistedACLInheritable
+from txweb2.dav.resource import TwistedACLInheritable
 
 from twistedcaldav.config import config
 from twistedcaldav.extensions import DAVFile, ReadOnlyResourceMixIn
+from twistedcaldav.timezones import hasTZ
 
-from twisted.internet.defer import succeed
+DEFAULT_TIMEZONE = "America/Los_Angeles"
 
-from twext.python.timezone import getLocalTimezone
 
 
 class WebCalendarResource (ReadOnlyResourceMixIn, DAVFile):
@@ -75,7 +77,7 @@
         return "Web Calendar"
 
     def contentType(self):
-        return MimeType.fromString("text/html; charset=utf-8");
+        return MimeType.fromString("text/html; charset=utf-8")
 
     def contentEncoding(self):
         return None
@@ -95,8 +97,11 @@
         else:
             cacheAttr = "_htmlContent"
             templateFileName = "standalone.html"
-        templateFileName = os.path.join(config.WebCalendarRoot, templateFileName)
 
+        templateFileName = os.path.join(
+            config.WebCalendarRoot, templateFileName
+        )
+
         #
         # See if the file changed, and dump the cached template if so.
         # Don't bother to check if we've checked in the past minute.
@@ -135,14 +140,17 @@
 
         #
         # Get URL of authenticated principal.
-        # Don't need to authenticate here because the ACL will have already required it.
+        # Don't need to authenticate here because the ACL will have already
+        # required it.
         #
-        authenticatedPrincipalURL = str(request.authnUser.childOfType(davxml.HRef))
+        authenticatedPrincipalURL = str(
+            request.authnUser.childOfType(davxml.HRef)
+        )
 
         def queryValue(arg):
             query = parse_qs(urlparse(request.uri).query, True)
             return query.get(arg, [""])[0]
-            
+
         #
         # Parse debug query arg
         #
@@ -180,3 +188,36 @@
                 response.headers.setHeader(header, value)
 
         return response
+
+
+
+try:
+    from Foundation import NSTimeZone
+
+    def lookupSystemTimezone():
+        return NSTimeZone.localTimeZone().name().encode("utf-8")
+
+except ImportError:
+    def lookupSystemTimezone():
+        return ""
+
+
+def getLocalTimezone():
+    """
+    Returns the default timezone for the server.  The order of precedence is:
+    config.DefaultTimezone, lookupSystemTimezone( ), DEFAULT_TIMEZONE.
+    Also, if neither of the first two values in that list are in the timezone
+    database, DEFAULT_TIMEZONE is returned.
+
+    @return: The server's local timezone name
+    @rtype: C{str}
+    """
+    if config.DefaultTimezone:
+        if hasTZ(config.DefaultTimezone):
+            return config.DefaultTimezone
+
+    systemTimezone = lookupSystemTimezone()
+    if hasTZ(systemTimezone):
+        return systemTimezone
+
+    return DEFAULT_TIMEZONE

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/conf/auth/augments-test.xml
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/conf/auth/augments-test.xml	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/conf/auth/augments-test.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -109,6 +109,7 @@
     <enable-addressbook>true</enable-addressbook>
     <enable-login>true</enable-login>
     <auto-schedule>true</auto-schedule>
+    <auto-schedule-mode>default</auto-schedule-mode>
   </record>
   <record>
     <uid>C38BEE7A-36EE-478C-9DCB-CBF4612AFE65</uid>
@@ -136,4 +137,49 @@
     <enable-login>true</enable-login>
     <auto-schedule>true</auto-schedule>
   </record>
+  <record>
+    <uid>6F9EE33B-78F6-481B-9289-3D0812FF0D64</uid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <enable-addressbook>true</enable-addressbook>
+    <enable-login>true</enable-login>
+    <auto-schedule>false</auto-schedule>
+    <auto-schedule-mode>default</auto-schedule-mode>
+  </record>
+  <record>
+    <uid>76E7ECA6-08BC-4AE7-930D-F2E7453993A5</uid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <enable-addressbook>true</enable-addressbook>
+    <enable-login>true</enable-login>
+    <auto-schedule>false</auto-schedule>
+    <auto-schedule-mode>default</auto-schedule-mode>
+  </record>
+  <record>
+    <uid>63A2F949-2D8D-4C8D-B8A5-DCF2A94610F3</uid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <enable-addressbook>true</enable-addressbook>
+    <enable-login>true</enable-login>
+    <auto-schedule>false</auto-schedule>
+    <auto-schedule-mode>default</auto-schedule-mode>
+  </record>
+  <record>
+    <uid>06E3BDCB-9C19-485A-B14E-F146A80ADDC6</uid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <enable-addressbook>true</enable-addressbook>
+    <enable-login>true</enable-login>
+    <auto-schedule>true</auto-schedule>
+    <auto-schedule-mode>default</auto-schedule-mode>
+  </record>
+  <record>
+    <uid>4D66A20A-1437-437D-8069-2F14E8322234</uid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <enable-addressbook>true</enable-addressbook>
+    <enable-login>true</enable-login>
+    <auto-schedule>true</auto-schedule>
+    <auto-schedule-mode>default</auto-schedule-mode>
+  </record>
 </augments>

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/conf/auth/resources-test.xml
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/conf/auth/resources-test.xml	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/conf/auth/resources-test.xml	2013-12-19 04:51:29 UTC (rev 12142)
@@ -1,5 +1,13 @@
 <accounts realm="Test Realm">
   <location>
+    <uid>fantastic</uid>
+    <guid>4D66A20A-1437-437D-8069-2F14E8322234</guid>
+    <name>Fantastic Conference Room</name>
+    <extras>
+      <associatedAddress>63A2F949-2D8D-4C8D-B8A5-DCF2A94610F3</associatedAddress>
+    </extras>
+  </location>
+  <location>
     <uid>jupiter</uid>
     <guid>jupiter</guid>
     <name>Jupiter Conference Room, Building 2, 1st Floor</name>
@@ -78,6 +86,9 @@
     <uid>sharissroom</uid>
     <guid>80689D41-DAF8-4189-909C-DB017B271892</guid>
     <name>Shari's Room</name>
+    <extras>
+      <associatedAddress>6F9EE33B-78F6-481B-9289-3D0812FF0D64</associatedAddress>
+    </extras>
   </location>
   <location>
     <uid>pluto</uid>
@@ -95,6 +106,14 @@
     <name>Room 10</name>
   </location>
   <location>
+    <uid>pretend</uid>
+    <guid>06E3BDCB-9C19-485A-B14E-F146A80ADDC6</guid>
+    <name>Pretend Conference Room</name>
+    <extras>
+      <associatedAddress>76E7ECA6-08BC-4AE7-930D-F2E7453993A5</associatedAddress>
+    </extras>
+  </location>
+  <location>
     <uid>neptune</uid>
     <guid>neptune</guid>
     <name>Neptune Conference Room, Building 2, 1st Floor</name>
@@ -224,4 +243,31 @@
     <guid>resource09</guid>
     <name>Resource 09</name>
   </resource>
+  <address>
+    <uid>testaddress1</uid>
+    <guid>6F9EE33B-78F6-481B-9289-3D0812FF0D64</guid>
+    <name>Test Address One</name>
+    <extras>
+      <streetAddress>20300 Stevens Creek Blvd, Cupertino, CA 95014</streetAddress>
+      <geo>37.322281,-122.028345</geo>
+    </extras>
+  </address>
+  <address>
+    <uid>il2</uid>
+    <guid>63A2F949-2D8D-4C8D-B8A5-DCF2A94610F3</guid>
+    <name>IL2</name>
+    <extras>
+      <streetAddress>2 Infinite Loop, Cupertino, CA 95014</streetAddress>
+      <geo>37.332633,-122.030502</geo>
+    </extras>
+  </address>
+  <address>
+    <uid>il1</uid>
+    <guid>76E7ECA6-08BC-4AE7-930D-F2E7453993A5</guid>
+    <name>IL1</name>
+    <extras>
+      <streetAddress>1 Infinite Loop, Cupertino, CA 95014</streetAddress>
+      <geo>37.331741,-122.030333</geo>
+    </extras>
+  </address>
 </accounts>

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/conf/caldavd-apple.plist
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/conf/caldavd-apple.plist	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/conf/caldavd-apple.plist	2013-12-19 04:51:29 UTC (rev 12142)
@@ -123,6 +123,8 @@
         <string>cluster.pg</string>
         <key>LogFile</key>
         <string>xpg_ctl.log</string>
+        <key>SocketDirectory</key>
+        <string>/var/run/caldavd/PostgresSocket</string>
     </dict>
 
     <!-- Data root -->

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/conf/caldavd-test.plist
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/conf/caldavd-test.plist	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/conf/caldavd-test.plist	2013-12-19 04:51:29 UTC (rev 12142)
@@ -284,29 +284,20 @@
                     <string>mail</string>
                     <string>mailAlias</string>
                 </array>
-                <key>firstName</key>
-                <string></string>
-                <key>lastName</key>
-                <string></string>
             </dict>
           </dict>
           <key>locations</key>
           <dict>
             <key>rdn</key>
             <string>ou=locations</string>
+            <key>associatedAddressAttr</key>
+            <string></string>
             <key>mapping</key>
             <dict>
                 <key>recordName</key>
                 <string>cn</string>
                 <key>fullName</key>
                 <string>cn</string>
-                <key>emailAddresses</key>
-                <array>
-                </array>
-                <key>firstName</key>
-                <string></string>
-                <key>lastName</key>
-                <string></string>
             </dict>
           </dict>
           <key>resources</key>
@@ -319,15 +310,24 @@
                 <string>cn</string>
                 <key>fullName</key>
                 <string>cn</string>
-                <key>emailAddresses</key>
-                <array>
-                </array>
-                <key>firstName</key>
-                <string></string>
-                <key>lastName</key>
-                <string></string>
             </dict>
           </dict>
+          <key>addresses</key>
+          <dict>
+            <key>rdn</key>
+            <string>ou=buildings</string>
+            <key>geoAttr</key>
+            <string></string>
+            <key>streetAddressAttr</key>
+            <string></string>
+            <key>mapping</key>
+            <dict>
+                <key>recordName</key>
+                <string>cn</string>
+                <key>fullName</key>
+                <string>cn</string>
+            </dict>
+          </dict>
         </dict>
         <key>groupSchema</key>
         <dict>
@@ -826,6 +826,10 @@
     <!-- Private Events -->
     <key>EnablePrivateEvents</key>
     <true/>
+    
+    <!-- Private Comment fix off for testing -->
+    <key>RemoveDuplicatePrivateComments</key>
+    <false/>
 
     <!-- Timezone Service -->
     <key>EnableTimezoneService</key>

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/loadtest/sim.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/loadtest/sim.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/loadtest/sim.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -43,6 +43,8 @@
 from twisted.internet.defer import inlineCallbacks
 from twisted.internet.protocol import ProcessProtocol
 
+from twisted.web.server import Site
+
 from contrib.performance.loadtest.ical import OS_X_10_6
 from contrib.performance.loadtest.profiles import Eventer, Inviter, Accepter
 from contrib.performance.loadtest.population import (
@@ -214,7 +216,6 @@
 Arrival = namedtuple('Arrival', 'factory parameters')
 
 
-from twisted.web import server
 
 class LoadSimulator(object):
     """
@@ -461,7 +462,7 @@
         if self.runtime is not None:
             self.reactor.callLater(self.runtime, self.stopAndReport)
         if self.webadminPort:
-            self.reactor.listenTCP(self.webadminPort, server.Site(LoadSimAdminResource(self)))
+            self.reactor.listenTCP(self.webadminPort, Site(LoadSimAdminResource(self)))
         self.reactor.run()
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/invite.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/invite.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/invite.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -17,7 +17,7 @@
 from caldavclientlibrary.protocol.url import URL
 from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
 from pycalendar.datetime import DateTime
-from twext.web2.dav.util import joinURL
+from txweb2.dav.util import joinURL
 from caldavclientlibrary.protocol.webdav.definitions import davxml
 
 ICAL = """BEGIN:VCALENDAR

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/multiget.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/multiget.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/multiget.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -19,7 +19,7 @@
 from caldavclientlibrary.protocol.http.data.string import ResponseDataString
 from caldavclientlibrary.protocol.webdav.definitions import davxml, statuscodes
 from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
-from twext.web2.dav.util import joinURL
+from txweb2.dav.util import joinURL
 
 class MultigetTest(HTTPTestBase):
     """

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/put.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/put.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/put.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -17,7 +17,7 @@
 from caldavclientlibrary.protocol.url import URL
 from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
 from pycalendar.datetime import DateTime
-from twext.web2.dav.util import joinURL
+from txweb2.dav.util import joinURL
 
 ICAL = """BEGIN:VCALENDAR
 CALSCALE:GREGORIAN

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/query.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/query.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/query.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -17,7 +17,7 @@
 from caldavclientlibrary.protocol.url import URL
 from caldavclientlibrary.protocol.webdav.definitions import davxml, statuscodes
 from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
-from twext.web2.dav.util import joinURL
+from txweb2.dav.util import joinURL
 from pycalendar.datetime import DateTime
 from caldavclientlibrary.protocol.caldav.query import QueryVEVENTTimeRange
 from caldavclientlibrary.protocol.http.data.string import ResponseDataString

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/sync.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/sync.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/requests/sync.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -17,7 +17,7 @@
 from caldavclientlibrary.protocol.url import URL
 from caldavclientlibrary.protocol.webdav.definitions import davxml
 from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
-from twext.web2.dav.util import joinURL
+from txweb2.dav.util import joinURL
 from pycalendar.datetime import DateTime
 
 ICAL = """BEGIN:VCALENDAR

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/sqlusage.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/sqlusage.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/sqlusage/sqlusage.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -28,7 +28,7 @@
 from contrib.performance.sqlusage.requests.query import QueryTest
 from contrib.performance.sqlusage.requests.sync import SyncTest
 from pycalendar.datetime import DateTime
-from twext.web2.dav.util import joinURL
+from txweb2.dav.util import joinURL
 import getopt
 import itertools
 import sys

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/stats.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/stats.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/contrib/performance/stats.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,16 +15,19 @@
 ##
 
 from __future__ import print_function
+
 from math import log, sqrt
+from time import mktime
+import random
+import sqlparse
+
 from pycalendar.datetime import DateTime
 from pycalendar.duration import Duration as PyDuration
 from pycalendar.icalendar.property import Property
 from pycalendar.timezone import Timezone
+
+from zope.interface import Interface, implements
 from twisted.python.util import FancyEqMixin
-from zope.interface import Interface, implements
-import random
-import time
-import sqlparse
 
 
 NANO = 1000000000.0
@@ -394,7 +397,7 @@
 
 
     def astimestamp(self, dt):
-        return time.mktime(dt.timetuple())
+        return mktime(dt.timetuple())
 
 
     def _findWorkAfter(self, when):

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/pyflakes
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/pyflakes	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/pyflakes	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,16 +14,13 @@
 fi;
 
 if [ $# -eq 0 ]; then
-  set - calendarserver twext twisted twistedcaldav txdav contrib;
+  set - calendarserver twisted twistedcaldav txdav contrib;
 fi;
 
 tmp="$(mktemp "/tmp/pyflakes.XXXXX")";
 
-cd "${wd}" && "${pyflakes}" "$@" | sed                                    \
-  -e "/'from ctypes import \\*' used; unable to detect undefined names/d" \
-  -e "/redefinition of unused/d"                                          \
-  -e "/^twext\\/backport/d"                                               \
-  -e "/xmlext.py:[0-9][0-9]*: /d"                                         \
+cd "${wd}" && "${pyflakes}" "$@" | sed  \
+  -e "/xmlext.py:[0-9][0-9]*: /d"       \
   | tee "${tmp}";
 
 if [ -s "${tmp}" ]; then error="true"; else error="false"; fi;

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/setup.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/setup.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/setup.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+
 from __future__ import print_function
 
 import sys
@@ -24,18 +25,20 @@
 
 from version import version
 
-def find_modules():
+
+
+def find_packages():
     modules = [
         "twisted.plugins",
     ]
 
+    excludes = [
+        ".svn",
+        "_trial_temp",
+        "build",
+    ]
+
     for root, dirs, files in os.walk("."):
-        excludes = [
-            ".svn",
-            "_trial_temp",
-            "build",
-        ]
-
         if root == ".":
             excludes.append("data")
 
@@ -48,38 +51,41 @@
 
     return modules
 
+
 #
 # Options
 #
 
-description = "CalDAV/CardDAV protocol extensions to twext.web2.dav",
+description = "Calendar and Contacts Server",
 long_description = """
-Extends twisted.web2.dav to implement CalDAV/CardDAV-aware resources and methods.
+Calendar and Contacts Server, implementing the CalDAV and CardDAV protocols.
 """
 
 classifiers = None
 
+
 #
 # Write version file
 #
 
 version_number, version_info = version()
 
-version_string = "{number} ({info})".format(number=version_number, info=version_info)
+version_string = (
+    "{number} ({info})"
+    .format(number=version_number, info=version_info)
+)
 version_file = file(os.path.join("calendarserver", "version.py"), "w")
 version_file.write('version = "{version}"\n'.format(version=version_string))
 version_file.close()
 
+
 #
 # Set up Extension modules that need to be built
 #
 
 from distutils.core import Extension
 
-extensions = [
-    Extension("twext.python.sendmsg",
-              sources=["twext/python/sendmsg.c"])
-]
+extensions = []
 
 if sys.platform == "darwin":
     extensions.append(
@@ -90,11 +96,7 @@
         )
     )
 
-    from twext.python import launchd
-    extensions.append(launchd.ffi.verifier.get_extension())
 
-
-
 #
 # Run setup
 #
@@ -107,58 +109,58 @@
         version=version_string,
         description=description,
         long_description=long_description,
-        url=None,
+        url="http://www.calendarserver.org/",
         classifiers=classifiers,
         author="Apple Inc.",
         author_email=None,
-        license=None,
+        license="Apache License, Version 2.0",
         platforms=["all"],
-        packages=find_modules(),
+        packages=find_packages(),
         package_data={
-                             "twistedcaldav": [
-                               "*.html",
-                               "zoneinfo/*.ics",
-                               "zoneinfo/*/*.ics",
-                               "zoneinfo/*/*/*.ics",
-                               "images/*/*.jpg",
-                             ],
-                             "calendarserver.webadmin": [
-                                 "*.html"
-                             ],
-                             "twistedcaldav.directory": [
-                                 "*.html"
-                             ],
-                             "txdav.common.datastore": [
-                               "sql_schema/*.sql",
-                               "sql_schema/*/*.sql",
-                               "sql_schema/*/*/*.sql",
-                             ],
-                           },
+            "twistedcaldav": [
+                "*.html",
+                "zoneinfo/*.ics",
+                "zoneinfo/*/*.ics",
+                "zoneinfo/*/*/*.ics",
+                "images/*/*.jpg",
+            ],
+            "calendarserver.webadmin": [
+                "*.html"
+            ],
+            "twistedcaldav.directory": [
+                "*.html"
+            ],
+            "txdav.common.datastore": [
+                "sql_schema/*.sql",
+                "sql_schema/*/*.sql",
+                "sql_schema/*/*/*.sql",
+            ],
+        },
         scripts=[
-                             "bin/caldavd",
-                             "bin/calendarserver_backup",
-                             "bin/calendarserver_bootstrap_database",
-                             "bin/calendarserver_command_gateway",
-                             "bin/calendarserver_config",
-                            #"bin/calendarserver_dbinspect",
-                            #"bin/calendarserver_dkimtool",
-                             "bin/calendarserver_export",
-                            #"bin/calendarserver_icalendar_validate",
-                            #"bin/calendarserver_load_augmentdb",
-                            #"bin/calendarserver_manage_postgres",
-                             "bin/calendarserver_manage_principals",
-                             "bin/calendarserver_manage_push",
-                             "bin/calendarserver_manage_timezones",
-                             "bin/calendarserver_migrate_resources",
-                            #"bin/calendarserver_monitor_amp_notifications",
-                            #"bin/calendarserver_monitor_notifications",
-                             "bin/calendarserver_purge_attachments",
-                             "bin/calendarserver_purge_events",
-                             "bin/calendarserver_purge_principals",
-                             "bin/calendarserver_shell",
-                             "bin/calendarserver_upgrade",
-                            #"bin/calendarserver_verify_data",
-                           ],
+            "bin/caldavd",
+            "bin/calendarserver_backup",
+            "bin/calendarserver_bootstrap_database",
+            "bin/calendarserver_command_gateway",
+            "bin/calendarserver_config",
+            # "bin/calendarserver_dbinspect",
+            # "bin/calendarserver_dkimtool",
+            "bin/calendarserver_export",
+            # "bin/calendarserver_icalendar_validate",
+            # "bin/calendarserver_load_augmentdb",
+            # "bin/calendarserver_manage_postgres",
+            "bin/calendarserver_manage_principals",
+            "bin/calendarserver_manage_push",
+            "bin/calendarserver_manage_timezones",
+            "bin/calendarserver_migrate_resources",
+            # "bin/calendarserver_monitor_amp_notifications",
+            # "bin/calendarserver_monitor_notifications",
+            "bin/calendarserver_purge_attachments",
+            "bin/calendarserver_purge_events",
+            "bin/calendarserver_purge_principals",
+            "bin/calendarserver_shell",
+            "bin/calendarserver_upgrade",
+            # "bin/calendarserver_verify_data",
+        ],
         data_files=[("caldavd", ["conf/caldavd.plist"]), ],
         ext_modules=extensions,
         py_modules=[],
@@ -177,7 +179,9 @@
             install_lib = install_lib[len(root):]
 
         for script in dist.scripts:
-            scriptPath = os.path.join(install_scripts, os.path.basename(script))
+            scriptPath = os.path.join(
+                install_scripts, os.path.basename(script)
+            )
 
             print("rewriting {0}".format(scriptPath))
 
@@ -196,17 +200,29 @@
                 line = line.rstrip("\n")
                 if fileType == "sh":
                     if line == "#PYTHONPATH":
-                        script.append('PYTHONPATH="{add}:$PYTHONPATH"'.format(add=install_lib))
+                        script.append(
+                            'PYTHONPATH="{add}:$PYTHONPATH"'
+                            .format(add=install_lib)
+                        )
                     elif line == "#PATH":
-                        script.append('PATH="{add}:$PATH"'.format(add=os.path.join(base, "usr", "bin")))
+                        script.append(
+                            'PATH="{add}:$PATH"'
+                            .format(add=os.path.join(base, "usr", "bin"))
+                        )
                     else:
                         script.append(line)
 
                 elif fileType == "python":
                     if line == "#PYTHONPATH":
-                        script.append('PYTHONPATH="{path}"'.format(path=install_lib))
+                        script.append(
+                            'PYTHONPATH="{path}"'
+                            .format(path=install_lib)
+                        )
                     elif line == "#PATH":
-                        script.append('PATH="{path}"'.format(path=os.path.join(base, "usr", "bin")))
+                        script.append(
+                            'PATH="{path}"'
+                            .format(path=os.path.join(base, "usr", "bin"))
+                        )
                     else:
                         script.append(line)
 
@@ -218,6 +234,5 @@
             newScript.close()
 
 
-
 if __name__ == "__main__":
     doSetup()

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/support/build.sh
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/support/build.sh	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/support/build.sh	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,6 +16,9 @@
 # limitations under the License.
 ##
 
+set -e
+set -u
+
 . "${wd}/support/py.sh";
 
 echo_header () {
@@ -51,55 +54,33 @@
 #   Assert that ldap.h is present with a version >= 20344
 #     find_header "ldap.h" 20344 "LDAP_VENDOR_VERSION"
 find_header () {
-  ARGS="$@";
-  ret=1;  # default to a failed check, forcing a fetch of the depencency
-  i=0;
-  for a in $ARGS; do
-    [ $i -eq 0 ] && local sysheader="$1";
-    [ $i -eq 1 ] && local minver="$2";
-    [ $i -eq 2 ] && local def="$3";
-    i=$(($i+1));
-  done;
-  [ ! $sysheader ] && return 1;
+  sys_header="$1"; shift;
+  if [ $# -ge 1 ]; then
+        min_version="$1"; shift;
+      version_macro="$1"; shift;
+  fi;
+
+  # No min_version given:
   # Check for presence of a header. We use the "-c" cc option because we don't
   # need to emit a file; cc exits nonzero if it can't find the header
-  if [ $# -lt 2 ]; then
-    echo "#include <${sysheader}>" | cc -x c -c - -o /dev/null 2> /dev/null;
+  if [ -z "${min_version:-}" ]; then
+    echo "#include <${sys_header}>" | cc -x c -c - -o /dev/null 2> /dev/null;
     return "$?";
+  fi;
+
   # Check for presence of a header of specified version
+  found_version="$(printf "#include <${sys_header}>\n${version_macro}\n" | cc -x c -E - | tail -1)";
+
+  if [ "${found_version}" == "${version_macro}" ]; then
+    # Macro was not replaced
+    return 1;
+  fi;
+
+  if cmp_version "${min_version}" "${found_version}"; then
+    return 0;
   else
-    found='';
-    local aout=$(mktemp -t ccXXXXXX); # compiled executable file path
-    local prog=$(mktemp -t ccXXXXXX); # C source file path
-    cat <<DOC > ${prog}
-#include <${sysheader}>
-#include <stdio.h>
-#define STR(x)   #x
-#define SHOW_DEFINE(x) printf("%s", STR(x))
-int main()
-{
-    if (${def})
-    {
-        SHOW_DEFINE(${def});
-        return 0;
-    };
     return 1;
-};
-DOC
-    cc -x c -o ${aout} ${prog} &> /dev/null;
-    if [ $? -eq 0 ] && [ -e ${aout} ] ; then
-      found=$(${aout});
-    fi;
-    if [ $? -eq 0 ] && [ ! -z ${found} ] ; then
-      cmp_version $minver $found;
-      ret=$?;
-    else
-      ret=1;   #cc exited nonzero or didn't emit a file
-    fi;
-    rm -f "${aout}";
-    rm -f "${prog}";
   fi;
-  return $ret;
 };
 
 # Initialize all the global state required to use this library.
@@ -528,9 +509,7 @@
                           # already has it?
   local  inplace="";      # Do development in-place; don't run setup.py to
                           # build, and instead add the source directory plus the
-                          # given relative path directly to sys.path.  twisted
-                          # and pycalendar are developed often enough that this is
-                          # convenient.
+                          # given relative path directly to sys.path.
   local skip_egg="false"; # Skip even the 'egg_info' step, because nothing needs
                           # to be built.
   local revision="0";     # Revision (if svn)
@@ -730,13 +709,14 @@
     using_system "memcached";
   else
     local le="libevent-2.0.21-stable";
-    local mc="memcached-1.4.15";
+    local mc="memcached-1.4.16";
     c_dependency -m "b2405cc9ebf264aa47ff615d9de527a2" \
       "libevent" "${le}" \
       "http://github.com/downloads/libevent/libevent/${le}.tar.gz";
-    c_dependency -m "36ea966f5a29655be1746bf4949f7f69" \
+    c_dependency -m "1c5781fecb52d70b615c6d0c9c140c9c" \
       "memcached" "${mc}" \
-      "http://memcached.googlecode.com/files/${mc}.tar.gz";
+      "http://www.memcached.org/files/${mc}.tar.gz";
+    # "http://memcached.googlecode.com/files/${mc}.tar.gz";
   fi;
 
   if type -P postgres > /dev/null; then
@@ -796,6 +776,20 @@
     "setuptools" "setuptools" "${st}" \
     "$pypi/s/setuptools/${st}.tar.gz";
 
+  local v="0.6";
+  local n="cffi";
+  local p="${n}-${v}";
+  py_dependency -v "0.6" -m "5be33b1ab0247a984d42b27344519337" \
+    "${n}" "${n}" "${p}" \
+    "${pypi}/c/${n}/${p}.tar.gz";
+
+  local v="2.10";
+  local n="pycparser";
+  local p="${n}-${v}";
+  py_dependency -v "0.6" -m "d87aed98c8a9f386aa56d365fe4d515f" \
+    "${n}" "${n}" "${p}" \
+    "${pypi}/p/${n}/${p}.tar.gz";
+
   local v="4.0.5";
   local n="zope.interface";
   local p="${n}-${v}";
@@ -812,8 +806,10 @@
 
   local n="PyKerberos";
   if type -P krb5-config > /dev/null; then
-    py_dependency -r 9409 \
-      "${n}" "kerberos" "${n}" \
+    local v="9409";
+    local p="${n}-${v}";
+    py_dependency -r "${v}" \
+      "${n}" "kerberos" "${p}" \
       "${svn_uri_base}/${n}/trunk";
   fi;
 
@@ -840,8 +836,27 @@
     "${n}" "pgdb" "${p}" \
     "${pypi}/P/${n}/${p}.tgz";
 
-  # Maintenance note: next time the Twisted dependency gets updated, check out
-  # twext/patches.py.
+  local v="0.1.2";
+  local n="sqlparse";
+  local p="${n}-${v}";
+  py_dependency -v "${v}" -s "978874e5ebbd78e6d419e8182ce4fb3c30379642" \
+    "SQLParse" "${n}" "${p}" \
+    "http://python-sqlparse.googlecode.com/files/${p}.tar.gz";
+
+  local v="2.6.1";
+  local n="pycrypto";
+  local p="${n}-${v}";
+  py_dependency -v "${v}" -m "55a61a054aa66812daf5161a0d5d7eda" \
+    "PyCrypto" "${n}" "${p}" \
+    "http://ftp.dlitz.net/pub/dlitz/crypto/${n}/${p}.tar.gz";
+
+  local v="0.1.7";
+  local n="pyasn1";
+  local p="${n}-${v}";
+  py_dependency -v "${v}" -m "2cbd80fcd4c7b1c82180d3d76fee18c8" \
+    "${n}" "${n}" "${p}" \
+    "${pypi}/p/${n}/${p}.tar.gz";
+
   local v="13.2.0";
   local n="Twisted";
   local p="${n}-${v}";
@@ -849,6 +864,13 @@
     "${n}" "twisted" "${p}" \
     "${pypi}/T/${n}/${p}.tar.bz2";
 
+  local v="12094";
+  local n="twext";
+  local p="${n}-${v}";
+  py_dependency -fe -r "${v}" \
+    "${n}" "${n}" "${p}" \
+    "${svn_uri_base}/${n}/trunk";
+
   local v="1.5";
   local n="python-dateutil";
   local p="${n}-${v}";
@@ -870,23 +892,26 @@
     "Python-LDAP" "ldap" "${p}" \
     "${pypi}/p/${n}/${p}.tar.gz";
 
-  # XXX actually PyCalendar should be imported in-place.
-  py_dependency -fe -i "src" -r 11947 \
-    "PyCalendar" "pycalendar" "pycalendar" \
-    "${svn_uri_base}/PyCalendar/trunk";
+  local v="11947";
+  local n="PyCalendar";
+  local p="${n}-${v}";
+  py_dependency -fe -i "src" -r "${v}" \
+    "${n}" "pycalendar" "${p}" \
+    "${svn_uri_base}/${n}/trunk";
 
+  # Can't add "-v 2011g" to args because the version check expects numbers.
+  local v="2013.8";
+  local n="pytz";
+  local p="${n}-${v}";
+  py_dependency -m "37750ca749ed3a52523b9682b0b7e381" \
+    "${n}" "${n}" "${p}" \
+    "${pypi}/p/${n}/${p}.tar.gz";
+
   #
   # Tool dependencies.  The code itself doesn't depend on these, but
   # they are useful to developers.
   #
 
-  local v="0.1.2";
-  local n="sqlparse";
-  local p="${n}-${v}";
-  py_dependency -v "${v}" -s "978874e5ebbd78e6d419e8182ce4fb3c30379642" \
-    "SQLParse" "${n}" "${p}" \
-    "http://python-sqlparse.googlecode.com/files/${p}.tar.gz";
-
   if type -P pyflakes > /dev/null; then
     using_system "PyFlakes";
   else
@@ -898,32 +923,13 @@
       "${pypi}/p/${n}/${p}.tar.gz";
   fi;
  
-  py_dependency -o -r HEAD \
-    "CalDAVClientLibrary" "caldavclientlibrary" "CalDAVClientLibrary" \
-    "${svn_uri_base}/CalDAVClientLibrary/trunk";
-
-  # Can't add "-v 2011g" to args because the version check expects numbers.
-  local v="2013.8";
-  local n="pytz";
+  local v="12068";
+  local n="CalDAVClientLibrary";
   local p="${n}-${v}";
-  py_dependency -m "37750ca749ed3a52523b9682b0b7e381" \
-    "${n}" "${n}" "${p}" \
-    "${pypi}/p/${n}/${p}.tar.gz";
+  py_dependency -o -r "${v}" \
+    "${n}" "caldavclientlibrary" "${p}" \
+    "${svn_uri_base}/${n}/trunk";
 
-  local v="2.6.1";
-  local n="pycrypto";
-  local p="${n}-${v}";
-  py_dependency -v "${v}" -m "55a61a054aa66812daf5161a0d5d7eda" \
-    "PyCrypto" "${n}" "${p}" \
-    "http://ftp.dlitz.net/pub/dlitz/crypto/${n}/${p}.tar.gz";
-
-  local v="0.1.7";
-  local n="pyasn1";
-  local p="${n}-${v}";
-  py_dependency -v "${v}" -m "2cbd80fcd4c7b1c82180d3d76fee18c8" \
-    "${n}" "${n}" "${p}" \
-    "${pypi}/p/${n}/${p}.tar.gz";
-
   local v="1.1.8";
   local n="setproctitle";
   local p="${n}-${v}";
@@ -931,20 +937,6 @@
     "${n}" "${n}" "${p}" \
     "${pypi}/s/${n}/${p}.tar.gz";
 
-  local v="0.8";
-  local n="cffi";
-  local p="${n}-${v}";
-  py_dependency -v "0.6" -m "e61deb0515311bb42d5d58b9403bc923" \
-    "${n}" "${n}" "${p}" \
-    "${pypi}/c/${n}/${p}.tar.gz";
-
-  local v="2.10";
-  local n="pycparser";
-  local p="${n}-${v}";
-  py_dependency -v "0.6" -m "d87aed98c8a9f386aa56d365fe4d515f" \
-    "${n}" "${n}" "${p}" \
-    "${pypi}/p/${n}/${p}.tar.gz";
-
   svn_get "CalDAVTester" "${top}/CalDAVTester" \
       "${svn_uri_base}/CalDAVTester/trunk" HEAD;
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/support/py.sh
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/support/py.sh	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/support/py.sh	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,6 +15,9 @@
 # limitations under the License.
 ##
 
+set -e
+set -u
+
 # Echo the major.minor version of the given Python interpreter.
 
 py_version () {

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/test
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/test	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/test	2013-12-19 04:51:29 UTC (rev 12142)
@@ -21,7 +21,9 @@
 
 wd="$(cd "$(dirname "$0")" && pwd -L)";
 
-#. "${wd}/support/build.sh";
+##
+# Options
+##
 
 do_setup="false";
 do_get="false";
@@ -78,15 +80,30 @@
   test_modules="$@";
   flaky=true;
 else
-  test_modules="calendarserver twistedcaldav twext txdav contrib ${m_twisted}";
+  test_modules="calendarserver twistedcaldav txdav contrib ${m_twisted}";
   flaky=true;
 fi;
 
+
+##
+# Clean up
+##
+
 find "${wd}" -name \*.pyc -print0 | xargs -0 rm;
 
+
+##
+# Unit tests
+##
+
 mkdir -p "${wd}/data";
 cd "${wd}" && "${wd}/bin/trial" --temp-directory="${wd}/data/trial" --rterrors ${reactor} ${random} ${until_fail} ${no_colour} ${coverage} ${numjobs} ${test_modules};
 
+
+##
+# Code linting
+##
+
 if ${flaky}; then
   echo "";
   echo "Running pyflakes...";
@@ -110,7 +127,7 @@
 
 #tmp="$(mktemp "/tmp/calendarserver_test_flakish.XXXXX")";
 #echo "";
-#echo "Checking for other issues..."
+#echo "Checking for legacy print statements..."
 #search_py 'print  *[^(]' | sed 's|#.*||' | grep 'print  *[^(]' > "${tmp}" || true;
 #if [ -s "${tmp}" ]; then
 #    echo "**** Use of legacy print statement found. ****";
@@ -119,6 +136,11 @@
 #fi;
 #rm -f "${tmp}";
 
+
+##
+# Empty files
+##
+
 tmp="$(mktemp "/tmp/calendarserver_test_emtpy.XXXXX")";
 find "${wd}" '!' '(' -type d '(' -path '*/.*' -or -name data ')' -prune ')' -type f -size 0 > "${tmp}";
 if [ -s "${tmp}" ]; then

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/caldav.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/caldav.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/caldav.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,8 +14,6 @@
 # limitations under the License.
 ##
 
-__import__("twext") # install patches before doing anything
-
 from zope.interface import implements
 from twisted.plugin import IPlugin
 from twisted.application.service import IServiceMaker

Deleted: CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/kqueuereactor.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/kqueuereactor.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/kqueuereactor.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -1,23 +0,0 @@
-##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-__import__("twext")
-
-from twisted.application.reactors import Reactor
-
-caldav_kqueue = Reactor(
-    'caldav_kqueue', 'twext.internet.kqreactor',
-    'kqueue(2)-based reactor.')

Deleted: CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/masterchild.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/masterchild.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twisted/plugins/masterchild.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -1,58 +0,0 @@
-##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from zope.interface import implementer
-
-from twisted.python.reflect import namedClass
-from twisted.plugin import IPlugin
-from twisted.application.service import IServiceMaker
-
-from twext.application.masterchild import MasterOptions, ChildOptions
-
-
- at implementer(IPlugin, IServiceMaker)
-class ServiceMaker(object):
-    def __init__(self, name, description, options, serviceMakerClass):
-        self.tapname = name
-        self.description = description
-        self.options = options
-        self.serviceMakerClass = serviceMakerClass
-        self._serviceMaker = None
-
-
-    def makeService(self, options):
-        if self._serviceMaker is None:
-            self._serviceMaker = namedClass(self.serviceMakerClass)()
-
-        return self._serviceMaker.makeService(options)
-
-
-
-masterServiceMaker = ServiceMaker(
-    "master",
-    "Master process application container",
-    MasterOptions,
-    "twext.application.masterchild.MasterServiceMaker"
-)
-
-
-
-childServiceMaker = ServiceMaker(
-    "child",
-    "Child process application container",
-    ChildOptions,
-    "twext.application.masterchild.ChildServiceMaker"
-)

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/__init__.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/__init__.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -21,15 +21,11 @@
 See RFC 4791.
 """
 
-# Make sure we have twext's required Twisted patches loaded before we do
-# anything at all.
-__import__("twext")
-
 #
 # Load in suitable file extension/content-type map from OS X
 #
 
-from twext.web2.static import File, loadMimeTypes
+from txweb2.static import File, loadMimeTypes
 
 File.contentTypes = loadMimeTypes(("/etc/apache2/mime.types", "/etc/httpd/mime.types",))
 
@@ -49,7 +45,7 @@
 # DefaultHTTPHandler
 #
 
-from twext.web2.http_headers import DefaultHTTPHandler, last, singleHeader
+from txweb2.http_headers import DefaultHTTPHandler, last, singleHeader
 
 DefaultHTTPHandler.updateParsers({
     "If-Schedule-Tag-Match": (last, str),

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/authkerb.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/authkerb.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/authkerb.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -42,9 +42,9 @@
 
 from twisted.cred import checkers, credentials, error
 from twisted.internet.defer import succeed
-from twext.web2 import responsecode
-from twext.web2.auth.interfaces import ICredentialFactory
-from twext.web2.dav.auth import IPrincipalCredentials
+from txweb2 import responsecode
+from txweb2.auth.interfaces import ICredentialFactory
+from txweb2.dav.auth import IPrincipalCredentials
 
 from twext.python.log import Logger
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/backup.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/backup.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/backup.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -24,7 +24,7 @@
 import fnmatch
 import commands
 
-from twext.python.plistlib import readPlist
+from plistlib import readPlist
 
 VERBOSE = os.environ.get('VERBOSE', False)
 FUNCLOG = os.environ.get('FUNCLOG', False)

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/bind.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/bind.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/bind.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -19,16 +19,16 @@
 Have to have this in a separate module for now.
 """
 
-from twext.web2.dav.util import bindMethods
+from txweb2.dav.util import bindMethods
 
 ##
 # Attach methods
 ##
 
 def doBind():
-    import twext.web2.dav.method
-    from twext.web2.dav.resource import DAVResource
-    bindMethods(twext.web2.dav.method, DAVResource)
+    import txweb2.dav.method
+    from txweb2.dav.resource import DAVResource
+    bindMethods(txweb2.dav.method, DAVResource)
 
     import twistedcaldav.method
     from twistedcaldav.resource import CalDAVResource

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/cache.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/cache.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/cache.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,10 +15,10 @@
 ##
 
 from twext.python.log import Logger
-from twext.web2.dav.util import allDataFromStream
-from twext.web2.http import Response
-from twext.web2.iweb import IResource
-from twext.web2.stream import MemoryStream
+from txweb2.dav.util import allDataFromStream
+from txweb2.http import Response
+from txweb2.iweb import IResource
+from txweb2.stream import MemoryStream
 
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/__init__.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/__init__.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,7 +14,7 @@
 # limitations under the License.
 ##
 
-from twext.web2.http_headers import DefaultHTTPHandler, tokenize, generateList, singleHeader
+from txweb2.http_headers import DefaultHTTPHandler, tokenize, generateList, singleHeader
 
 DefaultHTTPHandler.updateParsers({
     "x-forwarded-for": (tokenize, list),

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/pool.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/pool.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/pool.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -33,11 +33,11 @@
 from twisted.internet.error import ConnectionLost, ConnectionDone, ConnectError
 from twisted.internet.protocol import ClientFactory
 
-from twext.web2 import responsecode
-from twext.web2.client.http import HTTPClientProtocol
-from twext.web2.http import StatusResponse, HTTPError
-from twext.web2.dav.util import allDataFromStream
-from twext.web2.stream import MemoryStream
+from txweb2 import responsecode
+from txweb2.client.http import HTTPClientProtocol
+from txweb2.http import StatusResponse, HTTPError
+from txweb2.dav.util import allDataFromStream
+from txweb2.stream import MemoryStream
 
 class PooledHTTPClientFactory(ClientFactory):
     """

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/reverseproxy.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/reverseproxy.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/reverseproxy.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -20,10 +20,10 @@
 
 from zope.interface.declarations import implements
 
-from twext.web2 import iweb, responsecode
-from twext.web2.client.http import ClientRequest
-from twext.web2.http import StatusResponse, HTTPError
-from twext.web2.resource import LeafResource
+from txweb2 import iweb, responsecode
+from txweb2.client.http import ClientRequest
+from txweb2.http import StatusResponse, HTTPError
+from txweb2.resource import LeafResource
 
 from twext.python.log import Logger
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/test/test_reverseproxy.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/test/test_reverseproxy.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/client/test/test_reverseproxy.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,9 +14,9 @@
 # limitations under the License.
 ##
 
-from twext.web2.client.http import ClientRequest
-from twext.web2.http import HTTPError
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.client.http import ClientRequest
+from txweb2.http import HTTPError
+from txweb2.test.test_server import SimpleRequest
 from twistedcaldav.client.pool import _clientPools
 from twistedcaldav.client.reverseproxy import ReverseProxyResource
 from twistedcaldav.config import config

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/peruserdata.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/peruserdata.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/peruserdata.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -67,7 +67,7 @@
 
     # X- properties that are ignored - by default all X- properties are treated as per-user except for the
     # ones listed here
-    IGNORE_X_PROPERTIES = (Component.HIDDEN_INSTANCE_PROPERTY,)
+    IGNORE_X_PROPERTIES = [Component.HIDDEN_INSTANCE_PROPERTY]
 
     def __init__(self, uid):
         """

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/privateevents.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/privateevents.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/privateevents.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,8 +14,8 @@
 # limitations under the License.
 ##
 
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2 import responsecode
+from txweb2.http import HTTPError, StatusResponse
 from twistedcaldav.caldavxml import Property, CalendarData, CalendarComponent, \
     AllProperties, AllComponents
 from twistedcaldav.datafilters.calendardata import CalendarDataFilter

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/test/test_privateevents.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/test/test_privateevents.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/datafilters/test/test_privateevents.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,7 +14,7 @@
 # limitations under the License.
 ##
 
-from twext.web2.http import HTTPError
+from txweb2.http import HTTPError
 import twistedcaldav.test.util
 from twistedcaldav.datafilters.privateevents import PrivateEventFilter
 from twistedcaldav.ical import Component

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/addressbook.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/addressbook.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/addressbook.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -26,10 +26,10 @@
 ]
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.dav.util import joinURL
-from twext.web2.http import HTTPError
-from twext.web2.http_headers import ETag, MimeType
+from txweb2 import responsecode
+from txweb2.dav.util import joinURL
+from txweb2.http import HTTPError
+from txweb2.http_headers import ETag, MimeType
 
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/appleopendirectory.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/appleopendirectory.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -30,7 +30,7 @@
 
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue
 from twisted.cred.credentials import UsernamePassword
-from twext.web2.auth.digest import DigestedCredentials
+from txweb2.auth.digest import DigestedCredentials
 from twext.python.log import Logger
 
 from twistedcaldav.directory.cachingdirectory import CachingDirectoryService, \

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/augment.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/augment.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/augment.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -79,6 +79,7 @@
     "groups" : "Group",
     "locations" : "Location",
     "resources" : "Resource",
+    "addresses" : "Address",
 }
 
 class AugmentDB(object):

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/cachingdirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/cachingdirectory.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/cachingdirectory.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -31,9 +31,9 @@
 import base64
 
 from twext.python.log import Logger
-from twext.python.memcacheclient import ClientFactory, MemcacheError
 
 from twistedcaldav.config import config
+from twistedcaldav.memcacheclient import ClientFactory, MemcacheError
 from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord, DirectoryError, UnknownRecordTypeError
 from txdav.caldav.datastore.scheduling.cuaddress import normalizeCUAddr
 from twistedcaldav.directory.util import normalizeUUID

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/calendar.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/calendar.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -27,10 +27,10 @@
 ]
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.dav.util import joinURL
-from twext.web2.http import HTTPError
-from twext.web2.http_headers import ETag, MimeType
+from txweb2 import responsecode
+from txweb2.dav.util import joinURL
+from txweb2.http import HTTPError
+from txweb2.http_headers import ETag, MimeType
 
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/calendaruserproxy.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/calendaruserproxy.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -31,12 +31,12 @@
 import time
 
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2 import responsecode
+from txweb2.http import HTTPError, StatusResponse
 from txdav.xml import element as davxml
 from txdav.xml.base import dav_namespace
-from twext.web2.dav.util import joinURL
-from twext.web2.dav.noneprops import NonePropertyStore
+from txweb2.dav.util import joinURL
+from txweb2.dav.noneprops import NonePropertyStore
 
 from twext.python.log import Logger
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/common.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/common.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/common.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,9 +16,9 @@
 ##
 
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twext.web2.http import HTTPError
-from twext.web2 import responsecode
-from twext.web2.dav.util import joinURL
+from txweb2.http import HTTPError
+from txweb2 import responsecode
+from txweb2.dav.util import joinURL
 from twistedcaldav.directory.util import transactionFromRequest, NotFoundResource
 from twistedcaldav.directory.resource import DirectoryReverseProxyResource
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/digest.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/digest.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/digest.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -17,12 +17,12 @@
 
 from twisted.cred import error
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twext.web2.auth.digest import DigestCredentialFactory
-from twext.web2.auth.digest import DigestedCredentials
-from twext.web2.http_headers import Token
-from twext.web2.http_headers import parseKeyValue
-from twext.web2.http_headers import split
-from twext.web2.http_headers import tokenize
+from txweb2.auth.digest import DigestCredentialFactory
+from txweb2.auth.digest import DigestedCredentials
+from txweb2.http_headers import Token
+from txweb2.http_headers import parseKeyValue
+from txweb2.http_headers import split
+from txweb2.http_headers import tokenize
 
 from twext.python.log import Logger
 
@@ -35,7 +35,7 @@
 log = Logger()
 
 """
-Overrides twext.web2.auth.digest to allow specifying a qop value as a configuration parameter.
+Overrides txweb2.auth.digest to allow specifying a qop value as a configuration parameter.
 Also adds an sqlite-based credentials cache that is multi-process safe.
 
 """
@@ -121,7 +121,7 @@
 
 class QopDigestCredentialFactory(DigestCredentialFactory):
     """
-    See twext.web2.auth.digest.DigestCredentialFactory
+    See txweb2.auth.digest.DigestCredentialFactory
     """
 
     def __init__(self, algorithm, qop, realm, namespace="DIGESTCREDENTIALS"):
@@ -196,7 +196,7 @@
         @type response: C{str}
         @param response: A string of comma seperated key=value pairs
 
-        @type request: L{twext.web2.server.Request}
+        @type request: L{txweb2.server.Request}
         @param request: the request being processed
 
         @return: L{DigestedCredentials}
@@ -253,7 +253,7 @@
         @param auth:        the response parameters.
         @type auth:         C{dict}
         @param request:     the request being processed.
-        @type request:      L{twext.web2.server.Request}
+        @type request:      L{txweb2.server.Request}
 
         @return:            C{True} if validated.
         @raise LoginFailed: if validation fails.

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/directory.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/directory.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -35,8 +35,8 @@
 from twext.enterprise.dal.syntax import Delete
 from twext.enterprise.queue import WorkItem, PeerConnectionPool
 from twext.python.log import Logger
-from twext.web2.dav.auth import IPrincipalCredentials
-from twext.web2.dav.util import joinURL
+from txweb2.dav.auth import IPrincipalCredentials
+from txweb2.dav.util import joinURL
 
 from twisted.cred.checkers import ICredentialsChecker
 from twisted.cred.error import UnauthorizedLogin
@@ -86,6 +86,7 @@
     recordType_groups = "groups"
     recordType_locations = "locations"
     recordType_resources = "resources"
+    recordType_addresses = "addresses"
 
     searchContext_location = "location"
     searchContext_resource = "resource"

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/internal.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/internal.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/internal.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -23,7 +23,7 @@
     "InternalDirectoryService",
 ]
 
-from twext.web2.dav.auth import IPrincipalCredentials
+from txweb2.dav.auth import IPrincipalCredentials
 
 from twisted.cred.error import UnauthorizedLogin
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/ldapdirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/ldapdirectory.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/ldapdirectory.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -60,8 +60,8 @@
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue
 from twisted.internet.threads import deferToThread
 from twext.python.log import Logger
-from twext.web2.http import HTTPError, StatusResponse
-from twext.web2 import responsecode
+from txweb2.http import HTTPError, StatusResponse
+from txweb2 import responsecode
 
 class LdapDirectoryService(CachingDirectoryService):
     """
@@ -113,8 +113,6 @@
                 "guidAttr": "entryUUID",
                 "users": {
                     "rdn": "ou=People",
-                    "attr": "uid", # used only to synthesize email address
-                    "emailSuffix": None, # used only to synthesize email address
                     "filter": None, # additional filter for this type
                     "loginEnabledAttr" : "", # attribute controlling login
                     "loginEnabledValue" : "yes", # "True" value of above attribute
@@ -130,8 +128,6 @@
                 },
                 "groups": {
                     "rdn": "ou=Group",
-                    "attr": "cn", # used only to synthesize email address
-                    "emailSuffix": None, # used only to synthesize email address
                     "filter": None, # additional filter for this type
                     "mapping" : { # maps internal record names to LDAP
                         "recordName": "cn",
@@ -143,23 +139,18 @@
                 },
                 "locations": {
                     "rdn": "ou=Places",
-                    "attr": "cn", # used only to synthesize email address
-                    "emailSuffix": None, # used only to synthesize email address
                     "filter": None, # additional filter for this type
                     "calendarEnabledAttr" : "", # attribute controlling enabledForCalendaring
                     "calendarEnabledValue" : "yes", # "True" value of above attribute
+                    "associatedAddressAttr" : "",
                     "mapping" : { # maps internal record names to LDAP
                         "recordName": "cn",
                         "fullName" : "cn",
                         "emailAddresses" : ["mail"], # multiple LDAP fields supported
-                        "firstName" : "givenName",
-                        "lastName" : "sn",
                     },
                 },
                 "resources": {
                     "rdn": "ou=Resources",
-                    "attr": "cn", # used only to synthesize email address
-                    "emailSuffix": None, # used only to synthesize email address
                     "filter": None, # additional filter for this type
                     "calendarEnabledAttr" : "", # attribute controlling enabledForCalendaring
                     "calendarEnabledValue" : "yes", # "True" value of above attribute
@@ -167,10 +158,18 @@
                         "recordName": "cn",
                         "fullName" : "cn",
                         "emailAddresses" : ["mail"], # multiple LDAP fields supported
-                        "firstName" : "givenName",
-                        "lastName" : "sn",
                     },
                 },
+                "addresses": {
+                    "rdn": "ou=Buildings",
+                    "filter": None, # additional filter for this type
+                    "streetAddressAttr" : "",
+                    "geoAttr" : "",
+                    "mapping" : { # maps internal record names to LDAP
+                        "recordName": "cn",
+                        "fullName" : "cn",
+                    },
+                },
             },
             "groupSchema": {
                 "membersAttr": "member", # how members are specified
@@ -238,8 +237,10 @@
         for recordType in self.recordTypes():
             if self.rdnSchema[recordType]["attr"]:
                 attrSet.add(self.rdnSchema[recordType]["attr"])
-            if self.rdnSchema[recordType].get("calendarEnabledAttr", False):
-                attrSet.add(self.rdnSchema[recordType]["calendarEnabledAttr"])
+            for n in ("calendarEnabledAttr", "associatedAddressAttr",
+                "streetAddressAttr", "geoAttr"):
+                if self.rdnSchema[recordType].get(n, False):
+                    attrSet.add(self.rdnSchema[recordType][n])
             for attrList in self.rdnSchema[recordType]["mapping"].values():
                 if attrList:
                     # Since emailAddresses can map to multiple LDAP fields,
@@ -304,7 +305,7 @@
 
         # Build filter
         filterstr = "(!(objectClass=organizationalUnit))"
-        typeFilter = self.rdnSchema[recordType]["filter"]
+        typeFilter = self.rdnSchema[recordType].get("filter", "")
         if typeFilter:
             filterstr = "(&%s%s)" % (filterstr, typeFilter)
 
@@ -778,6 +779,7 @@
         enabledForAddressBooks = None
         uid = None
         enabledForLogin = True
+        extras = {}
 
         shortNames = tuple(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"]["recordName"]))
         if not shortNames:
@@ -794,17 +796,17 @@
 
         # Find or build email
         # (The emailAddresses mapping is a list of ldap fields)
-        emailAddressesMappedTo = self.rdnSchema[recordType]["mapping"]["emailAddresses"]
+        emailAddressesMappedTo = self.rdnSchema[recordType]["mapping"].get("emailAddresses", "")
         # Supporting either string or list for emailAddresses:
         if isinstance(emailAddressesMappedTo, str):
-            emailAddresses = set(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"]["emailAddresses"]))
+            emailAddresses = set(self._getMultipleLdapAttributes(attrs, self.rdnSchema[recordType]["mapping"].get("emailAddresses", "")))
         else:
             emailAddresses = set(self._getMultipleLdapAttributes(attrs, *self.rdnSchema[recordType]["mapping"]["emailAddresses"]))
-        emailSuffix = self.rdnSchema[recordType]["emailSuffix"]
+        emailSuffix = self.rdnSchema[recordType].get("emailSuffix", None)
 
         if len(emailAddresses) == 0 and emailSuffix:
             emailPrefix = self._getUniqueLdapAttribute(attrs,
-                self.rdnSchema[recordType]["attr"])
+                self.rdnSchema[recordType].get("attr", "cn"))
             emailAddresses.add(emailPrefix + emailSuffix)
 
         proxyGUIDs = ()
@@ -890,6 +892,25 @@
                     autoAcceptGroup = self._getUniqueLdapAttribute(attrs,
                         self.resourceSchema["autoAcceptGroupAttr"])
 
+            if recordType == self.recordType_locations:
+                if self.rdnSchema[recordType]["associatedAddressAttr"]:
+                    associatedAddress = self._getUniqueLdapAttribute(attrs,
+                        self.rdnSchema[recordType]["associatedAddressAttr"])
+                    if associatedAddress:
+                        extras["associatedAddress"] = associatedAddress
+
+        elif recordType == self.recordType_addresses:
+            if self.rdnSchema[recordType].get("geoAttr", ""):
+                geo = self._getUniqueLdapAttribute(attrs,
+                    self.rdnSchema[recordType]["geoAttr"])
+                if geo:
+                    extras["geo"] = geo
+            if self.rdnSchema[recordType].get("streetAddressAttr", ""):
+                street = self._getUniqueLdapAttribute(attrs,
+                    self.rdnSchema[recordType]["streetAddressAttr"])
+                if street:
+                    extras["streetAddress"] = street
+
         serverID = None
         if self.poddingSchema["serverIdAttr"]:
             serverID = self._getUniqueLdapAttribute(attrs,
@@ -911,6 +932,7 @@
             extProxies=proxyGUIDs,
             extReadOnlyProxies=readOnlyProxyGUIDs,
             attrs=attrs,
+            **extras
         )
 
         if self.augmentService is not None:
@@ -981,7 +1003,7 @@
 
             # Build filter
             filterstr = "(!(objectClass=organizationalUnit))"
-            typeFilter = self.rdnSchema[recordType]["filter"]
+            typeFilter = self.rdnSchema[recordType].get("filter", "")
             if typeFilter:
                 filterstr = "(&%s%s)" % (filterstr, typeFilter)
 
@@ -1003,17 +1025,17 @@
             elif indexType == self.INDEX_TYPE_CUA:
                 # indexKey is of the form "mailto:test at example.net"
                 email = indexKey[7:] # strip "mailto:"
-                emailSuffix = self.rdnSchema[recordType]["emailSuffix"]
+                emailSuffix = self.rdnSchema[recordType].get("emailSuffix", None)
                 if emailSuffix is not None and email.partition("@")[2] == emailSuffix:
                     filterstr = "(&%s(|(&(!(mail=*))(%s=%s))(mail=%s)))" % (
                         filterstr,
-                        self.rdnSchema[recordType]["attr"],
+                        self.rdnSchema[recordType].get("attr", "cn"),
                         email.partition("@")[0],
                         ldapEsc(email)
                     )
                 else:
                     # emailAddresses can map to multiple LDAP fields
-                    ldapFields = self.rdnSchema[recordType]["mapping"]["emailAddresses"]
+                    ldapFields = self.rdnSchema[recordType]["mapping"].get("emailAddresses", "")
                     if isinstance(ldapFields, str):
                         if ldapFields:
                             subfilter = "(%s=%s)" % (ldapFields, ldapEsc(email))
@@ -1108,7 +1130,7 @@
             typeCounts[recordType] = 0
             base = self.typeDNs[recordType]
             scope = ldap.SCOPE_SUBTREE
-            extraFilter = self.rdnSchema[recordType]["filter"]
+            extraFilter = self.rdnSchema[recordType].get("filter", "")
             filterstr = buildFilterFromTokens(recordType, self.rdnSchema[recordType]["mapping"],
                 tokens, extra=extraFilter)
 
@@ -1509,7 +1531,7 @@
         guid, shortNames, authIDs, fullName,
         firstName, lastName, emailAddresses,
         uid, dn, memberGUIDs, extProxies, extReadOnlyProxies,
-        attrs
+        attrs, **kwargs
     ):
         super(LdapDirectoryRecord, self).__init__(
             service=service,
@@ -1524,6 +1546,7 @@
             extProxies=extProxies,
             extReadOnlyProxies=extReadOnlyProxies,
             uid=uid,
+            **kwargs
         )
 
         # Save attributes of dn and attrs in case you might need them later

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/opendirectorybacker.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/opendirectorybacker.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -46,9 +46,9 @@
 from twext.python.filepath import CachingFilePath as FilePath
 from txdav.xml import element as davxml
 from txdav.xml.base import twisted_dav_namespace, dav_namespace, parse_date, twisted_private_namespace
-from twext.web2.dav.resource import DAVPropertyMixIn
-from twext.web2.dav.util import joinURL
-from twext.web2.http_headers import MimeType, generateContentType, ETag
+from txweb2.dav.resource import DAVPropertyMixIn
+from txweb2.dav.util import joinURL
+from txweb2.http_headers import MimeType, generateContentType, ETag
 
 
 from twistedcaldav import customxml, carddavxml

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/principal.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/principal.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -38,12 +38,12 @@
 from twisted.web.template import XMLFile, Element, renderer, tags
 from twistedcaldav.directory.util import NotFoundResource
 
-from twext.web2.auth.digest import DigestedCredentials
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError
+from txweb2.auth.digest import DigestedCredentials
+from txweb2 import responsecode
+from txweb2.http import HTTPError
 from txdav.xml import element as davxml
-from twext.web2.dav.util import joinURL
-from twext.web2.dav.noneprops import NonePropertyStore
+from txweb2.dav.util import joinURL
+from txweb2.dav.noneprops import NonePropertyStore
 
 from twext.python.log import Logger
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -18,7 +18,7 @@
 Implements a directory-backed principal hierarchy.
 """
 
-from twext.web2.dav.util import joinURL
+from txweb2.dav.util import joinURL
 
 from twistedcaldav.client.reverseproxy import ReverseProxyResource
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_aggregate.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_aggregate.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_aggregate.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -56,6 +56,7 @@
     groups = property(_records("groups"))
     locations = property(_records("locations"))
     resources = property(_records("resources"))
+    addresses = property(_records("addresses"))
 
     recordTypePrefixes = tuple(s[0] for s in testServices)
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_digest.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_digest.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_digest.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -21,16 +21,16 @@
 from twisted.internet import address
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python import failure
-from twext.web2.auth import digest
-from twext.web2.auth.wrapper import UnauthorizedResponse
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.auth import digest
+from txweb2.auth.wrapper import UnauthorizedResponse
+from txweb2.test.test_server import SimpleRequest
 
 from twistedcaldav.directory.digest import QopDigestCredentialFactory
 from twistedcaldav.test.util import TestCase
 from twistedcaldav.config import config
-from twext.web2.auth.digest import DigestCredentialFactory
-from twext.web2.test.test_httpauth import makeDigestDeterministic
-from twext.web2.test.test_httpauth import FAKE_STATIC_NONCE
+from txweb2.auth.digest import DigestCredentialFactory
+from txweb2.test.test_httpauth import makeDigestDeterministic
+from txweb2.test.test_httpauth import FAKE_STATIC_NONCE
 
 class FakeDigestCredentialFactory(QopDigestCredentialFactory):
     """

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_guidchange.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_guidchange.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_guidchange.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -18,8 +18,8 @@
 from twistedcaldav.directory.directory import DirectoryService
 
 from txdav.xml import element as davxml
-from twext.web2.dav.resource import AccessDeniedError
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.dav.resource import AccessDeniedError
+from txweb2.test.test_server import SimpleRequest
 
 from twistedcaldav.directory.test.util import maybeCommit
 from twistedcaldav.test.util import TestCase, xmlFile

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_ldapdirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_ldapdirectory.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_ldapdirectory.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -541,8 +541,6 @@
                             "recordName": "cn",
                             "fullName" : "cn",
                             "emailAddresses" : ["mail", "emailAliases"],
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
                         },
                     },
                     "locations": {
@@ -552,12 +550,11 @@
                         "filter": "(objectClass=apple-resource)", # additional filter for this type
                         "calendarEnabledAttr" : "", # attribute controlling calendaring
                         "calendarEnabledValue" : "yes", # "True" value of above attribute
+                        "associatedAddressAttr" : "assocAddr",
                         "mapping": { # maps internal record names to LDAP
                             "recordName": "cn",
                             "fullName" : "cn",
                             "emailAddresses" : "", # old style, single string
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
                         },
                     },
                     "resources": {
@@ -571,10 +568,17 @@
                             "recordName": "cn",
                             "fullName" : "cn",
                             "emailAddresses" : [], # new style, array
-                            "firstName" : "givenName",
-                            "lastName" : "sn",
                         },
                     },
+                    "addresses": {
+                        "rdn": "cn=Buildings",
+                        "geoAttr" : "coordinates",
+                        "streetAddressAttr" : "postal",
+                        "mapping": { # maps internal record names to LDAP
+                            "recordName": "cn",
+                            "fullName" : "cn",
+                        },
+                    },
                 },
                 "groupSchema": {
                     "membersAttr": "uniqueMember", # how members are specified
@@ -1514,6 +1518,39 @@
                 self.service.recordType_users)
             self.assertEquals(record.guid, guid.upper())
 
+            # Location with associated Address
+
+            dn = "cn=odtestlocation,cn=locations,dc=example,dc=com"
+            guid = "D3094652-344B-4633-8DB8-09639FA00FB6"
+            attrs = {
+                "apple-generateduid": [guid],
+                "cn": ["odtestlocation"],
+                "assocAddr" : ["6C6CD280-E6E3-11DF-9492-0800200C9A66"],
+            }
+            record = self.service._ldapResultToRecord(dn, attrs,
+                self.service.recordType_locations)
+            self.assertEquals(record.extras, {
+                "associatedAddress": "6C6CD280-E6E3-11DF-9492-0800200C9A66"
+            })
+           
+            # Address with street and geo
+
+            dn = "cn=odtestaddress,cn=buildings,dc=example,dc=com"
+            guid = "6C6CD280-E6E3-11DF-9492-0800200C9A66"
+            attrs = {
+                "apple-generateduid": [guid],
+                "cn": ["odtestaddress"],
+                "coordinates" : ["geo:1,2"],
+                "postal" : ["1 Infinite Loop, Cupertino, CA"],
+            }
+            record = self.service._ldapResultToRecord(dn, attrs,
+                self.service.recordType_addresses)
+            self.assertEquals(record.extras, {
+                "geo": "geo:1,2",
+                "streetAddress" : "1 Infinite Loop, Cupertino, CA",
+            })
+           
+
         def test_listRecords(self):
             """
             listRecords makes an LDAP query (with fake results in this test)

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_opendirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_opendirectory.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_opendirectory.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -21,7 +21,7 @@
 else:
     from calendarserver.platform.darwin.od import dsattributes
     from collections import defaultdict
-    from twext.web2.auth.digest import DigestedCredentials
+    from txweb2.auth.digest import DigestedCredentials
     from twisted.internet.defer import inlineCallbacks
     from twisted.python.runtime import platform
     from twisted.trial.unittest import SkipTest

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_principal.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_principal.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -20,10 +20,10 @@
 from twisted.cred.credentials import UsernamePassword
 from twisted.internet.defer import inlineCallbacks
 from txdav.xml import element as davxml
-from twext.web2.dav.fileop import rmdir
-from twext.web2.dav.resource import AccessDeniedError
-from twext.web2.http import HTTPError
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.dav.fileop import rmdir
+from txweb2.dav.resource import AccessDeniedError
+from txweb2.http import HTTPError
+from txweb2.test.test_server import SimpleRequest
 
 from twistedcaldav.cache import DisabledCacheNotifier
 from twistedcaldav.caldavxml import caldav_namespace

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_wiki.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_wiki.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_wiki.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -20,8 +20,8 @@
 )
 from twisted.internet.defer import inlineCallbacks, succeed
 from twisted.web.xmlrpc import Fault
-from twext.web2.http import HTTPError
-from twext.web2 import responsecode
+from txweb2.http import HTTPError
+from txweb2 import responsecode
 from twistedcaldav.config import config
 from twisted.web.error import Error as WebError
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_xmlfile.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_xmlfile.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/test_xmlfile.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -34,7 +34,8 @@
         DirectoryService.recordType_users,
         DirectoryService.recordType_groups,
         DirectoryService.recordType_locations,
-        DirectoryService.recordType_resources
+        DirectoryService.recordType_resources,
+        DirectoryService.recordType_addresses,
     ))
 
     users = {

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/util.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/test/util.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,7 +16,7 @@
 
 from twisted.trial.unittest import SkipTest
 from twisted.cred.credentials import UsernamePassword
-from twext.web2.auth.digest import DigestedCredentials, calcResponse, calcHA1
+from txweb2.auth.digest import DigestedCredentials, calcResponse, calcHA1
 
 from twistedcaldav.directory.directory import DirectoryService
 from twistedcaldav.directory.directory import UnknownRecordTypeError
@@ -44,6 +44,10 @@
     # Subclass should init this to a dict of resourcenames keys and dict values.
     resources = {}
 
+    # Subclass should init this to a dict of addressname keys and dict values.
+    addresses = {}
+
+
     # Subclass should init this to an IDirectoryService implementation class.
     def service(self):
         """

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/util.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/util.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -27,10 +27,10 @@
 
 from twext.enterprise.ienterprise import AlreadyFinishedError
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.auth.wrapper import UnauthorizedResponse
-from twext.web2.dav.resource import DAVResource
-from twext.web2.http import StatusResponse
+from txweb2 import responsecode
+from txweb2.auth.wrapper import UnauthorizedResponse
+from txweb2.dav.resource import DAVResource
+from txweb2.http import StatusResponse
 from twisted.internet.defer import inlineCallbacks, returnValue
 from txdav.xml import element as davxml
 from uuid import UUID, uuid5

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/wiki.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/wiki.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/wiki.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -27,10 +27,10 @@
 
 from twext.internet.gaiendpoint import MultiFailure
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.auth.wrapper import UnauthorizedResponse
-from twext.web2.dav.resource import TwistedACLInheritable
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2 import responsecode
+from txweb2.auth.wrapper import UnauthorizedResponse
+from txweb2.dav.resource import TwistedACLInheritable
+from txweb2.http import HTTPError, StatusResponse
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.web.error import Error as WebError

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/xmlaccountsparser.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/xmlaccountsparser.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -41,6 +41,7 @@
 ELEMENT_GROUP             = "group"
 ELEMENT_LOCATION          = "location"
 ELEMENT_RESOURCE          = "resource"
+ELEMENT_ADDRESS           = "address"
 
 ELEMENT_SHORTNAME         = "uid"
 ELEMENT_GUID              = "guid"
@@ -65,6 +66,7 @@
     ELEMENT_GROUP    : DirectoryService.recordType_groups,
     ELEMENT_LOCATION : DirectoryService.recordType_locations,
     ELEMENT_RESOURCE : DirectoryService.recordType_resources,
+    ELEMENT_ADDRESS  : DirectoryService.recordType_addresses,
 }
 
 class XMLAccountsParser(object):

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/xmlfile.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directory/xmlfile.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -29,7 +29,7 @@
 import types
 
 from twisted.cred.credentials import UsernamePassword
-from twext.web2.auth.digest import DigestedCredentials
+from txweb2.auth.digest import DigestedCredentials
 from twext.python.filepath import CachingFilePath as FilePath
 from twistedcaldav.config import config
 from twisted.internet.defer import succeed
@@ -71,6 +71,7 @@
                 self.recordType_groups,
                 self.recordType_locations,
                 self.recordType_resources,
+                self.recordType_addresses,
             ),
             'realmName' : '/Search',
             'statSeconds' : 15,
@@ -373,6 +374,7 @@
             'groups'    : 'group',
             'locations' : 'location',
             'resources' : 'resource',
+            'addresses' : 'address',
         }
         xmlType = xmlTypes[principal.recordType]
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directorybackedaddressbook.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directorybackedaddressbook.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/directorybackedaddressbook.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -23,10 +23,10 @@
 ]
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
-from twext.web2.dav.resource import TwistedACLInheritable
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2.dav.resource import TwistedACLInheritable
+from txweb2.http import HTTPError, StatusResponse
 
 from twisted.internet.defer import succeed, inlineCallbacks, maybeDeferred, returnValue
 from twisted.python.reflect import namedClass

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/dropbox.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/dropbox.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/dropbox.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -24,11 +24,11 @@
 ]
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
-from twext.web2.dav.http import ErrorResponse
-from twext.web2.dav.resource import DAVResource, TwistedACLInheritable
-from twext.web2.dav.util import joinURL
+from txweb2.dav.http import ErrorResponse
+from txweb2.dav.resource import DAVResource, TwistedACLInheritable
+from txweb2.dav.util import joinURL
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/extensions.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/extensions.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -40,23 +40,23 @@
 from twisted.web.template import Element, XMLFile, renderer, tags, flattenString
 from twisted.python.modules import getModule
 
-from twext.web2 import responsecode, server
-from twext.web2.http import HTTPError, Response, RedirectResponse
-from twext.web2.http import StatusResponse
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import FileStream
-from twext.web2.static import MetaDataMixin, StaticRenderMixin
+from txweb2 import responsecode, server
+from txweb2.http import HTTPError, Response, RedirectResponse
+from txweb2.http import StatusResponse
+from txweb2.http_headers import MimeType
+from txweb2.stream import FileStream
+from txweb2.static import MetaDataMixin, StaticRenderMixin
 from txdav.xml import element
 from txdav.xml.base import encodeXMLName
 from txdav.xml.element import dav_namespace
-from twext.web2.dav.http import MultiStatusResponse
-from twext.web2.dav.static import DAVFile as SuperDAVFile
-from twext.web2.dav.resource import DAVResource as SuperDAVResource
-from twext.web2.dav.resource import (
+from txweb2.dav.http import MultiStatusResponse
+from txweb2.dav.static import DAVFile as SuperDAVFile
+from txweb2.dav.resource import DAVResource as SuperDAVResource
+from txweb2.dav.resource import (
     DAVPrincipalResource as SuperDAVPrincipalResource
 )
 from twisted.internet.defer import gatherResults
-from twext.web2.dav.method import prop_common
+from txweb2.dav.method import prop_common
 
 from twext.python.log import Logger
 
@@ -541,7 +541,7 @@
                    SuperDAVResource,
                    DirectoryRenderingMixIn, StaticRenderMixin):
     """
-    Extended L{twext.web2.dav.resource.DAVResource} implementation.
+    Extended L{txweb2.dav.resource.DAVResource} implementation.
 
     Note we add StaticRenderMixin as a base class because we need all the etag etc behavior
     that is currently in static.py but is actually applicable to any type of resource.
@@ -577,7 +577,7 @@
 
 class DAVResourceWithChildrenMixin (object):
     """
-    Bits needed from twext.web2.static
+    Bits needed from txweb2.static
     """
 
     def __init__(self, principalCollections=None):
@@ -646,7 +646,7 @@
 
 class DAVResourceWithoutChildrenMixin (object):
     """
-    Bits needed from twext.web2.static
+    Bits needed from txweb2.static
     """
 
     def __init__(self, principalCollections=None):
@@ -670,7 +670,7 @@
                             SuperDAVPrincipalResource,
                             DirectoryRenderingMixIn):
     """
-    Extended L{twext.web2.dav.static.DAVFile} implementation.
+    Extended L{txweb2.dav.static.DAVFile} implementation.
     """
     log = Logger()
 
@@ -761,7 +761,7 @@
 
 class DAVFile (SuperDAVFile, DirectoryRenderingMixIn):
     """
-    Extended L{twext.web2.dav.static.DAVFile} implementation.
+    Extended L{txweb2.dav.static.DAVFile} implementation.
     """
     log = Logger()
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/freebusyurl.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/freebusyurl.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/freebusyurl.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -25,15 +25,15 @@
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
-from twext.web2.dav.http import ErrorResponse
-from twext.web2.dav.util import joinURL
-from twext.web2.http import HTTPError
-from twext.web2.http import Response
-from twext.web2.http import StatusResponse
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import MemoryStream
+from txweb2.dav.http import ErrorResponse
+from txweb2.dav.util import joinURL
+from txweb2.http import HTTPError
+from txweb2.http import Response
+from txweb2.http import StatusResponse
+from txweb2.http_headers import MimeType
+from txweb2.stream import MemoryStream
 
 from twistedcaldav import caldavxml
 from twistedcaldav.caldavxml import TimeRange

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/ical.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/ical.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/ical.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -35,8 +35,8 @@
 import uuid
 
 from twext.python.log import Logger
-from twext.web2.stream import IStream
-from twext.web2.dav.util import allDataFromStream
+from txweb2.stream import IStream
+from txweb2.dav.util import allDataFromStream
 
 from twistedcaldav.config import config
 from twistedcaldav.dateops import timeRangesOverlap, normalizeForIndex, differenceDateTime, \
@@ -3418,7 +3418,33 @@
         return False
 
 
+    def hasDuplicatePrivateComments(self, doFix=False):
+        """
+        Test and optionally remove "X-CALENDARSERVER-ATTENDEE-COMMENT" properties that have the same
+        "X-CALENDARSERVER-ATTENDEE-REF" parameter values in the same component.
 
+        @return: C{True} if there are duplicates that were not fixed.
+        """
+        if self.name() == "VCALENDAR":
+            for component in self.subcomponents():
+                if component.name() in ("VTIMEZONE",):
+                    continue
+                if component.hasDuplicatePrivateComments(doFix):
+                    return True
+        else:
+            attendee_refs = set()
+            for prop in tuple(self.properties("X-CALENDARSERVER-ATTENDEE-COMMENT")):
+                ref = prop.parameterValue("X-CALENDARSERVER-ATTENDEE-REF")
+                if ref in attendee_refs:
+                    if doFix:
+                        self.removeProperty(prop)
+                    else:
+                        return True
+                attendee_refs.add(ref)
+        return False
+
+
+
 # #
 # Timezones
 # #

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/icaldav.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/icaldav.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/icaldav.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -23,7 +23,7 @@
     "ICalendarPrincipalResource",
 ]
 
-from twext.web2.dav.idav import IDAVResource
+from txweb2.dav.idav import IDAVResource
 
 class ICalDAVResource(IDAVResource):
     """

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/linkresource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/linkresource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/linkresource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,10 +16,10 @@
 
 
 from twext.python.log import Logger
-from twext.web2 import responsecode, server, http
+from txweb2 import responsecode, server, http
 from txdav.xml import element as davxml
-from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.resource import WrapperResource
+from txweb2.http import HTTPError, StatusResponse
+from txweb2.resource import WrapperResource
 
 from twisted.internet.defer import inlineCallbacks, returnValue, maybeDeferred
 

Copied: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcacheclient.py (from rev 12132, CalendarServer/trunk/twistedcaldav/memcacheclient.py)
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcacheclient.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcacheclient.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -0,0 +1,1457 @@
+#!/usr/bin/env python
+from __future__ import print_function
+
+"""
+client module for memcached (memory cache daemon)
+
+Overview
+========
+
+See U{the MemCached homepage<http://www.danga.com/memcached>} for more about memcached.
+
+Usage summary
+=============
+
+This should give you a feel for how this module operates::
+
+    import memcacheclient
+    mc = memcacheclient.Client(['127.0.0.1:11211'], debug=0)
+
+    mc.set("some_key", "Some value")
+    value = mc.get("some_key")
+
+    mc.set("another_key", 3)
+    mc.delete("another_key")
+
+    mc.set("key", "1")   # note that the key used for incr/decr must be a string.
+    mc.incr("key")
+    mc.decr("key")
+
+The standard way to use memcache with a database is like this::
+
+    key = derive_key(obj)
+    obj = mc.get(key)
+    if not obj:
+        obj = backend_api.get(...)
+        mc.set(obj)
+
+    # we now have obj, and future passes through this code
+    # will use the object from the cache.
+
+Detailed Documentation
+======================
+
+More detailed documentation is available in the L{Client} class.
+"""
+
+import sys
+import socket
+import time
+import os
+import re
+import types
+
+from twext.python.log import Logger
+
+from twistedcaldav.config import config
+
+log = Logger()
+
+
+try:
+    import cPickle as pickle
+except ImportError:
+    import pickle
+
+try:
+    from zlib import compress, decompress
+    _supports_compress = True
+except ImportError:
+    _supports_compress = False
+    # quickly define a decompress just in case we recv compressed data.
+    def decompress(val):
+        raise _Error("received compressed data but I don't support compession (import error)")
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+from binascii import crc32   # zlib version is not cross-platform
+serverHashFunction = crc32
+
+__author__    = "Evan Martin <martine at danga.com>"
+__version__ = "1.44"
+__copyright__ = "Copyright (C) 2003 Danga Interactive"
+__license__   = "Python"
+
+SERVER_MAX_KEY_LENGTH = 250
+#  Storing values larger than 1MB requires recompiling memcached.  If you do,
+#  this value can be changed by doing "memcacheclient.SERVER_MAX_VALUE_LENGTH = N"
+#  after importing this module.
+SERVER_MAX_VALUE_LENGTH = 1024*1024
+
+class _Error(Exception):
+    pass
+
+class MemcacheError(_Error):
+    """
+    Memcache connection error
+    """
+
+class NotFoundError(MemcacheError):
+    """
+    NOT_FOUND error
+    """
+
+class TokenMismatchError(MemcacheError):
+    """
+    Check-and-set token mismatch
+    """
+
+try:
+    # Only exists in Python 2.4+
+    from threading import local
+except ImportError:
+    # TODO:  add the pure-python local implementation
+    class local(object):
+        pass
+
+class ClientFactory(object):
+
+    # unit tests should set this to True to enable the fake test cache
+    allowTestCache = False
+
+    @classmethod
+    def getClient(cls, servers, debug=0, pickleProtocol=0,
+                 pickler=pickle.Pickler, unpickler=pickle.Unpickler,
+                 pload=None, pid=None):
+
+        if cls.allowTestCache:
+            return TestClient(servers, debug=debug,
+                pickleProtocol=pickleProtocol, pickler=pickler,
+                unpickler=unpickler, pload=pload, pid=pid)
+        elif config.Memcached.Pools.Default.ClientEnabled:
+            return Client(servers, debug=debug, pickleProtocol=pickleProtocol,
+                pickler=pickler, unpickler=unpickler, pload=pload, pid=pid)
+        else:
+            return None
+
+
+class Client(local):
+    """
+    Object representing a pool of memcache servers.
+
+    See L{memcache} for an overview.
+
+    In all cases where a key is used, the key can be either:
+        1. A simple hashable type (string, integer, etc.).
+        2. A tuple of C{(hashvalue, key)}.  This is useful if you want to avoid
+        making this module calculate a hash value.  You may prefer, for
+        example, to keep all of a given user's objects on the same memcache
+        server, so you could use the user's unique id as the hash value.
+
+    @group Setup: __init__, set_servers, forget_dead_hosts, disconnect_all, debuglog
+    @group Insertion: set, add, replace, set_multi
+    @group Retrieval: get, get_multi
+    @group Integers: incr, decr
+    @group Removal: delete, delete_multi
+    @sort: __init__, set_servers, forget_dead_hosts, disconnect_all, debuglog,\
+           set, set_multi, add, replace, get, get_multi, incr, decr, delete, delete_multi
+    """
+    _FLAG_PICKLE  = 1<<0
+    _FLAG_INTEGER = 1<<1
+    _FLAG_LONG    = 1<<2
+    _FLAG_COMPRESSED = 1<<3
+
+    _SERVER_RETRIES = 10  # how many times to try finding a free server.
+
+    # exceptions for Client
+    class MemcachedKeyError(Exception):
+        pass
+    class MemcachedKeyLengthError(MemcachedKeyError):
+        pass
+    class MemcachedKeyCharacterError(MemcachedKeyError):
+        pass
+    class MemcachedKeyNoneError(MemcachedKeyError):
+        pass
+    class MemcachedKeyTypeError(MemcachedKeyError):
+        pass
+    class MemcachedStringEncodingError(Exception):
+        pass
+
+    def __init__(self, servers, debug=0, pickleProtocol=0,
+                 pickler=pickle.Pickler, unpickler=pickle.Unpickler,
+                 pload=None, pid=None):
+        """
+        Create a new Client object with the given list of servers.
+
+        @param servers: C{servers} is passed to L{set_servers}.
+        @param debug: whether to display error messages when a server can't be
+        contacted.
+        @param pickleProtocol: number to mandate protocol used by (c)Pickle.
+        @param pickler: optional override of default Pickler to allow subclassing.
+        @param unpickler: optional override of default Unpickler to allow subclassing.
+        @param pload: optional persistent_load function to call on pickle loading.
+        Useful for cPickle since subclassing isn't allowed.
+        @param pid: optional persistent_id function to call on pickle storing.
+        Useful for cPickle since subclassing isn't allowed.
+        """
+        local.__init__(self)
+        self.set_servers(servers)
+        self.debug = debug
+        self.stats = {}
+
+        # Allow users to modify pickling/unpickling behavior
+        self.pickleProtocol = pickleProtocol
+        self.pickler = pickler
+        self.unpickler = unpickler
+        self.persistent_load = pload
+        self.persistent_id = pid
+
+        #  figure out the pickler style
+        file = StringIO()
+        try:
+            pickler = self.pickler(file, protocol = self.pickleProtocol)
+            self.picklerIsKeyword = True
+        except TypeError:
+            self.picklerIsKeyword = False
+
+    def set_servers(self, servers):
+        """
+        Set the pool of servers used by this client.
+
+        @param servers: an array of servers.
+        Servers can be passed in two forms:
+            1. Strings of the form C{"host:port"}, which implies a default weight of 1.
+            2. Tuples of the form C{("host:port", weight)}, where C{weight} is
+            an integer weight value.
+        """
+        self.servers = [_Host(s, self.debuglog) for s in servers]
+        self._init_buckets()
+
+    def get_stats(self):
+        '''Get statistics from each of the servers.
+
+        @return: A list of tuples ( server_identifier, stats_dictionary ).
+            The dictionary contains a number of name/value pairs specifying
+            the name of the status field and the string value associated with
+            it.  The values are not converted from strings.
+        '''
+        data = []
+        for s in self.servers:
+            if not s.connect(): continue
+            if s.family == socket.AF_INET:
+                name = '%s:%s (%s)' % ( s.ip, s.port, s.weight )
+            else:
+                name = 'unix:%s (%s)' % ( s.address, s.weight )
+            s.send_cmd('stats')
+            serverData = {}
+            data.append(( name, serverData ))
+            readline = s.readline
+            while 1:
+                line = readline()
+                if not line or line.strip() == 'END': break
+                stats = line.split(' ', 2)
+                serverData[stats[1]] = stats[2]
+
+        return(data)
+
+    def get_slabs(self):
+        data = []
+        for s in self.servers:
+            if not s.connect(): continue
+            if s.family == socket.AF_INET:
+                name = '%s:%s (%s)' % ( s.ip, s.port, s.weight )
+            else:
+                name = 'unix:%s (%s)' % ( s.address, s.weight )
+            serverData = {}
+            data.append(( name, serverData ))
+            s.send_cmd('stats items')
+            readline = s.readline
+            while 1:
+                line = readline()
+                if not line or line.strip() == 'END': break
+                item = line.split(' ', 2)
+                #0 = STAT, 1 = ITEM, 2 = Value
+                slab = item[1].split(':', 2)
+                #0 = items, 1 = Slab #, 2 = Name
+                if not serverData.has_key(slab[1]):
+                    serverData[slab[1]] = {}
+                serverData[slab[1]][slab[2]] = item[2]
+        return data
+
+    def flush_all(self):
+        'Expire all data currently in the memcache servers.'
+        for s in self.servers:
+            if not s.connect(): continue
+            s.send_cmd('flush_all')
+            s.expect("OK")
+
+    def debuglog(self, str):
+        if self.debug:
+            sys.stderr.write("MemCached: %s\n" % str)
+
+    def _statlog(self, func):
+        if not self.stats.has_key(func):
+            self.stats[func] = 1
+        else:
+            self.stats[func] += 1
+
+    def forget_dead_hosts(self):
+        """
+        Reset every host in the pool to an "alive" state.
+        """
+        for s in self.servers:
+            s.deaduntil = 0
+
+    def _init_buckets(self):
+        self.buckets = []
+        for server in self.servers:
+            for i in range(server.weight):
+                self.buckets.append(server)
+
+    def _get_server(self, key):
+        if type(key) == types.TupleType:
+            serverhash, key = key
+        else:
+            serverhash = serverHashFunction(key)
+
+        for i in range(Client._SERVER_RETRIES):
+            server = self.buckets[serverhash % len(self.buckets)]
+            if server.connect():
+                #print("(using server %s)" % server, end="")
+                return server, key
+            serverhash = serverHashFunction(str(serverhash) + str(i))
+        log.error("Memcacheclient _get_server( ) failed to connect")
+        return None, None
+
+    def disconnect_all(self):
+        for s in self.servers:
+            s.close_socket()
+
+    def delete_multi(self, keys, time=0, key_prefix=''):
+        '''
+        Delete multiple keys in the memcache doing just one query.
+
+        >>> notset_keys = mc.set_multi({'key1' : 'val1', 'key2' : 'val2'})
+        >>> mc.get_multi(['key1', 'key2']) == {'key1' : 'val1', 'key2' : 'val2'}
+        1
+        >>> mc.delete_multi(['key1', 'key2'])
+        1
+        >>> mc.get_multi(['key1', 'key2']) == {}
+        1
+
+
+        This method is recommended over iterated regular L{delete}s as it reduces total latency, since
+        your app doesn't have to wait for each round-trip of L{delete} before sending
+        the next one.
+
+        @param keys: An iterable of keys to clear
+        @param time: number of seconds any subsequent set / update commands should fail. Defaults to 0 for no delay.
+        @param key_prefix:  Optional string to prepend to each key when sending to memcache.
+            See docs for L{get_multi} and L{set_multi}.
+
+        @return: 1 if no failure in communication with any memcacheds.
+        @rtype: int
+
+        '''
+
+        self._statlog('delete_multi')
+
+        server_keys, prefixed_to_orig_key = self._map_and_prefix_keys(keys, key_prefix)
+
+        # send out all requests on each server before reading anything
+        dead_servers = []
+
+        rc = 1
+        for server in server_keys.iterkeys():
+            bigcmd = []
+            write = bigcmd.append
+            if time != None:
+                 for key in server_keys[server]: # These are mangled keys
+                     write("delete %s %d\r\n" % (key, time))
+            else:
+                for key in server_keys[server]: # These are mangled keys
+                  write("delete %s\r\n" % key)
+            try:
+                server.send_cmds(''.join(bigcmd))
+            except socket.error, msg:
+                rc = 0
+                if type(msg) is types.TupleType: msg = msg[1]
+                server.mark_dead(msg)
+                dead_servers.append(server)
+
+        # if any servers died on the way, don't expect them to respond.
+        for server in dead_servers:
+            del server_keys[server]
+
+        for server, keys in server_keys.iteritems():
+            try:
+                for key in keys:
+                    server.expect("DELETED")
+            except socket.error, msg:
+                if type(msg) is types.TupleType: msg = msg[1]
+                server.mark_dead(msg)
+                rc = 0
+        return rc
+
+    def delete(self, key, time=0):
+        '''Deletes a key from the memcache.
+
+        @return: Nonzero on success.
+        @param time: number of seconds any subsequent set / update commands should fail. Defaults to 0 for no delay.
+        @rtype: int
+        '''
+        check_key(key)
+        server, key = self._get_server(key)
+        if not server:
+            return 0
+        self._statlog('delete')
+        if time != None:
+            cmd = "delete %s %d" % (key, time)
+        else:
+            cmd = "delete %s" % key
+
+        try:
+            server.send_cmd(cmd)
+            server.expect("DELETED")
+        except socket.error, msg:
+            if type(msg) is types.TupleType: msg = msg[1]
+            server.mark_dead(msg)
+            return 0
+        return 1
+
+    def incr(self, key, delta=1):
+        """
+        Sends a command to the server to atomically increment the value for C{key} by
+        C{delta}, or by 1 if C{delta} is unspecified.  Returns None if C{key} doesn't
+        exist on server, otherwise it returns the new value after incrementing.
+
+        Note that the value for C{key} must already exist in the memcache, and it
+        must be the string representation of an integer.
+
+        >>> mc.set("counter", "20")  # returns 1, indicating success
+        1
+        >>> mc.incr("counter")
+        21
+        >>> mc.incr("counter")
+        22
+
+        Overflow on server is not checked.  Be aware of values approaching
+        2**32.  See L{decr}.
+
+        @param delta: Integer amount to increment by (should be zero or greater).
+        @return: New value after incrementing.
+        @rtype: int
+        """
+        return self._incrdecr("incr", key, delta)
+
+    def decr(self, key, delta=1):
+        """
+        Like L{incr}, but decrements.  Unlike L{incr}, underflow is checked and
+        new values are capped at 0.  If server value is 1, a decrement of 2
+        returns 0, not -1.
+
+        @param delta: Integer amount to decrement by (should be zero or greater).
+        @return: New value after decrementing.
+        @rtype: int
+        """
+        return self._incrdecr("decr", key, delta)
+
+    def _incrdecr(self, cmd, key, delta):
+        check_key(key)
+        server, key = self._get_server(key)
+        if not server:
+            return 0
+        self._statlog(cmd)
+        cmd = "%s %s %d" % (cmd, key, delta)
+        try:
+            server.send_cmd(cmd)
+            line = server.readline()
+            return int(line)
+        except socket.error, msg:
+            if type(msg) is types.TupleType: msg = msg[1]
+            server.mark_dead(msg)
+            return None
+
+    def add(self, key, val, time = 0, min_compress_len = 0):
+        '''
+        Add new key with value.
+
+        Like L{set}, but only stores in memcache if the key doesn't already exist.
+
+        @return: Nonzero on success.
+        @rtype: int
+        '''
+        return self._set("add", key, val, time, min_compress_len)
+
+    def append(self, key, val, time=0, min_compress_len=0):
+        '''Append the value to the end of the existing key's value.
+
+        Only stores in memcache if key already exists.
+        Also see L{prepend}.
+
+        @return: Nonzero on success.
+        @rtype: int
+        '''
+        return self._set("append", key, val, time, min_compress_len)
+
+    def prepend(self, key, val, time=0, min_compress_len=0):
+        '''Prepend the value to the beginning of the existing key's value.
+
+        Only stores in memcache if key already exists.
+        Also see L{append}.
+
+        @return: Nonzero on success.
+        @rtype: int
+        '''
+        return self._set("prepend", key, val, time, min_compress_len)
+
+    def replace(self, key, val, time=0, min_compress_len=0):
+        '''Replace existing key with value.
+
+        Like L{set}, but only stores in memcache if the key already exists.
+        The opposite of L{add}.
+
+        @return: Nonzero on success.
+        @rtype: int
+        '''
+        return self._set("replace", key, val, time, min_compress_len)
+
+    def set(self, key, val, time=0, min_compress_len=0, token=None):
+        '''Unconditionally sets a key to a given value in the memcache.
+
+        The C{key} can optionally be an tuple, with the first element
+        being the server hash value and the second being the key.
+        If you want to avoid making this module calculate a hash value.
+        You may prefer, for example, to keep all of a given user's objects
+        on the same memcache server, so you could use the user's unique
+        id as the hash value.
+
+        @return: Nonzero on success.
+        @rtype: int
+        @param time: Tells memcached the time which this value should expire, either
+        as a delta number of seconds, or an absolute unix time-since-the-epoch
+        value. See the memcached protocol docs section "Storage Commands"
+        for more info on <exptime>. We default to 0 == cache forever.
+        @param min_compress_len: The threshold length to kick in auto-compression
+        of the value using the zlib.compress() routine. If the value being cached is
+        a string, then the length of the string is measured, else if the value is an
+    , then the length of the pickle result is measured. If the resulting
+        attempt at compression yeilds a larger string than the input, then it is
+        discarded. For backwards compatability, this parameter defaults to 0,
+        indicating don't ever try to compress.
+        '''
+        return self._set("set", key, val, time, min_compress_len, token=token)
+
+
+    def _map_and_prefix_keys(self, key_iterable, key_prefix):
+        """Compute the mapping of server (_Host instance) -> list of keys to stuff onto that server, as well as the mapping of
+        prefixed key -> original key.
+
+
+        """
+        # Check it just once ...
+        key_extra_len=len(key_prefix)
+        if key_prefix:
+            check_key(key_prefix)
+
+        # server (_Host) -> list of unprefixed server keys in mapping
+        server_keys = {}
+
+        prefixed_to_orig_key = {}
+        # build up a list for each server of all the keys we want.
+        for orig_key in key_iterable:
+            if type(orig_key) is types.TupleType:
+                # Tuple of hashvalue, key ala _get_server(). Caller is essentially telling us what server to stuff this on.
+                # Ensure call to _get_server gets a Tuple as well.
+                str_orig_key = str(orig_key[1])
+                server, key = self._get_server((orig_key[0], key_prefix + str_orig_key)) # Gotta pre-mangle key before hashing to a server. Returns the mangled key.
+            else:
+                str_orig_key = str(orig_key) # set_multi supports int / long keys.
+                server, key = self._get_server(key_prefix + str_orig_key)
+
+            # Now check to make sure key length is proper ...
+            check_key(str_orig_key, key_extra_len=key_extra_len)
+
+            if not server:
+                continue
+
+            if not server_keys.has_key(server):
+                server_keys[server] = []
+            server_keys[server].append(key)
+            prefixed_to_orig_key[key] = orig_key
+
+        return (server_keys, prefixed_to_orig_key)
+
+    def set_multi(self, mapping, time=0, key_prefix='', min_compress_len=0):
+        '''
+        Sets multiple keys in the memcache doing just one query.
+
+        >>> notset_keys = mc.set_multi({'key1' : 'val1', 'key2' : 'val2'})
+        >>> mc.get_multi(['key1', 'key2']) == {'key1' : 'val1', 'key2' : 'val2'}
+        1
+
+
+        This method is recommended over regular L{set} as it lowers the number of
+        total packets flying around your network, reducing total latency, since
+        your app doesn't have to wait for each round-trip of L{set} before sending
+        the next one.
+
+        @param mapping: A dict of key/value pairs to set.
+        @param time: Tells memcached the time which this value should expire, either
+        as a delta number of seconds, or an absolute unix time-since-the-epoch
+        value. See the memcached protocol docs section "Storage Commands"
+        for more info on <exptime>. We default to 0 == cache forever.
+        @param key_prefix:  Optional string to prepend to each key when sending to memcache. Allows you to efficiently stuff these keys into a pseudo-namespace in memcache:
+            >>> notset_keys = mc.set_multi({'key1' : 'val1', 'key2' : 'val2'}, key_prefix='subspace_')
+            >>> len(notset_keys) == 0
+            True
+            >>> mc.get_multi(['subspace_key1', 'subspace_key2']) == {'subspace_key1' : 'val1', 'subspace_key2' : 'val2'}
+            True
+
+            Causes key 'subspace_key1' and 'subspace_key2' to be set. Useful in conjunction with a higher-level layer which applies namespaces to data in memcache.
+            In this case, the return result would be the list of notset original keys, prefix not applied.
+
+        @param min_compress_len: The threshold length to kick in auto-compression
+        of the value using the zlib.compress() routine. If the value being cached is
+        a string, then the length of the string is measured, else if the value is an
+        object, then the length of the pickle result is measured. If the resulting
+        attempt at compression yeilds a larger string than the input, then it is
+        discarded. For backwards compatability, this parameter defaults to 0,
+        indicating don't ever try to compress.
+        @return: List of keys which failed to be stored [ memcache out of memory, etc. ].
+        @rtype: list
+
+        '''
+
+        self._statlog('set_multi')
+
+
+
+        server_keys, prefixed_to_orig_key = self._map_and_prefix_keys(mapping.iterkeys(), key_prefix)
+
+        # send out all requests on each server before reading anything
+        dead_servers = []
+
+        for server in server_keys.iterkeys():
+            bigcmd = []
+            write = bigcmd.append
+            try:
+                for key in server_keys[server]: # These are mangled keys
+                    store_info = self._val_to_store_info(mapping[prefixed_to_orig_key[key]], min_compress_len)
+                    write("set %s %d %d %d\r\n%s\r\n" % (key, store_info[0], time, store_info[1], store_info[2]))
+                server.send_cmds(''.join(bigcmd))
+            except socket.error, msg:
+                if type(msg) is types.TupleType: msg = msg[1]
+                server.mark_dead(msg)
+                dead_servers.append(server)
+
+        # if any servers died on the way, don't expect them to respond.
+        for server in dead_servers:
+            del server_keys[server]
+
+        #  short-circuit if there are no servers, just return all keys
+        if not server_keys: return(mapping.keys())
+
+        notstored = [] # original keys.
+        for server, keys in server_keys.iteritems():
+            try:
+                for key in keys:
+                    line = server.readline()
+                    if line == 'STORED':
+                        continue
+                    else:
+                        notstored.append(prefixed_to_orig_key[key]) #un-mangle.
+            except (_Error, socket.error), msg:
+                if type(msg) is types.TupleType: msg = msg[1]
+                server.mark_dead(msg)
+        return notstored
+
+    def _val_to_store_info(self, val, min_compress_len):
+        """
+           Transform val to a storable representation, returning a tuple of the flags, the length of the new value, and the new value itself.
+        """
+        flags = 0
+        if isinstance(val, str):
+            pass
+        elif isinstance(val, int):
+            flags |= Client._FLAG_INTEGER
+            val = "%d" % val
+            # force no attempt to compress this silly string.
+            min_compress_len = 0
+        elif isinstance(val, long):
+            flags |= Client._FLAG_LONG
+            val = "%d" % val
+            # force no attempt to compress this silly string.
+            min_compress_len = 0
+        else:
+            flags |= Client._FLAG_PICKLE
+            file = StringIO()
+            if self.picklerIsKeyword:
+                pickler = self.pickler(file, protocol = self.pickleProtocol)
+            else:
+                pickler = self.pickler(file, self.pickleProtocol)
+            if self.persistent_id:
+                pickler.persistent_id = self.persistent_id
+            pickler.dump(val)
+            val = file.getvalue()
+
+        lv = len(val)
+        # We should try to compress if min_compress_len > 0 and we could
+        # import zlib and this string is longer than our min threshold.
+        if min_compress_len and _supports_compress and lv > min_compress_len:
+            comp_val = compress(val)
+            # Only retain the result if the compression result is smaller
+            # than the original.
+            if len(comp_val) < lv:
+                flags |= Client._FLAG_COMPRESSED
+                val = comp_val
+
+        #  silently do not store if value length exceeds maximum
+        if len(val) >= SERVER_MAX_VALUE_LENGTH: return(0)
+
+        return (flags, len(val), val)
+
+    def _set(self, cmd, key, val, time, min_compress_len = 0, token=None):
+        check_key(key)
+        server, key = self._get_server(key)
+        if not server:
+            return 0
+
+        self._statlog(cmd)
+
+        store_info = self._val_to_store_info(val, min_compress_len)
+        if not store_info: return(0)
+
+        if token is not None:
+            cmd = "cas"
+            fullcmd = "cas %s %d %d %d %s\r\n%s" % (key, store_info[0], time, store_info[1], token, store_info[2])
+        else:
+            fullcmd = "%s %s %d %d %d\r\n%s" % (cmd, key, store_info[0], time, store_info[1], store_info[2])
+        try:
+            server.send_cmd(fullcmd)
+            result = server.expect("STORED")
+
+            if (result == "STORED"):
+                return True
+
+            if (result == "NOT_FOUND"):
+                raise NotFoundError(key)
+
+            if token and result == "EXISTS":
+                log.debug("Memcacheclient check-and-set failed")
+                raise TokenMismatchError(key)
+
+            log.error("Memcacheclient %s command failed with result (%s)" %
+                (cmd, result))
+
+            return False
+
+        except socket.error, msg:
+            if type(msg) is types.TupleType: msg = msg[1]
+            server.mark_dead(msg)
+        return 0
+
+    def get(self, key):
+        '''Retrieves a key from the memcache.
+
+        @return: The value or None.
+        '''
+        check_key(key)
+        server, key = self._get_server(key)
+        if not server:
+            raise MemcacheError("Memcache connection error")
+
+        self._statlog('get')
+
+        try:
+            server.send_cmd("get %s" % key)
+            rkey, flags, rlen, = self._expectvalue(server)
+            if not rkey:
+                return None
+            value = self._recv_value(server, flags, rlen)
+            server.expect("END")
+        except (_Error, socket.error), msg:
+            if type(msg) is types.TupleType: msg = msg[1]
+            server.mark_dead(msg)
+            raise MemcacheError("Memcache connection error")
+        return value
+
+    def gets(self, key):
+        '''Retrieves a key from the memcache.
+
+        @return: The value or None.
+        '''
+        check_key(key)
+        server, key = self._get_server(key)
+        if not server:
+            raise MemcacheError("Memcache connection error")
+
+        self._statlog('get')
+
+        try:
+            server.send_cmd("gets %s" % key)
+            rkey, flags, rlen, cas_token = self._expectvalue_cas(server)
+            if not rkey:
+                return (None, None)
+            value = self._recv_value(server, flags, rlen)
+            server.expect("END")
+        except (_Error, socket.error), msg:
+            if type(msg) is types.TupleType: msg = msg[1]
+            server.mark_dead(msg)
+            raise MemcacheError("Memcache connection error")
+        return (value, cas_token)
+
+    def get_multi(self, keys, key_prefix=''):
+        '''
+        Retrieves multiple keys from the memcache doing just one query.
+
+        >>> success = mc.set("foo", "bar")
+        >>> success = mc.set("baz", 42)
+        >>> mc.get_multi(["foo", "baz", "foobar"]) == {"foo": "bar", "baz": 42}
+        1
+        >>> mc.set_multi({'k1' : 1, 'k2' : 2}, key_prefix='pfx_') == []
+        1
+
+        This looks up keys 'pfx_k1', 'pfx_k2', ... . Returned dict will just have unprefixed keys 'k1', 'k2'.
+        >>> mc.get_multi(['k1', 'k2', 'nonexist'], key_prefix='pfx_') == {'k1' : 1, 'k2' : 2}
+        1
+
+        get_mult [ and L{set_multi} ] can take str()-ables like ints / longs as keys too. Such as your db pri key fields.
+        They're rotored through str() before being passed off to memcache, with or without the use of a key_prefix.
+        In this mode, the key_prefix could be a table name, and the key itself a db primary key number.
+
+        >>> mc.set_multi({42: 'douglass adams', 46 : 'and 2 just ahead of me'}, key_prefix='numkeys_') == []
+        1
+        >>> mc.get_multi([46, 42], key_prefix='numkeys_') == {42: 'douglass adams', 46 : 'and 2 just ahead of me'}
+        1
+
+        This method is recommended over regular L{get} as it lowers the number of
+        total packets flying around your network, reducing total latency, since
+        your app doesn't have to wait for each round-trip of L{get} before sending
+        the next one.
+
+        See also L{set_multi}.
+
+        @param keys: An array of keys.
+        @param key_prefix: A string to prefix each key when we communicate with memcache.
+            Facilitates pseudo-namespaces within memcache. Returned dictionary keys will not have this prefix.
+        @return:  A dictionary of key/value pairs that were available. If key_prefix was provided, the keys in the retured dictionary will not have it present.
+
+        '''
+
+        self._statlog('get_multi')
+
+        server_keys, prefixed_to_orig_key = self._map_and_prefix_keys(keys, key_prefix)
+
+        # send out all requests on each server before reading anything
+        dead_servers = []
+        for server in server_keys.iterkeys():
+            try:
+                server.send_cmd("get %s" % " ".join(server_keys[server]))
+            except socket.error, msg:
+                if type(msg) is types.TupleType: msg = msg[1]
+                server.mark_dead(msg)
+                dead_servers.append(server)
+
+        # if any servers died on the way, don't expect them to respond.
+        for server in dead_servers:
+            del server_keys[server]
+
+        retvals = {}
+        for server in server_keys.iterkeys():
+            try:
+                line = server.readline()
+                while line and line != 'END':
+                    rkey, flags, rlen = self._expectvalue(server, line)
+                    #  Bo Yang reports that this can sometimes be None
+                    if rkey is not None:
+                        val = self._recv_value(server, flags, rlen)
+                        try:
+                            retvals[prefixed_to_orig_key[rkey]] = val   # un-prefix returned key.
+                        except KeyError:
+                            pass
+                    line = server.readline()
+            except (_Error, socket.error), msg:
+                if type(msg) is types.TupleType: msg = msg[1]
+                server.mark_dead(msg)
+        return retvals
+
+    def gets_multi(self, keys, key_prefix=''):
+        '''
+        Retrieves multiple keys from the memcache doing just one query.
+        See also L{gets} and L{get_multi}.
+        '''
+
+        self._statlog('gets_multi')
+
+        server_keys, prefixed_to_orig_key = self._map_and_prefix_keys(keys, key_prefix)
+
+        # send out all requests on each server before reading anything
+        dead_servers = []
+        for server in server_keys.iterkeys():
+            try:
+                server.send_cmd("gets %s" % " ".join(server_keys[server]))
+            except socket.error, msg:
+                if type(msg) is types.TupleType: msg = msg[1]
+                server.mark_dead(msg)
+                dead_servers.append(server)
+
+        # if any servers died on the way, don't expect them to respond.
+        for server in dead_servers:
+            del server_keys[server]
+
+        retvals = {}
+        for server in server_keys.iterkeys():
+            try:
+                line = server.readline()
+                while line and line != 'END':
+                    rkey, flags, rlen, cas_token = self._expectvalue_cas(server, line)
+                    #  Bo Yang reports that this can sometimes be None
+                    if rkey is not None:
+                        val = self._recv_value(server, flags, rlen)
+                        try:
+                            retvals[prefixed_to_orig_key[rkey]] = (val, cas_token)   # un-prefix returned key.
+                        except KeyError:
+                            pass
+                    line = server.readline()
+            except (_Error, socket.error), msg:
+                if type(msg) is types.TupleType: msg = msg[1]
+                server.mark_dead(msg)
+        return retvals
+
+    def _expectvalue(self, server, line=None):
+        if not line:
+            line = server.readline()
+
+        if line[:5] == 'VALUE':
+            resp, rkey, flags, len = line.split()
+            flags = int(flags)
+            rlen = int(len)
+            return (rkey, flags, rlen)
+        else:
+            return (None, None, None)
+
+    def _expectvalue_cas(self, server, line=None):
+        if not line:
+            line = server.readline()
+
+        if line[:5] == 'VALUE':
+            resp, rkey, flags, len, rtoken = line.split()
+            flags = int(flags)
+            rlen = int(len)
+            return (rkey, flags, rlen, rtoken)
+        else:
+            return (None, None, None, None)
+
+    def _recv_value(self, server, flags, rlen):
+        rlen += 2 # include \r\n
+        buf = server.recv(rlen)
+        if len(buf) != rlen:
+            raise _Error("received %d bytes when expecting %d" % (len(buf), rlen))
+
+        if len(buf) == rlen:
+            buf = buf[:-2]  # strip \r\n
+
+        if flags & Client._FLAG_COMPRESSED:
+            buf = decompress(buf)
+
+
+        if  flags == 0 or flags == Client._FLAG_COMPRESSED:
+            # Either a bare string or a compressed string now decompressed...
+            val = buf
+        elif flags & Client._FLAG_INTEGER:
+            val = int(buf)
+        elif flags & Client._FLAG_LONG:
+            val = long(buf)
+        elif flags & Client._FLAG_PICKLE:
+            try:
+                file = StringIO(buf)
+                unpickler = self.unpickler(file)
+                if self.persistent_load:
+                    unpickler.persistent_load = self.persistent_load
+                val = unpickler.load()
+            except Exception, e:
+                self.debuglog('Pickle error: %s\n' % e)
+                val = None
+        else:
+            self.debuglog("unknown flags on get: %x\n" % flags)
+
+        return val
+
+
+
+class TestClient(Client):
+    """
+    Fake memcache client for unit tests
+
+    """
+
+    def __init__(self, servers, debug=0, pickleProtocol=0,
+                 pickler=pickle.Pickler, unpickler=pickle.Unpickler,
+                 pload=None, pid=None):
+
+        local.__init__(self)
+
+        super(TestClient, self).__init__(servers, debug=debug,
+            pickleProtocol=pickleProtocol, pickler=pickler, unpickler=unpickler,
+            pload=pload, pid=pid)
+
+        self.data = {}
+        self.token = 0
+
+
+
+    def get_stats(self):
+        raise NotImplementedError()
+
+    def get_slabs(self):
+        raise NotImplementedError()
+
+    def flush_all(self):
+        raise NotImplementedError()
+
+    def forget_dead_hosts(self):
+        raise NotImplementedError()
+
+    def delete_multi(self, keys, time=0, key_prefix=''):
+        '''
+        Delete multiple keys in the memcache doing just one query.
+
+        >>> notset_keys = mc.set_multi({'key1' : 'val1', 'key2' : 'val2'})
+        >>> mc.get_multi(['key1', 'key2']) == {'key1' : 'val1', 'key2' : 'val2'}
+        1
+        >>> mc.delete_multi(['key1', 'key2'])
+        1
+        >>> mc.get_multi(['key1', 'key2']) == {}
+        1
+        '''
+
+        self._statlog('delete_multi')
+        for key in keys:
+            key = key_prefix + key
+            del self.data[key]
+        return 1
+
+    def delete(self, key, time=0):
+        '''Deletes a key from the memcache.
+
+        @return: Nonzero on success.
+        @param time: number of seconds any subsequent set / update commands should fail. Defaults to 0 for no delay.
+        @rtype: int
+        '''
+        check_key(key)
+        del self.data[key]
+        return 1
+
+
+    def incr(self, key, delta=1):
+        raise NotImplementedError()
+
+    def decr(self, key, delta=1):
+        raise NotImplementedError()
+
+    def add(self, key, val, time = 0, min_compress_len = 0):
+        raise NotImplementedError()
+
+    def append(self, key, val, time=0, min_compress_len=0):
+        raise NotImplementedError()
+
+    def prepend(self, key, val, time=0, min_compress_len=0):
+        raise NotImplementedError()
+
+    def replace(self, key, val, time=0, min_compress_len=0):
+        raise NotImplementedError()
+
+    def set(self, key, val, time=0, min_compress_len=0, token=None):
+        self._statlog('set')
+        return self._set("set", key, val, time, min_compress_len, token=token)
+
+    def set_multi(self, mapping, time=0, key_prefix='', min_compress_len=0):
+        self._statlog('set_multi')
+        for key, val in mapping.iteritems():
+            key = key_prefix + key
+            self._set("set", key, val, time, min_compress_len)
+        return []
+
+    def _set(self, cmd, key, val, time, min_compress_len = 0, token=None):
+        check_key(key)
+        self._statlog(cmd)
+
+        serialized = pickle.dumps(val, pickle.HIGHEST_PROTOCOL)
+
+        if token is not None:
+            if self.data.has_key(key):
+                stored_val, stored_token = self.data[key]
+                if token != stored_token:
+                    raise TokenMismatchError(key)
+
+        self.data[key] = (serialized, str(self.token))
+        self.token += 1
+
+        return True
+
+    def get(self, key):
+        check_key(key)
+
+        self._statlog('get')
+        if self.data.has_key(key):
+            stored_val, stored_token = self.data[key]
+            val = pickle.loads(stored_val)
+            return val
+        return None
+
+
+    def gets(self, key):
+        check_key(key)
+        if self.data.has_key(key):
+            stored_val, stored_token = self.data[key]
+            val = pickle.loads(stored_val)
+            return (val, stored_token)
+        return (None, None)
+
+    def get_multi(self, keys, key_prefix=''):
+        self._statlog('get_multi')
+
+        results = {}
+        for key in keys:
+            key = key_prefix + key
+            val = self.get(key)
+            results[key] = val
+        return results
+
+    def gets_multi(self, keys, key_prefix=''):
+        self._statlog('gets_multi')
+        results = {}
+        for key in keys:
+            key = key_prefix + key
+            result = self.gets(key)
+            if result[1] is not None:
+                results[key] = result
+        return results
+
+
+class _Host:
+    _DEAD_RETRY = 1  # number of seconds before retrying a dead server.
+    _SOCKET_TIMEOUT = 3  #  number of seconds before sockets timeout.
+
+    def __init__(self, host, debugfunc=None):
+        if isinstance(host, types.TupleType):
+            host, self.weight = host
+        else:
+            self.weight = 1
+
+        #  parse the connection string
+        m = re.match(r'^(?P<proto>unix):(?P<path>.*)$', host)
+        if not m:
+            m = re.match(r'^(?P<proto>inet):'
+                    r'(?P<host>[^:]+)(:(?P<port>[0-9]+))?$', host)
+        if not m: m = re.match(r'^(?P<host>[^:]+):(?P<port>[0-9]+)$', host)
+        if not m:
+            raise ValueError('Unable to parse connection string: "%s"' % host)
+
+        hostData = m.groupdict()
+        if hostData.get('proto') == 'unix':
+            self.family = socket.AF_UNIX
+            self.address = hostData['path']
+        else:
+            self.family = socket.AF_INET
+            self.ip = hostData['host']
+            self.port = int(hostData.get('port', 11211))
+            self.address = ( self.ip, self.port )
+
+        if not debugfunc:
+            debugfunc = lambda x: x
+        self.debuglog = debugfunc
+
+        self.deaduntil = 0
+        self.socket = None
+
+        self.buffer = ''
+
+    def _check_dead(self):
+        if self.deaduntil and self.deaduntil > time.time():
+            return 1
+        self.deaduntil = 0
+        return 0
+
+    def connect(self):
+        if self._get_socket():
+            return 1
+        return 0
+
+    def mark_dead(self, reason):
+        log.error("Memcacheclient socket marked dead (%s)" % (reason,))
+        self.debuglog("MemCache: %s: %s.  Marking dead." % (self, reason))
+        self.deaduntil = time.time() + _Host._DEAD_RETRY
+        self.close_socket()
+
+    def _get_socket(self):
+        if self._check_dead():
+            log.error("Memcacheclient _get_socket() found dead socket")
+            return None
+        if self.socket:
+            return self.socket
+        s = socket.socket(self.family, socket.SOCK_STREAM)
+        if hasattr(s, 'settimeout'): s.settimeout(self._SOCKET_TIMEOUT)
+        try:
+            s.connect(self.address)
+        except socket.timeout, msg:
+            log.error("Memcacheclient _get_socket() connection timed out (%s)" %
+                (msg,))
+            self.mark_dead("connect: %s" % msg)
+            return None
+        except socket.error, msg:
+            if type(msg) is types.TupleType: msg = msg[1]
+            log.error("Memcacheclient _get_socket() connection error (%s)" %
+                (msg,))
+            self.mark_dead("connect: %s" % msg[1])
+            return None
+        self.socket = s
+        self.buffer = ''
+        return s
+
+    def close_socket(self):
+        if self.socket:
+            self.socket.close()
+            self.socket = None
+
+    def send_cmd(self, cmd):
+        self.socket.sendall(cmd + '\r\n')
+
+    def send_cmds(self, cmds):
+        """ cmds already has trailing \r\n's applied """
+        self.socket.sendall(cmds)
+
+    def readline(self):
+        buf = self.buffer
+        recv = self.socket.recv
+        while True:
+            index = buf.find('\r\n')
+            if index >= 0:
+                break
+            data = recv(4096)
+            if not data:
+                self.mark_dead('Connection closed while reading from %s'
+                        % repr(self))
+                break
+            buf += data
+        if index >= 0:
+            self.buffer = buf[index+2:]
+            buf = buf[:index]
+        else:
+            self.buffer = ''
+        return buf
+
+    def expect(self, text):
+        line = self.readline()
+        if line != text:
+            self.debuglog("while expecting '%s', got unexpected response '%s'" % (text, line))
+        return line
+
+    def recv(self, rlen):
+        self_socket_recv = self.socket.recv
+        buf = self.buffer
+        while len(buf) < rlen:
+            foo = self_socket_recv(4096)
+            buf += foo
+            if len(foo) == 0:
+                raise _Error, ( 'Read %d bytes, expecting %d, '
+                        'read returned 0 length bytes' % ( len(buf), rlen ))
+        self.buffer = buf[rlen:]
+        return buf[:rlen]
+
+    def __str__(self):
+        d = ''
+        if self.deaduntil:
+            d = " (dead until %d)" % self.deaduntil
+
+        if self.family == socket.AF_INET:
+            return "inet:%s:%d%s" % (self.address[0], self.address[1], d)
+        else:
+            return "unix:%s%s" % (self.address, d)
+
+def check_key(key, key_extra_len=0):
+    """Checks sanity of key.  Fails if:
+        Key length is > SERVER_MAX_KEY_LENGTH (Raises MemcachedKeyLength).
+        Contains control characters  (Raises MemcachedKeyCharacterError).
+        Is not a string (Raises MemcachedStringEncodingError)
+        Is an unicode string (Raises MemcachedStringEncodingError)
+        Is not a string (Raises MemcachedKeyError)
+        Is None (Raises MemcachedKeyError)
+    """
+
+    return # Short-circuit this expensive method
+
+    if type(key) == types.TupleType: key = key[1]
+    if not key:
+        raise Client.MemcachedKeyNoneError, ("Key is None")
+    if isinstance(key, unicode):
+        raise Client.MemcachedStringEncodingError, ("Keys must be str()'s, not "
+                "unicode.  Convert your unicode strings using "
+                "mystring.encode(charset)!")
+    if not isinstance(key, str):
+        raise Client.MemcachedKeyTypeError, ("Key must be str()'s")
+
+    if isinstance(key, basestring):
+        if len(key) + key_extra_len > SERVER_MAX_KEY_LENGTH:
+             raise Client.MemcachedKeyLengthError, ("Key length is > %s"
+                     % SERVER_MAX_KEY_LENGTH)
+        for char in key:
+            if ord(char) < 32 or ord(char) == 127:
+                raise Client.MemcachedKeyCharacterError, "Control characters not allowed"
+
+def _doctest():
+    import doctest, memcacheclient
+    servers = ["127.0.0.1:11211"]
+    mc = Client(servers, debug=1)
+    globs = {"mc": mc}
+    return doctest.testmod(memcacheclient, globs=globs)
+
+if __name__ == "__main__":
+    print("Testing docstrings...")
+    _doctest()
+    print("Running tests:")
+    print
+    serverList = [["127.0.0.1:11211"]]
+    if '--do-unix' in sys.argv:
+        serverList.append([os.path.join(os.getcwd(), 'memcached.socket')])
+
+    for servers in serverList:
+        mc = Client(servers, debug=1)
+
+        def to_s(val):
+            if not isinstance(val, types.StringTypes):
+                return "%s (%s)" % (val, type(val))
+            return "%s" % val
+        def test_setget(key, val):
+            print("Testing set/get {'%s': %s} ..." % (to_s(key), to_s(val)), end="")
+            mc.set(key, val)
+            newval = mc.get(key)
+            if newval == val:
+                print("OK")
+                return 1
+            else:
+                print("FAIL")
+                return 0
+
+
+        class FooStruct:
+            def __init__(self):
+                self.bar = "baz"
+            def __str__(self):
+                return "A FooStruct"
+            def __eq__(self, other):
+                if isinstance(other, FooStruct):
+                    return self.bar == other.bar
+                return 0
+
+        test_setget("a_string", "some random string")
+        test_setget("an_integer", 42)
+        if test_setget("long", long(1<<30)):
+            print("Testing delete ...", end="")
+            if mc.delete("long"):
+                print("OK")
+            else:
+                print("FAIL")
+        print("Testing get_multi ...", end="")
+        print(mc.get_multi(["a_string", "an_integer"]))
+
+        print("Testing get(unknown value) ...", end="")
+        print(to_s(mc.get("unknown_value")))
+
+        f = FooStruct()
+        test_setget("foostruct", f)
+
+        print("Testing incr ...", end="")
+        x = mc.incr("an_integer", 1)
+        if x == 43:
+            print("OK")
+        else:
+            print("FAIL")
+
+        print("Testing decr ...", end="")
+        x = mc.decr("an_integer", 1)
+        if x == 42:
+            print("OK")
+        else:
+            print("FAIL")
+
+        # sanity tests
+        print("Testing sending spaces...", end="")
+        try:
+            x = mc.set("this has spaces", 1)
+        except Client.MemcachedKeyCharacterError, msg:
+            print("OK")
+        else:
+            print("FAIL")
+
+        print("Testing sending control characters...", end="")
+        try:
+            x = mc.set("this\x10has\x11control characters\x02", 1)
+        except Client.MemcachedKeyCharacterError, msg:
+            print("OK")
+        else:
+            print("FAIL")
+
+        print("Testing using insanely long key...", end="")
+        try:
+            x = mc.set('a'*SERVER_MAX_KEY_LENGTH + 'aaaa', 1)
+        except Client.MemcachedKeyLengthError, msg:
+            print("OK")
+        else:
+            print("FAIL")
+
+        print("Testing sending a unicode-string key...", end="")
+        try:
+            x = mc.set(u'keyhere', 1)
+        except Client.MemcachedStringEncodingError, msg:
+            print("OK", end="")
+        else:
+            print("FAIL", end="")
+        try:
+            x = mc.set((u'a'*SERVER_MAX_KEY_LENGTH).encode('utf-8'), 1)
+        except:
+            print("FAIL", end="")
+        else:
+            print("OK", end="")
+        import pickle
+        s = pickle.loads('V\\u4f1a\np0\n.')
+        try:
+            x = mc.set((s*SERVER_MAX_KEY_LENGTH).encode('utf-8'), 1)
+        except Client.MemcachedKeyLengthError:
+            print("OK")
+        else:
+            print("FAIL")
+
+        print("Testing using a value larger than the memcached value limit...", end="")
+        x = mc.set('keyhere', 'a'*SERVER_MAX_VALUE_LENGTH)
+        if mc.get('keyhere') == None:
+            print("OK", end="")
+        else:
+            print("FAIL", end="")
+        x = mc.set('keyhere', 'a'*SERVER_MAX_VALUE_LENGTH + 'aaa')
+        if mc.get('keyhere') == None:
+            print("OK")
+        else:
+            print("FAIL")
+
+        print("Testing set_multi() with no memcacheds running", end="")
+        mc.disconnect_all()
+        errors = mc.set_multi({'keyhere' : 'a', 'keythere' : 'b'})
+        if errors != []:
+            print("FAIL")
+        else:
+            print("OK")
+
+        print("Testing delete_multi() with no memcacheds running", end="")
+        mc.disconnect_all()
+        ret = mc.delete_multi({'keyhere' : 'a', 'keythere' : 'b'})
+        if ret != 1:
+            print("FAIL")
+        else:
+          print("OK")
+
+# vim: ts=4 sw=4 et :

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcachepool.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcachepool.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcachepool.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -18,13 +18,14 @@
 
 from twisted.internet.defer import Deferred, fail
 from twisted.internet.protocol import ReconnectingClientFactory
+from twisted.protocols.memcache import MemCacheProtocol, NoSuchCommand
 
+from twext.python.log import Logger
 from twext.internet.gaiendpoint import GAIEndpoint
 from twext.internet.adaptendpoint import connect
 
-from twext.python.log import Logger
-from twext.protocols.memcache import MemCacheProtocol, NoSuchCommand
 
+
 class PooledMemCacheProtocol(MemCacheProtocol):
     """
     A MemCacheProtocol that will notify a connectionPool that it is ready
@@ -161,7 +162,9 @@
 
         self.shutdown_deferred = None
         self.shutdown_requested = False
-        reactor.addSystemEventTrigger('before', 'shutdown', self._shutdownCallback)
+        reactor.addSystemEventTrigger(
+            'before', 'shutdown', self._shutdownCallback
+        )
 
         self._busyClients = set([])
         self._freeClients = set([])
@@ -191,8 +194,9 @@
 
         @return: A L{Deferred} that fires with the L{IProtocol} instance.
         """
-        self.log.debug("Initiating new client connection to: %r" % (
-                self._endpoint,))
+        self.log.debug(
+            "Initiating new client connection to: %r" % (self._endpoint,)
+        )
         self._logClientStats()
 
         self._pendingConnects += 1
@@ -239,9 +243,12 @@
             Upon memcache error, log the failed request along with the error
             message and free the client.
             """
-            self.log.error("Memcache error: %s; request: %s %s" %
-                (failure.value, command,
-                " ".join(args)[:self.REQUEST_LOGGING_SIZE],))
+            self.log.error(
+                "Memcache error: %s; request: %s %s" % (
+                    failure.value, command,
+                    " ".join(args)[:self.REQUEST_LOGGING_SIZE],
+                )
+            )
             self.clientFree(client)
 
         self.clientBusy(client)
@@ -276,11 +283,14 @@
             d = self._performRequestOnClient(
                 client, command, *args, **kwargs)
 
-        elif len(self._busyClients) + self._pendingConnects >= self._maxClients:
+        elif (
+            len(self._busyClients) + self._pendingConnects >= self._maxClients
+        ):
             d = Deferred()
             self._commands.append((d, command, args, kwargs))
-            self.log.debug("Command queued: %s, %r, %r" % (
-                    command, args, kwargs))
+            self.log.debug(
+                "Command queued: %s, %r, %r" % (command, args, kwargs)
+            )
             self._logClientStats()
 
         else:
@@ -292,12 +302,14 @@
 
 
     def _logClientStats(self):
-        self.log.debug("Clients #free: %d, #busy: %d, "
-                       "#pending: %d, #queued: %d" % (
+        self.log.debug(
+            "Clients #free: %d, #busy: %d, #pending: %d, #queued: %d" % (
                 len(self._freeClients),
                 len(self._busyClients),
                 self._pendingConnects,
-                len(self._commands)))
+                len(self._commands),
+            )
+        )
 
 
     def clientGone(self, client):
@@ -349,8 +361,10 @@
         if len(self._commands) > 0:
             d, command, args, kwargs = self._commands.pop(0)
 
-            self.log.debug("Performing Queued Command: %s, %r, %r" % (
-                    command, args, kwargs))
+            self.log.debug(
+                "Performing Queued Command: %s, %r, %r"
+                % (command, args, kwargs)
+            )
             self._logClientStats()
 
             _ign_d = self.performRequest(
@@ -425,6 +439,8 @@
 _memCachePools = {}         # Maps a name to a pool object
 _memCachePoolHandler = {}   # Maps a handler id to a named pool
 
+
+
 def installPools(pools, maxClients=5, reactor=None):
     if reactor is None:
         from twisted.internet import reactor
@@ -440,7 +456,9 @@
 
 
 
-def _installPool(name, handleTypes, serverEndpoint, maxClients=5, reactor=None):
+def _installPool(
+    name, handleTypes, serverEndpoint, maxClients=5, reactor=None
+):
     pool = MemCachePool(serverEndpoint, maxClients=maxClients, reactor=None)
     _memCachePools[name] = pool
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcacheprops.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcacheprops.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/memcacheprops.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -33,14 +33,15 @@
     from md5 import new as md5
 
 from twext.python.log import Logger
-from twext.python.memcacheclient import ClientFactory
-from twext.python.memcacheclient import MemcacheError, TokenMismatchError
 from twext.python.filepath import CachingFilePath as FilePath
+from txweb2 import responsecode
+from txweb2.http import HTTPError, StatusResponse
+
 from txdav.xml.base import encodeXMLName
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError, StatusResponse
 
 from twistedcaldav.config import config
+from twistedcaldav.memcacheclient import ClientFactory
+from twistedcaldav.memcacheclient import MemcacheError, TokenMismatchError
 
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/acl.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/acl.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/acl.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -22,9 +22,9 @@
 
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.dav.util import parentForURL
-from twext.web2.http import HTTPError
+from txweb2 import responsecode
+from txweb2.dav.util import parentForURL
+from txweb2.http import HTTPError
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/get.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/get.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/get.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -21,14 +21,14 @@
 __all__ = ["http_GET"]
 
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
-from twext.web2.dav.http import ErrorResponse
-from twext.web2.dav.util import parentForURL
-from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.http import Response
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import MemoryStream
+from txweb2.dav.http import ErrorResponse
+from txweb2.dav.util import parentForURL
+from txweb2.http import HTTPError, StatusResponse
+from txweb2.http import Response
+from txweb2.http_headers import MimeType
+from txweb2.stream import MemoryStream
 
 from twistedcaldav.config import config
 from twistedcaldav.customxml import calendarserver_namespace

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/mkcalendar.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/mkcalendar.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/mkcalendar.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -23,15 +23,15 @@
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python.failure import Failure
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
-from twext.web2.dav.http import MultiStatusResponse, PropertyStatusResponseQueue
-from twext.web2.dav.util import davXMLFromStream
-from twext.web2.dav.util import parentForURL
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2.dav.http import MultiStatusResponse, PropertyStatusResponseQueue
+from txweb2.dav.util import davXMLFromStream
+from txweb2.dav.util import parentForURL
+from txweb2.http import HTTPError, StatusResponse
 
 from twext.python.log import Logger
-from twext.web2.dav.http import ErrorResponse
+from txweb2.dav.http import ErrorResponse
 
 from twistedcaldav import caldavxml
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/mkcol.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/mkcol.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/mkcol.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -25,14 +25,14 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
-from twext.web2.http import Response
-from twext.web2.dav.http import ErrorResponse, PropertyStatusResponseQueue
-from twext.web2.dav.util import davXMLFromStream
-from twext.web2.dav.util import parentForURL
-from twext.web2.http import HTTPError
-from twext.web2.http import StatusResponse
+from txweb2.http import Response
+from txweb2.dav.http import ErrorResponse, PropertyStatusResponseQueue
+from txweb2.dav.util import davXMLFromStream
+from txweb2.dav.util import parentForURL
+from txweb2.http import HTTPError
+from txweb2.http import StatusResponse
 
 from twistedcaldav import caldavxml, carddavxml, mkcolxml
 from twistedcaldav.config import config
@@ -100,7 +100,7 @@
         doc = (yield davXMLFromStream(request.stream))
     except ValueError, e:
         log.error("Error while handling MKCOL: %s" % (e,))
-        # TODO: twext.web2.dav 'MKCOL' tests demand this particular response
+        # TODO: txweb2.dav 'MKCOL' tests demand this particular response
         # code, but should we really be looking at the XML content or the
         # content-type header?  It seems to me like this ought to be considered
         # a BAD_REQUEST if it claims to be XML but isn't, but an

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/post.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/post.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/post.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -21,8 +21,8 @@
 
 __all__ = ["http_POST"]
 
-from twext.web2 import responsecode
-from twext.web2.http import StatusResponse
+from txweb2 import responsecode
+from txweb2.http import StatusResponse
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/propfind.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/propfind.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/propfind.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -1,4 +1,4 @@
-# -*- test-case-name: twext.web2.dav.test.test_prop.PROP.test_PROPFIND -*-
+# -*- test-case-name: txweb2.dav.test.test_prop.PROP.test_PROPFIND -*-
 ##
 # Copyright (c) 2005-2013 Apple Computer, Inc. All rights reserved.
 #
@@ -29,13 +29,13 @@
 
 from twisted.python.failure import Failure
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twext.web2.http import HTTPError
-from twext.web2 import responsecode
-from twext.web2.http import StatusResponse
+from txweb2.http import HTTPError
+from txweb2 import responsecode
+from txweb2.http import StatusResponse
 from txdav.xml import element as davxml
-from twext.web2.dav.http import MultiStatusResponse, statusForFailure, \
+from txweb2.dav.http import MultiStatusResponse, statusForFailure, \
     ErrorResponse
-from twext.web2.dav.util import normalizeURL, davXMLFromStream, parentForURL
+from txweb2.dav.util import normalizeURL, davXMLFromStream, parentForURL
 
 from twext.python.log import Logger
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -29,15 +29,15 @@
 import string
 
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.dav.util import davXMLFromStream
+from txweb2 import responsecode
+from txweb2.http import HTTPError, StatusResponse
+from txweb2.dav.util import davXMLFromStream
 from txdav.xml import element as davxml
 from txdav.xml.base import encodeXMLName
 from txdav.xml.element import lookupElement
 
 from twext.python.log import Logger
-from twext.web2.dav.http import ErrorResponse
+from txweb2.dav.http import ErrorResponse
 
 from twistedcaldav import caldavxml
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_addressbook_query.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_addressbook_query.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_addressbook_query.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -26,12 +26,12 @@
 from twisted.internet.defer import inlineCallbacks, returnValue, maybeDeferred
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
-from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
-from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
-from twext.web2.dav.util import joinURL
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2.dav.http import ErrorResponse, MultiStatusResponse
+from txweb2.dav.method.report import NumberOfMatchesWithinLimits
+from txweb2.dav.util import joinURL
+from txweb2.http import HTTPError, StatusResponse
 
 from twistedcaldav import carddavxml
 from twistedcaldav.config import config

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_calendar_query.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_calendar_query.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_calendar_query.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -24,12 +24,12 @@
     maybeDeferred
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.dav.http import MultiStatusResponse
-from twext.web2.dav.http import ErrorResponse
-from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
-from twext.web2.dav.util import joinURL
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2 import responsecode
+from txweb2.dav.http import MultiStatusResponse
+from txweb2.dav.http import ErrorResponse
+from txweb2.dav.method.report import NumberOfMatchesWithinLimits
+from txweb2.dav.util import joinURL
+from txweb2.http import HTTPError, StatusResponse
 
 from twistedcaldav import caldavxml
 from twistedcaldav.caldavxml import caldav_namespace, MaxInstances, \

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_common.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_common.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_common.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -38,15 +38,15 @@
 
 from twisted.internet.defer import inlineCallbacks, returnValue, maybeDeferred
 from twisted.python.failure import Failure
-from twext.web2 import responsecode
+from txweb2 import responsecode
 
 from txdav.xml import element
-from twext.web2.dav.http import statusForFailure
-from twext.web2.dav.method.propfind import propertyName
-from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
-from twext.web2.dav.method.report import max_number_of_matches
-from twext.web2.dav.resource import AccessDeniedError
-from twext.web2.http import HTTPError
+from txweb2.dav.http import statusForFailure
+from txweb2.dav.method.propfind import propertyName
+from txweb2.dav.method.report import NumberOfMatchesWithinLimits
+from txweb2.dav.method.report import max_number_of_matches
+from txweb2.dav.resource import AccessDeniedError
+from txweb2.http import HTTPError
 
 from twext.python.log import Logger
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_freebusy.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_freebusy.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_freebusy.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -23,12 +23,12 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.dav.http import ErrorResponse
-from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
-from twext.web2.http import HTTPError, Response, StatusResponse
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import MemoryStream
+from txweb2 import responsecode
+from txweb2.dav.http import ErrorResponse
+from txweb2.dav.method.report import NumberOfMatchesWithinLimits
+from txweb2.http import HTTPError, Response, StatusResponse
+from txweb2.http_headers import MimeType
+from txweb2.stream import MemoryStream
 
 from twistedcaldav import caldavxml
 from twistedcaldav.ical import Component

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_multiget_common.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_multiget_common.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_multiget_common.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -23,12 +23,12 @@
 from urllib import unquote
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
 from txdav.xml.base import dav_namespace
-from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
-from twext.web2.dav.resource import AccessDeniedError
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2.dav.http import ErrorResponse, MultiStatusResponse
+from txweb2.dav.resource import AccessDeniedError
+from txweb2.http import HTTPError, StatusResponse
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_sync_collection.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_sync_collection.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/method/report_sync_collection.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -25,13 +25,13 @@
 
 from twext.python.log import Logger
 from txdav.xml import element
-from twext.web2.dav.http import ErrorResponse
-from twext.web2 import responsecode
-from twext.web2.dav.http import MultiStatusResponse, statusForFailure
-from twext.web2.dav.method.prop_common import responseForHref
-from twext.web2.dav.method.propfind import propertyName
-from twext.web2.dav.util import joinURL
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2.dav.http import ErrorResponse
+from txweb2 import responsecode
+from txweb2.dav.http import MultiStatusResponse, statusForFailure
+from txweb2.dav.method.prop_common import responseForHref
+from txweb2.dav.method.propfind import propertyName
+from txweb2.dav.util import joinURL
+from txweb2.http import HTTPError, StatusResponse
 
 from twistedcaldav.config import config
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/notifications.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/notifications.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/notifications.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -24,7 +24,7 @@
 ]
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
 
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue,\

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -46,17 +46,17 @@
 from txdav.xml import element
 from txdav.xml.element import dav_namespace
 
-from twext.web2 import responsecode, http, http_headers
-from twext.web2.dav.auth import AuthenticationWrapper as SuperAuthenticationWrapper
-from twext.web2.dav.idav import IDAVPrincipalCollectionResource
-from twext.web2.dav.resource import AccessDeniedError, DAVPrincipalCollectionResource, \
+from txweb2 import responsecode, http, http_headers
+from txweb2.dav.auth import AuthenticationWrapper as SuperAuthenticationWrapper
+from txweb2.dav.idav import IDAVPrincipalCollectionResource
+from txweb2.dav.resource import AccessDeniedError, DAVPrincipalCollectionResource, \
     davPrivilegeSet
-from twext.web2.dav.resource import TwistedACLInheritable
-from twext.web2.dav.util import joinURL, parentForURL, normalizeURL
-from twext.web2.http import HTTPError, RedirectResponse, StatusResponse, Response
-from twext.web2.dav.http import ErrorResponse
-from twext.web2.http_headers import MimeType, ETag
-from twext.web2.stream import MemoryStream
+from txweb2.dav.resource import TwistedACLInheritable
+from txweb2.dav.util import joinURL, parentForURL, normalizeURL
+from txweb2.http import HTTPError, RedirectResponse, StatusResponse, Response
+from txweb2.dav.http import ErrorResponse
+from txweb2.http_headers import MimeType, ETag
+from txweb2.stream import MemoryStream
 
 from twistedcaldav import caldavxml, customxml
 from twistedcaldav import carddavxml
@@ -322,7 +322,7 @@
         successfully rendered.
 
         @param request: the request to generate a response for.
-        @type request: L{twext.web2.iweb.IRequest}
+        @type request: L{txweb2.iweb.IRequest}
         @param transaction: optional transaction to use instead of associated transaction
         @type transaction: L{txdav.caldav.idav.ITransaction}
         """
@@ -1354,7 +1354,7 @@
             if self.exists() and hasattr(self, "scheduleEtags"):
                 etags = self.scheduleEtags
                 if len(etags) > 1:
-                    # This is almost verbatim from twext.web2.static.checkPreconditions
+                    # This is almost verbatim from txweb2.static.checkPreconditions
                     if request.method not in ("GET", "HEAD"):
 
                         # Always test against the current etag first just in case schedule-etags is out of sync
@@ -1402,7 +1402,7 @@
         @param request: the request used to look up parent resources to
             validate.
 
-        @type request: L{twext.web2.iweb.IRequest}
+        @type request: L{txweb2.iweb.IRequest}
 
         @return: a deferred that fires when a calendar collection has been
             created in this resource.
@@ -1488,7 +1488,7 @@
         @param request: the request used to look up parent resources to
             validate.
 
-        @type request: L{twext.web2.iweb.IRequest}
+        @type request: L{txweb2.iweb.IRequest}
 
         @return: a deferred that fires when an addressbook collection has been
             created in this resource.

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/scheduling_store/caldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/scheduling_store/caldav/resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/scheduling_store/caldav/resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -33,11 +33,11 @@
 # around that for now.
 __import__("twistedcaldav.stdconfig") # FIXME
 
-from twext.web2 import responsecode
-from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
-from twext.web2.dav.resource import davPrivilegeSet
-from twext.web2.dav.util import joinURL, normalizeURL
-from twext.web2.http import HTTPError
+from txweb2 import responsecode
+from txweb2.dav.http import ErrorResponse, MultiStatusResponse
+from txweb2.dav.resource import davPrivilegeSet
+from txweb2.dav.util import joinURL, normalizeURL
+from txweb2.http import HTTPError
 
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 from twisted.python.failure import Failure

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/scheduling_store/caldav/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/scheduling_store/caldav/test/test_resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/scheduling_store/caldav/test/test_resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,7 +14,7 @@
 # limitations under the License.
 ##
 
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.test.test_server import SimpleRequest
 
 from twisted.internet.defer import inlineCallbacks
 
@@ -22,7 +22,7 @@
 from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
 
 from txdav.xml import element as davxml
-from twext.web2.http import HTTPError
+from txweb2.http import HTTPError
 
 class Properties (StoreTestCase):
     """

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/sharing.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/sharing.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -25,11 +25,11 @@
     "SharedHomeMixin",
 ]
 
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError, Response, XMLResponse
-from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
-from twext.web2.dav.resource import TwistedACLInheritable
-from twext.web2.dav.util import allDataFromStream, joinURL
+from txweb2 import responsecode
+from txweb2.http import HTTPError, Response, XMLResponse
+from txweb2.dav.http import ErrorResponse, MultiStatusResponse
+from txweb2.dav.resource import TwistedACLInheritable
+from txweb2.dav.util import allDataFromStream, joinURL
 
 from txdav.common.datastore.sql_tables import _BIND_MODE_OWN, \
     _BIND_MODE_READ, _BIND_MODE_WRITE, _BIND_STATUS_INVITED, \
@@ -142,7 +142,7 @@
 
         @return: the (asynchronous) HTTP result to respond to the direct-share
             request.
-        @rtype: L{Deferred} firing L{twext.web2.http.Response}, failing with
+        @rtype: L{Deferred} firing L{txweb2.http.Response}, failing with
             L{HTTPError}
         """
 
@@ -299,13 +299,13 @@
         underlying shared collection.
 
         @param request: the request used to locate the owner resource.
-        @type request: L{twext.web2.iweb.IRequest}
+        @type request: L{txweb2.iweb.IRequest}
 
         @param args: The arguments for
-            L{twext.web2.dav.idav.IDAVResource.accessControlList}
+            L{txweb2.dav.idav.IDAVResource.accessControlList}
 
         @param kwargs: The keyword arguments for
-            L{twext.web2.dav.idav.IDAVResource.accessControlList}, plus
+            L{txweb2.dav.idav.IDAVResource.accessControlList}, plus
             keyword-only arguments.
 
         @return: the appropriate WebDAV ACL for the sharee

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/simpleresource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/simpleresource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/simpleresource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -26,9 +26,9 @@
     "SimpleDataResource",
 ]
 
-from twext.web2 import http
-from twext.web2.dav.noneprops import NonePropertyStore
-from twext.web2.http import Response
+from txweb2 import http
+from txweb2.dav.noneprops import NonePropertyStore
+from txweb2.http import Response
 
 from twisted.internet.defer import succeed
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/stdconfig.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/stdconfig.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -22,9 +22,9 @@
 
 from twisted.python.runtime import platform
 
-from twext.python.plistlib import PlistParser #@UnresolvedImport
+from plistlib import PlistParser #@UnresolvedImport
 from twext.python.log import Logger, InvalidLogLevelError, LogLevel
-from twext.web2.dav.resource import TwistedACLInheritable
+from txweb2.dav.resource import TwistedACLInheritable
 
 from txdav.xml import element as davxml
 
@@ -34,6 +34,7 @@
 from twistedcaldav.util import getPasswordFromKeychain
 from twistedcaldav.util import KeychainAccessError, KeychainPasswordNotFound
 from twistedcaldav.util import computeProcessCount
+from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
 
 from calendarserver.push.util import getAPNTopicFromCertificate
 from twistedcaldav import ical
@@ -166,7 +167,7 @@
 DEFAULT_RESOURCE_PARAMS = {
     "twistedcaldav.directory.xmlfile.XMLDirectoryService": {
         "xmlFile": "resources.xml",
-        "recordTypes" : ("locations", "resources"),
+        "recordTypes" : ("locations", "resources", "addresses"),
     },
     "twistedcaldav.directory.appleopendirectory.OpenDirectoryService": {
         "node": "/Search",
@@ -588,10 +589,13 @@
 
         "Calendars" : {
             "Enabled"         : True, # Calendar on/off switch
+            "IgnorePerUserProperties" : [
+                "X-APPLE-STRUCTURED-LOCATION",
+            ],
         },
         "AddressBooks" : {
             "Enabled"         : False, # Address Books on/off switch
-        }
+        },
     },
 
     "RestrictCalendarsToOneComponentType" : True, # Only allow calendars to be created with a single component type
@@ -619,6 +623,8 @@
     "EnableDefaultAlarms" : True, # Support for default alarms generated by the server
     "RemoveDuplicateAlarms": True, # Remove duplicate alarms on PUT
 
+    "RemoveDuplicatePrivateComments": False, # Remove duplicate private comments on PUT
+
     # CardDAV Features
     "DirectoryAddressBook": {
         "Enabled": True,
@@ -948,6 +954,7 @@
         "DatabaseName": "caldav",
         "ClusterName": "cluster",
         "LogFile": "postgres.log",
+        "SocketDirectory": "",
         "ListenAddresses": [],
         "SharedBuffers": 0, # BuffersToConnectionsRatio * MaxConnections
                             # Note: don't set this, it will be computed dynamically
@@ -1004,7 +1011,7 @@
     "FreeBusyIndexDelayedExpand": True,
 
     # The RootResource uses a twext property store. Specify the class here
-    "RootResourcePropStoreClass": "twext.web2.dav.xattrprops.xattrPropertyStore",
+    "RootResourcePropStoreClass": "txweb2.dav.xattrprops.xattrPropertyStore",
 
     # Used in the command line utilities to specify which service class to
     # use to carry out work.
@@ -1557,7 +1564,16 @@
                         (direction,))
 
 
+def _updateSharing(configDict, reloading=False):
+    #
+    # Sharing
+    #
 
+    # Transfer configured non-per-user property names to PerUserDataFilter
+    for propertyName in configDict.Sharing.Calendars.IgnorePerUserProperties:
+        PerUserDataFilter.IGNORE_X_PROPERTIES.append(propertyName)
+
+
 def _updateServers(configDict, reloading=False):
     from txdav.caldav.datastore.scheduling.ischedule.localservers import Servers
     if configDict.Servers.Enabled:
@@ -1635,6 +1651,7 @@
     _updateNotifications,
     _updateICalendar,
     _updateScheduling,
+    _updateSharing,
     _updateServers,
     _updateCompliance,
     )

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/storebridge.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/storebridge.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -17,19 +17,22 @@
 
 from pycalendar.datetime import DateTime
 
+from twext.enterprise.locking import LockTimeout
 from twext.python.log import Logger
-from twext.web2.dav.http import ErrorResponse, ResponseQueue, MultiStatusResponse
-from twext.web2.dav.noneprops import NonePropertyStore
-from twext.web2.dav.resource import TwistedACLInheritable, AccessDeniedError, \
+from txweb2 import responsecode, http_headers, http
+from txweb2.dav.http import ErrorResponse, ResponseQueue, MultiStatusResponse
+from txweb2.dav.noneprops import NonePropertyStore
+from txweb2.dav.resource import TwistedACLInheritable, AccessDeniedError, \
     davPrivilegeSet
-from twext.web2.dav.util import parentForURL, allDataFromStream, joinURL, davXMLFromStream
-from twext.web2.filter.location import addLocation
-from twext.web2.http import HTTPError, StatusResponse, Response
-from twext.web2.http_headers import ETag, MimeType, MimeDisposition
-from twext.web2.responsecode import \
+from txweb2.dav.util import parentForURL, allDataFromStream, joinURL, davXMLFromStream
+from txweb2.filter.location import addLocation
+from txweb2.http import HTTPError, StatusResponse, Response
+from txweb2.http_headers import ETag, MimeType, MimeDisposition
+from txweb2.iweb import IResponse
+from txweb2.responsecode import \
     FORBIDDEN, NO_CONTENT, NOT_FOUND, CREATED, CONFLICT, PRECONDITION_FAILED, \
     BAD_REQUEST, OK, INSUFFICIENT_STORAGE_SPACE, SERVICE_UNAVAILABLE
-from twext.web2.stream import ProducerStream, readStream, MemoryStream
+from txweb2.stream import ProducerStream, readStream, MemoryStream
 
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue, maybeDeferred
 from twisted.internet.protocol import Protocol
@@ -41,14 +44,20 @@
     MaxInstances, NoUIDConflict
 from twistedcaldav.carddavxml import carddav_namespace, NoUIDConflict as NovCardUIDConflict
 from twistedcaldav.config import config
+from twistedcaldav.customxml import calendarserver_namespace
 from twistedcaldav.directory.wiki import WikiDirectoryService, getWikiAccess
 from twistedcaldav.ical import Component as VCalendar, Property as VProperty, \
     InvalidICalendarDataError, iCalendarProductID, Component
+from twistedcaldav.instance import InvalidOverriddenInstanceError, \
+    TooManyInstancesError
 from twistedcaldav.memcachelock import MemcacheLockTimeoutError
 from twistedcaldav.notifications import NotificationCollectionResource, NotificationResource
 from twistedcaldav.resource import CalDAVResource, GlobalAddressBookResource, \
     DefaultAlarmPropertyMixin
 from twistedcaldav.scheduling_store.caldav.resource import ScheduleInboxResource
+from twistedcaldav.sharing import invitationBindStatusToXMLMap, \
+    invitationBindModeToXMLMap
+from twistedcaldav.util import bestAcceptType
 from twistedcaldav.vcard import Component as VCard, InvalidVCardDataError
 
 from txdav.base.propertystore.base import PropertyName
@@ -58,7 +67,7 @@
     TooManyAttendeesError, InvalidCalendarAccessError, ValidOrganizerError, \
     InvalidPerUserDataMerge, \
     AttendeeAllowedError, ResourceDeletedError, InvalidAttachmentOperation, \
-    ShareeAllowedError
+    ShareeAllowedError, DuplicatePrivateCommentsError
 from txdav.carddav.iaddressbookstore import KindChangeNotAllowedError, \
     GroupWithUnsharedAddressNotAllowedError
 from txdav.common.datastore.sql_tables import _BIND_MODE_READ, _BIND_MODE_WRITE, \
@@ -74,19 +83,10 @@
 from txdav.xml.base import dav_namespace, WebDAVUnknownElement, encodeXMLName
 
 from urlparse import urlsplit, urljoin
+import collections
 import hashlib
 import time
 import uuid
-from twext.web2 import responsecode, http_headers, http
-from twext.web2.iweb import IResponse
-from twistedcaldav.customxml import calendarserver_namespace
-from twistedcaldav.instance import InvalidOverriddenInstanceError, \
-    TooManyInstancesError
-from twistedcaldav.util import bestAcceptType
-import collections
-from twistedcaldav.sharing import invitationBindStatusToXMLMap, \
-    invitationBindModeToXMLMap
-
 """
 Wrappers to translate between the APIs in L{txdav.caldav.icalendarstore} and
 L{txdav.carddav.iaddressbookstore} and those in L{twistedcaldav}.
@@ -450,12 +450,12 @@
             this is the request which I{triggered} the C{DELETE}, but which may
             not actually be a C{DELETE} request itself.
 
-        @type request: L{twext.web2.iweb.IRequest}
+        @type request: L{txweb2.iweb.IRequest}
 
         @return: an HTTP response suitable for sending to a client (or
             including in a multi-status).
 
-        @rtype: something adaptable to L{twext.web2.iweb.IResponse}
+        @rtype: something adaptable to L{txweb2.iweb.IResponse}
         """
 
         # Check sharee collection first
@@ -2291,11 +2291,53 @@
         returnValue(response)
 
     # The following are used to map store exceptions into HTTP error responses
-    StoreExceptionsStatusErrors = set()
     StoreExceptionsErrors = {}
-    StoreMoveExceptionsStatusErrors = set()
     StoreMoveExceptionsErrors = {}
+    StoreRemoveExceptionsErrors = {}
 
+    @classmethod
+    def _storeExceptionStatus(cls, err, arg):
+        """
+        Raise a status error.
+
+        @param err: the actual exception that caused the error
+        @type err: L{Exception}
+        @param arg: description of error or C{None}
+        @type arg: C{str} or C{None}
+        """
+        raise HTTPError(StatusResponse(responsecode.FORBIDDEN, arg if arg is not None else str(err)))
+
+
+    @classmethod
+    def _storeExceptionError(cls, err, arg):
+        """
+        Raise a DAV:error error with the supplied error element.
+
+        @param err: the actual exception that caused the error
+        @type err: L{Exception}
+        @param arg: the error element
+        @type arg: C{tuple}
+        """
+        raise HTTPError(ErrorResponse(
+            responsecode.FORBIDDEN,
+            arg,
+            str(err),
+        ))
+
+
+    @classmethod
+    def _storeExceptionUnavailable(cls, err, arg):
+        """
+        Raise a service unavailable error.
+
+        @param err: the actual exception that caused the error
+        @type err: L{Exception}
+        @param arg: description of error or C{None}
+        @type arg: C{str} or C{None}
+        """
+        raise HTTPError(StatusResponse(responsecode.SERVICE_UNAVAILABLE, arg if arg is not None else str(err)))
+
+
     @requiresPermissions(fromParent=[davxml.Unbind()])
     def http_DELETE(self, request):
         """
@@ -2387,15 +2429,9 @@
             # Grab the current exception state here so we can use it in a re-raise - we need this because
             # an inlineCallback might be called and that raises an exception when it returns, wiping out the
             # original exception "context".
-            if type(err) in self.StoreMoveExceptionsStatusErrors:
-                raise HTTPError(StatusResponse(responsecode.FORBIDDEN, str(err)))
-
-            elif type(err) in self.StoreMoveExceptionsErrors:
-                raise HTTPError(ErrorResponse(
-                    responsecode.FORBIDDEN,
-                    self.StoreMoveExceptionsErrors[type(err)],
-                    str(err),
-                ))
+            if type(err) in self.StoreMoveExceptionsErrors:
+                error, arg = self.StoreMoveExceptionsErrors[type(err)]
+                error(err, arg)
             else:
                 # Return the original failure (exception) state
                 raise
@@ -2438,15 +2474,9 @@
 
         # Map store exception to HTTP errors
         except Exception as err:
-            if type(err) in self.StoreExceptionsStatusErrors:
-                raise HTTPError(StatusResponse(responsecode.FORBIDDEN, str(err)))
-
-            elif type(err) in self.StoreExceptionsErrors:
-                raise HTTPError(ErrorResponse(
-                    responsecode.FORBIDDEN,
-                    self.StoreExceptionsErrors[type(err)],
-                    str(err),
-                ))
+            if type(err) in self.StoreExceptionsErrors:
+                error, arg = self.StoreExceptionsErrors[type(err)]
+                error(err, arg)
             else:
                 raise
 
@@ -2457,7 +2487,7 @@
         Move this object to a different parent.
 
         @param request:
-        @type request: L{twext.web2.iweb.IRequest}
+        @type request: L{txweb2.iweb.IRequest}
         @param destinationparent: Parent to move to
         @type destinationparent: L{CommonHomeChild}
         @param destination_name: name of new resource
@@ -2476,12 +2506,12 @@
         @param request: Unused by this implementation; present for signature
             compatibility with L{CalendarCollectionResource.storeRemove}.
 
-        @type request: L{twext.web2.iweb.IRequest}
+        @type request: L{txweb2.iweb.IRequest}
 
         @return: an HTTP response suitable for sending to a client (or
             including in a multi-status).
 
-         @rtype: something adaptable to L{twext.web2.iweb.IResponse}
+         @rtype: something adaptable to L{txweb2.iweb.IResponse}
         """
 
         # Do delete
@@ -2491,6 +2521,14 @@
         except NoSuchObjectResourceError:
             raise HTTPError(NOT_FOUND)
 
+        # Map store exception to HTTP errors
+        except Exception as err:
+            if type(err) in self.StoreExceptionsErrors:
+                error, arg = self.StoreExceptionsErrors[type(err)]
+                error(err, arg)
+            else:
+                raise
+
         # Re-initialize to get stuff setup again now we have no object
         self._initializeWithObject(None, self._newStoreParent)
 
@@ -2624,50 +2662,51 @@
         else:
             return False
 
-    StoreExceptionsStatusErrors = set((
-        ObjectResourceNameNotAllowedError,
-        ObjectResourceNameAlreadyExistsError,
-    ))
-
     StoreExceptionsErrors = {
-        TooManyObjectResourcesError: customxml.MaxResources(),
-        ObjectResourceTooBigError: (caldav_namespace, "max-resource-size"),
-        InvalidObjectResourceError: (caldav_namespace, "valid-calendar-data"),
-        InvalidComponentForStoreError: (caldav_namespace, "valid-calendar-object-resource"),
-        InvalidComponentTypeError: (caldav_namespace, "supported-component"),
-        TooManyAttendeesError: MaxAttendeesPerInstance.fromString(str(config.MaxAttendeesPerInstance)),
-        InvalidCalendarAccessError: (calendarserver_namespace, "valid-access-restriction"),
-        ValidOrganizerError: (calendarserver_namespace, "valid-organizer"),
-        UIDExistsError: NoUIDConflict(),
-        UIDExistsElsewhereError: (caldav_namespace, "unique-scheduling-object-resource"),
-        InvalidUIDError: NoUIDConflict(),
-        InvalidPerUserDataMerge: (caldav_namespace, "valid-calendar-data"),
-        AttendeeAllowedError: (caldav_namespace, "attendee-allowed"),
-        InvalidOverriddenInstanceError: (caldav_namespace, "valid-calendar-data"),
-        TooManyInstancesError: MaxInstances.fromString(str(config.MaxAllowedInstances)),
-        AttachmentStoreValidManagedID: (caldav_namespace, "valid-managed-id"),
-        ShareeAllowedError: (calendarserver_namespace, "sharee-privilege-needed",),
+        ObjectResourceNameNotAllowedError: (_CommonObjectResource._storeExceptionStatus, None,),
+        ObjectResourceNameAlreadyExistsError: (_CommonObjectResource._storeExceptionStatus, None,),
+        TooManyObjectResourcesError: (_CommonObjectResource._storeExceptionError, customxml.MaxResources(),),
+        ObjectResourceTooBigError: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "max-resource-size"),),
+        InvalidObjectResourceError: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "valid-calendar-data"),),
+        InvalidComponentForStoreError: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "valid-calendar-object-resource"),),
+        InvalidComponentTypeError: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "supported-component"),),
+        TooManyAttendeesError: (_CommonObjectResource._storeExceptionError, MaxAttendeesPerInstance.fromString(str(config.MaxAttendeesPerInstance)),),
+        InvalidCalendarAccessError: (_CommonObjectResource._storeExceptionError, (calendarserver_namespace, "valid-access-restriction"),),
+        ValidOrganizerError: (_CommonObjectResource._storeExceptionError, (calendarserver_namespace, "valid-organizer"),),
+        UIDExistsError: (_CommonObjectResource._storeExceptionError, NoUIDConflict(),),
+        UIDExistsElsewhereError: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "unique-scheduling-object-resource"),),
+        InvalidUIDError: (_CommonObjectResource._storeExceptionError, NoUIDConflict(),),
+        InvalidPerUserDataMerge: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "valid-calendar-data"),),
+        AttendeeAllowedError: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "attendee-allowed"),),
+        InvalidOverriddenInstanceError: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "valid-calendar-data"),),
+        TooManyInstancesError: (_CommonObjectResource._storeExceptionError, MaxInstances.fromString(str(config.MaxAllowedInstances)),),
+        AttachmentStoreValidManagedID: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "valid-managed-id"),),
+        ShareeAllowedError: (_CommonObjectResource._storeExceptionError, (calendarserver_namespace, "sharee-privilege-needed",),),
+        DuplicatePrivateCommentsError: (_CommonObjectResource._storeExceptionError, (calendarserver_namespace, "no-duplicate-private-comments",),),
+        LockTimeout: (_CommonObjectResource._storeExceptionUnavailable, "Lock timed out.",),
     }
 
-    StoreMoveExceptionsStatusErrors = set((
-        ObjectResourceNameNotAllowedError,
-        ObjectResourceNameAlreadyExistsError,
-    ))
-
     StoreMoveExceptionsErrors = {
-        TooManyObjectResourcesError: customxml.MaxResources(),
-        InvalidResourceMove: (calendarserver_namespace, "valid-move"),
-        InvalidComponentTypeError: (caldav_namespace, "supported-component"),
+        ObjectResourceNameNotAllowedError: (_CommonObjectResource._storeExceptionStatus, None,),
+        ObjectResourceNameAlreadyExistsError: (_CommonObjectResource._storeExceptionStatus, None,),
+        TooManyObjectResourcesError: (_CommonObjectResource._storeExceptionError, customxml.MaxResources(),),
+        InvalidResourceMove: (_CommonObjectResource._storeExceptionError, (calendarserver_namespace, "valid-move"),),
+        InvalidComponentTypeError: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "supported-component"),),
+        LockTimeout: (_CommonObjectResource._storeExceptionUnavailable, "Lock timed out.",),
     }
 
+    StoreRemoveExceptionsErrors = {
+        LockTimeout: (_CommonObjectResource._storeExceptionUnavailable, "Lock timed out.",),
+    }
+
     StoreAttachmentValidErrors = set((
         AttachmentStoreFailed,
         InvalidAttachmentOperation,
     ))
 
     StoreAttachmentExceptionsErrors = {
-        AttachmentStoreValidManagedID: (caldav_namespace, "valid-managed-id-parameter",),
-        AttachmentRemoveFailed: (caldav_namespace, "valid-attachment-remove",),
+        AttachmentStoreValidManagedID: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "valid-managed-id-parameter",),),
+        AttachmentRemoveFailed: (_CommonObjectResource._storeExceptionError, (caldav_namespace, "valid-attachment-remove",),),
     }
 
 
@@ -2683,7 +2722,7 @@
             if self.exists():
                 etags = self.scheduleEtags
                 if len(etags) > 1:
-                    # This is almost verbatim from twext.web2.static.checkPreconditions
+                    # This is almost verbatim from txweb2.static.checkPreconditions
                     if request.method not in ("GET", "HEAD"):
 
                         # Always test against the current etag first just in case schedule-etags is out of sync
@@ -2981,28 +3020,15 @@
         except Exception as err:
 
             if type(err) in self.StoreAttachmentValidErrors:
-                raise HTTPError(ErrorResponse(
-                    responsecode.FORBIDDEN,
-                    (caldav_namespace, valid_preconditions[action],),
-                    str(err),
-                ))
+                self._storeExceptionError(err, (caldav_namespace, valid_preconditions[action],))
 
             elif type(err) in self.StoreAttachmentExceptionsErrors:
-                raise HTTPError(ErrorResponse(
-                    responsecode.FORBIDDEN,
-                    self.StoreAttachmentExceptionsErrors[type(err)],
-                    str(err),
-                ))
+                error, arg = self.StoreAttachmentExceptionsErrors[type(err)]
+                error(err, arg)
 
-            elif type(err) in self.StoreExceptionsStatusErrors:
-                raise HTTPError(StatusResponse(responsecode.FORBIDDEN, str(err)))
-
             elif type(err) in self.StoreExceptionsErrors:
-                raise HTTPError(ErrorResponse(
-                    responsecode.FORBIDDEN,
-                    self.StoreExceptionsErrors[type(err)],
-                    str(err),
-                ))
+                error, arg = self.StoreExceptionsErrors[type(err)]
+                error(err, arg)
 
             else:
                 raise
@@ -3300,32 +3326,32 @@
 
     vCard = _CommonObjectResource.component
 
-    StoreExceptionsStatusErrors = set((
-        ObjectResourceNameNotAllowedError,
-        ObjectResourceNameAlreadyExistsError,
-    ))
-
     StoreExceptionsErrors = {
-        TooManyObjectResourcesError: customxml.MaxResources(),
-        ObjectResourceTooBigError: (carddav_namespace, "max-resource-size"),
-        InvalidObjectResourceError: (carddav_namespace, "valid-address-data"),
-        InvalidComponentForStoreError: (carddav_namespace, "valid-addressbook-object-resource"),
-        UIDExistsError: NovCardUIDConflict(),
-        InvalidUIDError: NovCardUIDConflict(),
-        InvalidPerUserDataMerge: (carddav_namespace, "valid-address-data"),
+        ObjectResourceNameNotAllowedError: (_CommonObjectResource._storeExceptionStatus, None,),
+        ObjectResourceNameAlreadyExistsError: (_CommonObjectResource._storeExceptionStatus, None,),
+        TooManyObjectResourcesError: (_CommonObjectResource._storeExceptionError, customxml.MaxResources(),),
+        ObjectResourceTooBigError: (_CommonObjectResource._storeExceptionError, (carddav_namespace, "max-resource-size"),),
+        InvalidObjectResourceError: (_CommonObjectResource._storeExceptionError, (carddav_namespace, "valid-address-data"),),
+        InvalidComponentForStoreError: (_CommonObjectResource._storeExceptionError, (carddav_namespace, "valid-addressbook-object-resource"),),
+        UIDExistsError: (_CommonObjectResource._storeExceptionError, NovCardUIDConflict(),),
+        InvalidUIDError: (_CommonObjectResource._storeExceptionError, NovCardUIDConflict(),),
+        InvalidPerUserDataMerge: (_CommonObjectResource._storeExceptionError, (carddav_namespace, "valid-address-data"),),
+        LockTimeout: (_CommonObjectResource._storeExceptionUnavailable, "Lock timed out.",),
     }
 
-    StoreMoveExceptionsStatusErrors = set((
-        ObjectResourceNameNotAllowedError,
-        ObjectResourceNameAlreadyExistsError,
-    ))
-
     StoreMoveExceptionsErrors = {
-        TooManyObjectResourcesError: customxml.MaxResources(),
-        InvalidResourceMove: (calendarserver_namespace, "valid-move"),
+        ObjectResourceNameNotAllowedError: (_CommonObjectResource._storeExceptionStatus, None,),
+        ObjectResourceNameAlreadyExistsError: (_CommonObjectResource._storeExceptionStatus, None,),
+        TooManyObjectResourcesError: (_CommonObjectResource._storeExceptionError, customxml.MaxResources(),),
+        InvalidResourceMove: (_CommonObjectResource._storeExceptionError, (calendarserver_namespace, "valid-move"),),
+        LockTimeout: (_CommonObjectResource._storeExceptionUnavailable, "Lock timed out.",),
     }
 
+    StoreRemoveExceptionsErrors = {
+        LockTimeout: (_CommonObjectResource._storeExceptionUnavailable, "Lock timed out.",),
+    }
 
+
     def resourceType(self):
         if self.isShared():
             return customxml.ResourceType.sharedownergroup
@@ -3488,13 +3514,13 @@
         "direct" shares are not supported.
 
         @param request: the request used to locate the owner resource.
-        @type request: L{twext.web2.iweb.IRequest}
+        @type request: L{txweb2.iweb.IRequest}
 
         @param args: The arguments for
-            L{twext.web2.dav.idav.IDAVResource.accessControlList}
+            L{txweb2.dav.idav.IDAVResource.accessControlList}
 
         @param kwargs: The keyword arguments for
-            L{twext.web2.dav.idav.IDAVResource.accessControlList}, plus
+            L{txweb2.dav.idav.IDAVResource.accessControlList}, plus
             keyword-only arguments.
 
         @return: the appropriate WebDAV ACL for the sharee

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_accounting.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_accounting.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_accounting.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,9 +14,9 @@
 # limitations under the License.
 ##
 
-from twext.web2.channel.http import HTTPLoggingChannelRequest
-from twext.web2 import http_headers
-from twext.web2.channel.http import HTTPChannel
+from txweb2.channel.http import HTTPLoggingChannelRequest
+from txweb2 import http_headers
+from txweb2.channel.http import HTTPChannel
 from twistedcaldav.accounting import emitAccounting
 from twistedcaldav.config import config
 import twistedcaldav.test.util

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_addressbookmultiget.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_addressbookmultiget.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_addressbookmultiget.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,11 +16,11 @@
 
 import os
 
-from twext.web2 import responsecode
-from twext.web2.iweb import IResponse
-from twext.web2.stream import MemoryStream
-from twext.web2.dav.util import davXMLFromStream, joinURL
-from twext.web2.http_headers import Headers, MimeType
+from txweb2 import responsecode
+from txweb2.iweb import IResponse
+from txweb2.stream import MemoryStream
+from txweb2.dav.util import davXMLFromStream, joinURL
+from txweb2.http_headers import Headers, MimeType
 
 from twistedcaldav import carddavxml
 from twistedcaldav import vcard

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_addressbookquery.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_addressbookquery.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_addressbookquery.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,11 +16,11 @@
 
 import os
 
-from twext.web2 import responsecode
-from twext.web2.iweb import IResponse
-from twext.web2.stream import MemoryStream
+from txweb2 import responsecode
+from txweb2.iweb import IResponse
+from txweb2.stream import MemoryStream
 from txdav.xml import element as davxml
-from twext.web2.dav.util import davXMLFromStream, joinURL
+from txweb2.dav.util import davXMLFromStream, joinURL
 
 from twistedcaldav import carddavxml, vcard
 from twistedcaldav.config import config

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_cache.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_cache.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_cache.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -20,9 +20,9 @@
 
 from twisted.internet.defer import succeed, maybeDeferred, inlineCallbacks
 
-from twext.web2.dav.util import allDataFromStream
-from twext.web2.stream import MemoryStream
-from twext.web2.http_headers import Headers
+from txweb2.dav.util import allDataFromStream
+from txweb2.stream import MemoryStream
+from txweb2.http_headers import Headers
 
 from txdav.xml import element as davxml
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_calendarquery.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_calendarquery.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_calendarquery.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -18,11 +18,11 @@
 
 from twisted.trial.unittest import SkipTest
 
-from twext.web2 import responsecode
-from twext.web2.iweb import IResponse
-from twext.web2.stream import MemoryStream
+from txweb2 import responsecode
+from txweb2.iweb import IResponse
+from txweb2.stream import MemoryStream
 from txdav.xml import element as davxml
-from twext.web2.dav.util import davXMLFromStream
+from txweb2.dav.util import davXMLFromStream
 
 from twistedcaldav import caldavxml
 from twistedcaldav import ical

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_collectioncontents.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_collectioncontents.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_collectioncontents.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,10 +16,10 @@
 
 from twisted.internet.defer import inlineCallbacks
 from twext.python.filepath import CachingFilePath as FilePath
-from twext.web2 import responsecode
-from twext.web2.iweb import IResponse
-from twext.web2.stream import MemoryStream, FileStream
-from twext.web2.http_headers import MimeType
+from txweb2 import responsecode
+from txweb2.iweb import IResponse
+from txweb2.stream import MemoryStream, FileStream
+from txweb2.http_headers import MimeType
 
 from twistedcaldav.ical import Component
 from twistedcaldav.memcachelock import MemcacheLock
@@ -27,7 +27,7 @@
 
 
 from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
-from twext.web2.dav.util import joinURL
+from txweb2.dav.util import joinURL
 from txdav.caldav.datastore.sql import CalendarObject
 
 class CollectionContents(StoreTestCase):

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_config.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_config.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_config.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,7 +16,7 @@
 
 import socket
 
-from twext.python.plistlib import writePlist #@UnresolvedImport
+from plistlib import writePlist #@UnresolvedImport
 from twext.python.log import LogLevel
 from twext.python.test.test_log import defaultLogLevel, logLevelForNamespace
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_extensions.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_extensions.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_extensions.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,8 +16,8 @@
 ##
 
 from twext.python.filepath import CachingFilePath as FilePath
-from twext.web2.http_headers import MimeType
-from twext.web2.static import MetaDataMixin
+from txweb2.http_headers import MimeType
+from txweb2.static import MetaDataMixin
 
 from twisted.internet.defer import inlineCallbacks, Deferred, succeed
 from twisted.web.microdom import parseString

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_freebusyquery.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_freebusyquery.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_freebusyquery.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -21,11 +21,11 @@
 
 from twext.python.filepath import CachingFilePath as FilePath
 
-from twext.web2 import responsecode
-from twext.web2.iweb import IResponse
-from twext.web2.stream import MemoryStream
+from txweb2 import responsecode
+from txweb2.iweb import IResponse
+from txweb2.stream import MemoryStream
 
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.test.test_server import SimpleRequest
 
 import twistedcaldav.test.util
 from twistedcaldav import caldavxml

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_icalendar.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_icalendar.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_icalendar.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -10128,3 +10128,322 @@
             ical2 = Component.fromString(calendar)
             ical2.onlyPastInstances(rid)
             self.assertEqual(str(ical2), split_past.replace("\n", "\r\n"), "Failed past: %s" % (title,))
+
+
+    def test_hasDuplicatePrivateComments(self):
+        """
+        Test that L{Component.hasDuplicatePrivateComments} correctly detects, but does not fix, duplicate private comments.
+        """
+
+        data = (
+            (
+                "No comments",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+            ),
+
+            (
+                "One comment",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+            ),
+
+            (
+                "Two different comments",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+            ),
+
+            (
+                "Two duplicates, one different",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+            ),
+
+            (
+                "No duplicates in two components",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user03";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message3
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+            ),
+
+            (
+                "Two duplicates in one component, three different in another",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user03";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message3
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+            ),
+        )
+
+        for title, txt, result in data:
+            component = Component.fromString(txt)
+            self.assertEqual(component.hasDuplicatePrivateComments(doFix=False), result, msg=title)
+            self.assertEqual(normalize_iCalStr(component), normalize_iCalStr(txt), msg=title)
+
+
+    def test_hasDuplicatePrivateComments_withFix(self):
+        """
+        Test that L{Component.hasDuplicatePrivateComments} correctly removes duplicate comments.
+        """
+
+        data = (
+            (
+                "No comments",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+            ),
+
+            (
+                "One comment",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+            ),
+
+            (
+                "Two different comments",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+            ),
+
+            (
+                "Two duplicates, one different",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+RRULE:FREQ=DAILY
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+RECURRENCE-ID:20080602T120000Z
+DTSTART:20080602T120000Z
+DURATION:PT1H
+DTSTAMP:20080601T120000Z
+SUMMARY:Test
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user01";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message1
+X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:user02";X-CALENDARSERVER-DTSTAMP=20130606T152554Z:Message2
+END:VEVENT
+END:VCALENDAR
+""",
+                False,
+            ),
+        )
+
+        for title, txt, result, result_changed in data:
+            component = Component.fromString(txt)
+            changed = component.hasDuplicatePrivateComments(doFix=True)
+            self.assertEqual(sorted(normalize_iCalStr(component).splitlines()), sorted(normalize_iCalStr(result).splitlines()), msg=title)
+            self.assertEqual(changed, result_changed, msg=title)

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_kerberos.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_kerberos.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_kerberos.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -17,7 +17,7 @@
 from twisted.cred.error import LoginFailed
 from twisted.cred.error import UnauthorizedLogin
 from twisted.internet.defer import inlineCallbacks
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.test.test_server import SimpleRequest
 
 from twistedcaldav import authkerb
 import twistedcaldav.test.util

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_link.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_link.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_link.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,9 +14,9 @@
 # limitations under the License.
 ##
 
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError
-from twext.web2.test.test_server import SimpleRequest
+from txweb2 import responsecode
+from txweb2.http import HTTPError
+from txweb2.test.test_server import SimpleRequest
 
 from twisted.internet.defer import inlineCallbacks, succeed
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_memcachelock.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_memcachelock.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_memcachelock.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -5,16 +5,17 @@
 Test the memcache client protocol.
 """
 
-from twext.protocols.memcache import MemCacheProtocol
-
 from twisted.test.proto_helpers import StringTransportWithDisconnection
 from twisted.internet.task import Clock
 from twisted.internet.defer import inlineCallbacks
+from twisted.protocols.memcache import MemCacheProtocol
 
 from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
 
 from twistedcaldav.test.util import TestCase
 
+
+
 class MemCacheTestCase(TestCase):
     """
     Test client protocol class L{MemCacheProtocol}.
@@ -22,22 +23,32 @@
 
     class FakedMemcacheLock(MemcacheLock):
 
-        def __init__(self, faked, namespace, locktoken, timeout=5.0, retry_interval=0.1, expire_time=0):
+        def __init__(
+            self, faked, namespace, locktoken,
+            timeout=5.0, retry_interval=0.1, expire_time=0
+        ):
             """
-
             @param namespace: a unique namespace for this lock's tokens
             @type namespace: C{str}
+
             @param locktoken: the name of the locktoken
             @type locktoken: C{str}
-            @param timeout: the maximum time in seconds that the lock should block
+
+            @param timeout: the maximum time in seconds that the lock should
+                block
             @type timeout: C{float}
+
             @param retry_interval: the interval to retry acquiring the lock
             @type retry_interval: C{float}
-            @param expiryTime: the time in seconds for the lock to expire. Zero: no expiration.
+
+            @param expiryTime: the time in seconds for the lock to expire.
+                Zero: no expiration.
             @type expiryTime: C{float}
             """
 
-            super(MemCacheTestCase.FakedMemcacheLock, self).__init__(namespace, locktoken, timeout, retry_interval, expire_time)
+            super(MemCacheTestCase.FakedMemcacheLock, self).__init__(
+                namespace, locktoken, timeout, retry_interval, expire_time
+            )
             self.faked = faked
 
         def _getMemcacheProtocol(self):
@@ -90,11 +101,16 @@
         called back with the value and the flag associated with the given key
         if the server returns a successful result.
         """
-        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
+        lock = MemCacheTestCase.FakedMemcacheLock(
+            self.proto, "lock", "locking"
+        )
         return self._test(
             lock.get("foo"),
             "get lock:foo-acbd18db4cc2f85cedef654fccc4a4d8\r\n",
-            "VALUE lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 3\r\nbar\r\nEND\r\n",
+            (
+                "VALUE lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 3\r\n"
+                "bar\r\nEND\r\n"
+            ),
             "bar"
         )
 
@@ -105,7 +121,9 @@
         called back with the value and the flag associated with the given key
         if the server returns a successful result.
         """
-        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
+        lock = MemCacheTestCase.FakedMemcacheLock(
+            self.proto, "lock", "locking"
+        )
         return self._test(
             lock.set("foo", "bar"),
             "set lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 0 3\r\nbar\r\n",
@@ -121,7 +139,9 @@
         called back with the value and the flag associated with the given key
         if the server returns a successful result.
         """
-        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
+        lock = MemCacheTestCase.FakedMemcacheLock(
+            self.proto, "lock", "locking"
+        )
         yield self._test(
             lock.acquire(),
             "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
@@ -138,7 +158,9 @@
         called back with the value and the flag associated with the given key
         if the server returns a successful result.
         """
-        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking", timeout=0)
+        lock = MemCacheTestCase.FakedMemcacheLock(
+            self.proto, "lock", "locking", timeout=0
+        )
         yield self._test(
             lock.acquire(),
             "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
@@ -155,11 +177,17 @@
         called back with the value and the flag associated with the given key
         if the server returns a successful result.
         """
-        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking", timeout=0)
+        lock = MemCacheTestCase.FakedMemcacheLock(
+            self.proto, "lock", "locking", timeout=0
+        )
         try:
             yield self._test(
                 lock.acquire(),
-                "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
+                (
+                    "add lock:"
+                    "locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n"
+                    "1\r\n"
+                ),
                 "NOT_STORED\r\n",
                 True
             )
@@ -179,7 +207,9 @@
         called back with the value and the flag associated with the given key
         if the server returns a successful result.
         """
-        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
+        lock = MemCacheTestCase.FakedMemcacheLock(
+            self.proto, "lock", "locking"
+        )
         yield self._test(
             lock.acquire(),
             "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
@@ -203,7 +233,9 @@
         called back with the value and the flag associated with the given key
         if the server returns a successful result.
         """
-        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
+        lock = MemCacheTestCase.FakedMemcacheLock(
+            self.proto, "lock", "locking"
+        )
         yield self._test(
             lock.acquire(),
             "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
@@ -225,7 +257,9 @@
         called back with the value and the flag associated with the given key
         if the server returns a successful result.
         """
-        lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", u"locking")
+        lock = MemCacheTestCase.FakedMemcacheLock(
+            self.proto, "lock", u"locking"
+        )
         yield self._test(
             lock.acquire(),
             "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
@@ -253,7 +287,9 @@
             self.fail("AssertionError not raised")
 
         try:
-            lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", ("abc",))
+            lock = MemCacheTestCase.FakedMemcacheLock(
+                self.proto, "lock", ("abc",)
+            )
             yield lock.acquire()
             self.fail("AssertionError not raised")
         except AssertionError:

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_memcacheprops.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_memcacheprops.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_memcacheprops.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -26,7 +26,7 @@
 
 import os
 
-from twext.web2.http import HTTPError
+from txweb2.http import HTTPError
 
 from txdav.xml.base import encodeXMLName
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_mkcalendar.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_mkcalendar.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_mkcalendar.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -18,11 +18,11 @@
 
 from twisted.internet.defer import inlineCallbacks
 
-from twext.web2 import responsecode
-from twext.web2.iweb import IResponse
-from twext.web2.stream import MemoryStream
+from txweb2 import responsecode
+from txweb2.iweb import IResponse
+from txweb2.stream import MemoryStream
 from txdav.xml import element as davxml
-from twext.web2.dav.fileop import rmdir
+from txweb2.dav.fileop import rmdir
 
 from twistedcaldav import caldavxml
 from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_multiget.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_multiget.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_multiget.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,11 +14,11 @@
 ##
 
 from twext.python.filepath import CachingFilePath as FilePath
-from twext.web2 import responsecode
-from twext.web2.dav.util import davXMLFromStream, joinURL
-from twext.web2.http_headers import Headers, MimeType
-from twext.web2.iweb import IResponse
-from twext.web2.stream import MemoryStream
+from txweb2 import responsecode
+from txweb2.dav.util import davXMLFromStream, joinURL
+from txweb2.http_headers import Headers, MimeType
+from txweb2.iweb import IResponse
+from txweb2.stream import MemoryStream
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_options.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_options.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_options.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,8 +14,8 @@
 # limitations under the License.
 ##
 
-from twext.web2.iweb import IResponse
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.iweb import IResponse
+from txweb2.test.test_server import SimpleRequest
 
 import twistedcaldav.test.util
 from twistedcaldav.config import config

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_props.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_props.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_props.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,10 +14,10 @@
 # limitations under the License.
 ##
 
-from twext.web2 import responsecode, http_headers
-from twext.web2.dav.util import davXMLFromStream
-from twext.web2.iweb import IResponse
-from twext.web2.stream import MemoryStream
+from txweb2 import responsecode, http_headers
+from txweb2.dav.util import davXMLFromStream
+from txweb2.iweb import IResponse
+from txweb2.stream import MemoryStream
 
 from twistedcaldav import caldavxml
 from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,8 +15,8 @@
 ##
 
 from txdav.xml.element import HRef, Principal, Unauthenticated
-from twext.web2.http import HTTPError
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.http import HTTPError
+from txweb2.test.test_server import SimpleRequest
 
 from twisted.internet.defer import inlineCallbacks
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_sharing.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_sharing.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,10 +14,10 @@
 # limitations under the License.
 ##
 
-from twext.web2 import responsecode
-from twext.web2.dav.util import allDataFromStream
-from twext.web2.http_headers import MimeType
-from twext.web2.iweb import IResponse
+from txweb2 import responsecode
+from txweb2.dav.util import allDataFromStream
+from txweb2.http_headers import MimeType
+from txweb2.iweb import IResponse
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_util.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_util.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,7 +14,7 @@
 # limitations under the License.
 ##
 
-from twext.web2.http_headers import Headers
+from txweb2.http_headers import Headers
 
 import twistedcaldav.test.util
 from twistedcaldav.util import bestAcceptType

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_wrapping.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_wrapping.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/test_wrapping.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -19,41 +19,37 @@
 """
 
 
-from twext.web2.responsecode import UNAUTHORIZED
-from twext.web2.http_headers import Headers
 from twext.enterprise.ienterprise import AlreadyFinishedError
+from twext.enterprise.locking import NamedLock
+from txweb2 import responsecode
+from txweb2.http import HTTPError
+from txweb2.http_headers import Headers, MimeType
+from txweb2.responsecode import INSUFFICIENT_STORAGE_SPACE
+from txweb2.responsecode import UNAUTHORIZED
+from txweb2.stream import MemoryStream
 
-from txdav.xml import element as davxml
-from twistedcaldav.config import config
-
 from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.internet.defer import maybeDeferred
 
+from twistedcaldav.config import config
+from twistedcaldav.directory.test.test_xmlfile import XMLFileBase
 from twistedcaldav.ical import Component as VComponent
-from twistedcaldav.vcard import Component as VCComponent
-
 from twistedcaldav.storebridge import DropboxCollection, \
     CalendarCollectionResource
-
 from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
+from twistedcaldav.vcard import Component as VCComponent
 
-from txdav.idav import IDataStore
+from txdav.caldav.datastore.file import Calendar
 from txdav.caldav.datastore.test.test_file import test_event_text
-
+from txdav.caldav.icalendarstore import ICalendarHome
 from txdav.carddav.datastore.test.test_file import vcard4_text
-
+from txdav.carddav.iaddressbookstore import IAddressBookHome
 from txdav.common.datastore.test.util import assertProvides
-
-
-from twext.web2.http import HTTPError
-from twext.web2.responsecode import INSUFFICIENT_STORAGE_SPACE
-from twext.web2.stream import MemoryStream
 from txdav.common.datastore.test.util import deriveQuota
-from twistedcaldav.directory.test.test_xmlfile import XMLFileBase
-from txdav.caldav.icalendarstore import ICalendarHome
-from txdav.carddav.iaddressbookstore import IAddressBookHome
+from txdav.idav import IDataStore
+from txdav.xml import element as davxml
 
-from twisted.internet.defer import maybeDeferred
-from txdav.caldav.datastore.file import Calendar
+import hashlib
 
 def _todo(f, why):
     f.todo = why
@@ -560,3 +556,90 @@
         self.requestUnderTest = None
         yield self.assertCalendarEmpty(wsanchez)
         yield self.assertCalendarEmpty(cdaboo)
+
+
+
+class TimeoutTests(StoreTestCase):
+    """
+    Tests for L{twistedcaldav.storebridge} lock timeouts.
+    """
+
+    @inlineCallbacks
+    def test_timeoutOnPUT(self):
+        """
+        PUT gets a 503 on a lock timeout.
+        """
+
+        # Create a fake lock
+        txn = self.transactionUnderTest()
+        yield NamedLock.acquire(txn, "ImplicitUIDLock:%s" % (hashlib.md5("uid1").hexdigest(),))
+
+        # PUT fails
+        request = SimpleStoreRequest(
+            self,
+            "PUT",
+            "/calendars/users/wsanchez/calendar/1.ics",
+            headers=Headers({"content-type": MimeType.fromString("text/calendar")}),
+            authid="wsanchez"
+        )
+        request.stream = MemoryStream("""BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Apple Computer\, Inc//iCal 2.0//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:uid1
+DTSTART;VALUE=DATE:20020101
+DTEND;VALUE=DATE:20020102
+DTSTAMP:20020101T121212Z
+SUMMARY:New Year's Day
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n"))
+        response = yield self.send(request)
+        self.assertEqual(response.code, responsecode.SERVICE_UNAVAILABLE)
+
+
+    @inlineCallbacks
+    def test_timeoutOnDELETE(self):
+        """
+        DELETE gets a 503 on a lock timeout.
+        """
+
+        # PUT works
+        request = SimpleStoreRequest(
+            self,
+            "PUT",
+            "/calendars/users/wsanchez/calendar/1.ics",
+            headers=Headers({"content-type": MimeType.fromString("text/calendar")}),
+            authid="wsanchez"
+        )
+        request.stream = MemoryStream("""BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Apple Computer\, Inc//iCal 2.0//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:uid1
+DTSTART;VALUE=DATE:20020101
+DTEND;VALUE=DATE:20020102
+DTSTAMP:20020101T121212Z
+ORGANIZER:mailto:wsanchez at example.com
+ATTENDEE:mailto:wsanchez at example.com
+SUMMARY:New Year's Day
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n"))
+        response = yield self.send(request)
+        self.assertEqual(response.code, responsecode.CREATED)
+
+        # Create a fake lock
+        txn = self.transactionUnderTest()
+        yield NamedLock.acquire(txn, "ImplicitUIDLock:%s" % (hashlib.md5("uid1").hexdigest(),))
+
+        request = SimpleStoreRequest(
+            self,
+            "DELETE",
+            "/calendars/users/wsanchez/calendar/1.ics",
+            authid="wsanchez"
+        )
+        response = yield self.send(request)
+        self.assertEqual(response.code, responsecode.SERVICE_UNAVAILABLE)

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/util.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/test/util.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -26,13 +26,13 @@
 from twisted.internet.defer import succeed, fail, inlineCallbacks, returnValue
 from twisted.internet.protocol import ProcessProtocol
 
-from twext.python.memcacheclient import ClientFactory
 from twext.python.filepath import CachingFilePath as FilePath
-import twext.web2.dav.test.util
+import txweb2.dav.test.util
 from txdav.xml import element as davxml, element
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2.http import HTTPError, StatusResponse
 
 from twistedcaldav import memcacher
+from twistedcaldav.memcacheclient import ClientFactory
 from twistedcaldav.bind import doBind
 from twistedcaldav.directory import augment
 from twistedcaldav.directory.addressbook import DirectoryAddressBookHomeProvisioningResource
@@ -52,7 +52,7 @@
 from twext.python.log import Logger
 from txdav.caldav.datastore.test.util import buildCalendarStore
 from calendarserver.tap.util import getRootResource, directoryFromConfig
-from twext.web2.dav.test.util import SimpleRequest
+from txweb2.dav.test.util import SimpleRequest
 from twistedcaldav.directory.util import transactionFromRequest
 from twistedcaldav.directory.directory import DirectoryService
 
@@ -187,7 +187,7 @@
 
 
 
-class StoreTestCase(CommonCommonTests, twext.web2.dav.test.util.TestCase):
+class StoreTestCase(CommonCommonTests, txweb2.dav.test.util.TestCase):
     """
     A base class for tests that use the SQL store.
     """
@@ -268,7 +268,7 @@
 
 
 
-class TestCase(twext.web2.dav.test.util.TestCase):
+class TestCase(txweb2.dav.test.util.TestCase):
     resource_class = RootResource
 
     def createDataStore(self):

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/timezoneservice.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/timezoneservice.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/timezoneservice.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -22,17 +22,17 @@
     "TimezoneServiceResource",
 ]
 
-from twext.web2.dav.http import ErrorResponse
+from txweb2.dav.http import ErrorResponse
 
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.xml import element as davxml
-from twext.web2.dav.method.propfind import http_PROPFIND
-from twext.web2.dav.noneprops import NonePropertyStore
-from twext.web2.http import HTTPError
-from twext.web2.http import Response
-from twext.web2.http import XMLResponse
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import MemoryStream
+from txweb2.dav.method.propfind import http_PROPFIND
+from txweb2.dav.noneprops import NonePropertyStore
+from txweb2.http import HTTPError
+from txweb2.http import Response
+from txweb2.http import XMLResponse
+from txweb2.http_headers import MimeType
+from txweb2.stream import MemoryStream
 
 from twisted.internet.defer import succeed
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/timezonestdservice.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/timezonestdservice.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/timezonestdservice.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -26,13 +26,13 @@
 ]
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.dav.method.propfind import http_PROPFIND
-from twext.web2.dav.noneprops import NonePropertyStore
-from twext.web2.http import HTTPError, JSONResponse
-from twext.web2.http import Response
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import MemoryStream
+from txweb2 import responsecode
+from txweb2.dav.method.propfind import http_PROPFIND
+from txweb2.dav.noneprops import NonePropertyStore
+from txweb2.http import HTTPError, JSONResponse
+from txweb2.http import Response
+from txweb2.http_headers import MimeType
+from txweb2.stream import MemoryStream
 from txdav.xml import element as davxml
 
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue, \

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/upgrade.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/upgrade.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -34,7 +34,7 @@
 
 from twext.python.log import Logger
 from txdav.xml import element
-from twext.web2.dav.fileop import rmdir
+from txweb2.dav.fileop import rmdir
 
 from twistedcaldav import caldavxml
 from twistedcaldav.directory import calendaruserproxy

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/util.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/util.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -35,14 +35,20 @@
 ##
 
 try:
-    from ctypes import *
-    import ctypes.util
+    from ctypes import (
+        cdll,
+        c_int, c_uint64, c_ulong,
+        c_char_p, c_void_p,
+        addressof, sizeof, c_size_t,
+        connect,
+    )
+    from ctypes.util import find_library
     hasCtypes = True
 except ImportError:
     hasCtypes = False
 
 if sys.platform == "darwin" and hasCtypes:
-    libc = cdll.LoadLibrary(ctypes.util.find_library("libc"))
+    libc = cdll.LoadLibrary(find_library("libc"))
 
     def getNCPU():
         """
@@ -56,8 +62,8 @@
         ]
         libc.sysctlbyname(
             "hw.ncpu",
-            c_voidp(addressof(ncpu)),
-            c_voidp(addressof(size)),
+            c_void_p(addressof(ncpu)),
+            c_void_p(addressof(size)),
             None,
             0
         )
@@ -77,8 +83,8 @@
         ]
         libc.sysctlbyname(
             "hw.memsize",
-            c_voidp(addressof(memsize)),
-            c_voidp(addressof(size)),
+            c_void_p(addressof(memsize)),
+            c_void_p(addressof(size)),
             None,
             0
         )
@@ -87,7 +93,7 @@
 
 
 elif sys.platform == "linux2" and hasCtypes:
-    libc = cdll.LoadLibrary(ctypes.util.find_library("libc"))
+    libc = cdll.LoadLibrary(find_library("libc"))
 
     def getNCPU():
         return libc.get_nprocs()

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/vcard.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/vcard.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/twistedcaldav/vcard.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -28,8 +28,8 @@
 import codecs
 
 from twext.python.log import Logger
-from twext.web2.stream import IStream
-from twext.web2.dav.util import allDataFromStream
+from txweb2.stream import IStream
+from txweb2.dav.util import allDataFromStream
 
 from twistedcaldav.config import config
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/__init__.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/__init__.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -18,7 +18,3 @@
 """
 WebDAV support for Twisted.
 """
-
-# Make sure we have twext's required Twisted patches loaded before we do
-# anything at all.
-__import__("twext")

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/datastore/file.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/datastore/file.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -26,7 +26,7 @@
 
 from twext.python.log import Logger
 from twext.enterprise.ienterprise import AlreadyFinishedError
-from twext.web2.dav.resource import TwistedGETContentMD5
+from txweb2.dav.resource import TwistedGETContentMD5
 from txdav.idav import IDataStoreObject
 from txdav.base.propertystore.base import PropertyName
 from txdav.xml.element import GETContentType

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/datastore/subpostgres.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/datastore/subpostgres.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/datastore/subpostgres.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -167,7 +167,7 @@
     def __init__(self, dataStoreDirectory, subServiceFactory,
                  schema, resetSchema=False, databaseName='subpostgres',
                  clusterName="cluster",
-                 logFile="postgres.log", socketDir="/tmp",
+                 logFile="postgres.log", socketDir="",
                  listenAddresses=[], sharedBuffers=30,
                  maxConnections=20, options=[],
                  testMode=False,
@@ -223,20 +223,15 @@
             self.host, self.port = listenAddresses[0].split(":") if ":" in listenAddresses[0] else (listenAddresses[0], None,)
             self.listenAddresses = [addr.split(":")[0] for addr in listenAddresses]
         else:
-            if socketDir:
-                # Unix socket length path limit
-                self.socketDir = CachingFilePath("%s/ccs_postgres_%s/" %
-                    (socketDir, md5(dataStoreDirectory.path).hexdigest()))
-                if len(self.socketDir.path) > 64:
-                    socketDir = "/tmp"
-                    self.socketDir = CachingFilePath("/tmp/ccs_postgres_%s/" %
-                        (md5(dataStoreDirectory.path).hexdigest()))
-                self.host = self.socketDir.path
-                self.port = None
-            else:
-                self.socketDir = None
-                self.host = "localhost"
-                self.port = None
+            if not socketDir:
+                # Socket directory was not specified, so come up with one
+                # in /tmp and based on a hash of the data store directory
+                digest = md5(dataStoreDirectory.path).hexdigest()
+                socketDir = "/tmp/ccs_postgres_" + digest
+                
+            self.socketDir = CachingFilePath(socketDir)
+            self.host = self.socketDir.path
+            self.port = None
             self.listenAddresses = []
         self.sharedBuffers = sharedBuffers if not testMode else 16
         self.maxConnections = maxConnections if not testMode else 4

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/propertystore/base.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/propertystore/base.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/propertystore/base.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -26,7 +26,7 @@
 from twext.python.log import Logger
 from txdav.xml import element as davxml
 from txdav.xml.base import encodeXMLName
-from twext.web2.dav.resource import TwistedGETContentMD5, \
+from txweb2.dav.resource import TwistedGETContentMD5, \
     TwistedQuotaRootProperty
 
 from txdav.idav import IPropertyStore, IPropertyName

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/propertystore/xattr.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/propertystore/xattr.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/base/propertystore/xattr.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -65,7 +65,7 @@
 
     # Mimic old xattr-prefix behavior by importing it directly.
     deadPropertyXattrPrefix = namedAny(
-        "twext.web2.dav.xattrprops.xattrPropertyStore.deadPropertyXattrPrefix"
+        "txweb2.dav.xattrprops.xattrPropertyStore.deadPropertyXattrPrefix"
     )
 
     # There is a 127 character limit for xattr keys so we need to

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/file.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/file.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -35,11 +35,11 @@
 
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed, fail
 
-from twext.python.vcomponent import VComponent
+from twistedcaldav.ical import Component as VComponent
 from txdav.xml import element as davxml
 from txdav.xml.rfc2518 import GETContentType
-from twext.web2.dav.resource import TwistedGETContentMD5
-from twext.web2.http_headers import generateContentType, MimeType
+from txweb2.dav.resource import TwistedGETContentMD5
+from txweb2.http_headers import generateContentType, MimeType
 
 from twistedcaldav import caldavxml, customxml, ical
 from twistedcaldav.caldavxml import ScheduleCalendarTransp, Opaque, Transparent
@@ -78,6 +78,8 @@
 
 IGNORE_NAMES = ('dropbox', 'notification', 'freebusy')
 
+
+
 class CalendarHome(CommonHome):
     implements(ICalendarHome)
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/caldav/delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/caldav/delivery.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/caldav/delivery.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,12 +15,12 @@
 ##
 
 from twext.python.log import Logger, LogLevel
-from twext.web2.dav.http import ErrorResponse
+from txweb2.dav.http import ErrorResponse
 
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 from twisted.python.failure import Failure
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError
+from txweb2 import responsecode
+from txweb2.http import HTTPError
 
 from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.config import config

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/caldav/scheduler.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/caldav/scheduler.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/caldav/scheduler.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,9 +15,9 @@
 ##
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.dav.http import ErrorResponse
-from twext.web2.http import HTTPError, StatusResponse
+from txweb2 import responsecode
+from txweb2.dav.http import ErrorResponse
+from txweb2.http import HTTPError, StatusResponse
 
 from twisted.internet.defer import inlineCallbacks
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/delivery.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/delivery.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -21,9 +21,9 @@
 
 from twext.enterprise.queue import inTransaction
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.dav.http import ErrorResponse
-from twext.web2.http import HTTPError
+from txweb2 import responsecode
+from txweb2.dav.http import ErrorResponse
+from txweb2.http import HTTPError
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python.failure import Failure
 from twistedcaldav.caldavxml import caldav_namespace

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/scheduler.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/scheduler.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/scheduler.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,7 +15,7 @@
 ##
 
 from twext.python.log import Logger
-from twext.web2.dav.http import ErrorResponse
+from txweb2.dav.http import ErrorResponse
 from twisted.internet.defer import succeed
 from twistedcaldav.caldavxml import caldav_namespace
 from txdav.caldav.datastore.scheduling.cuaddress import RemoteCalendarUser

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/imip/test/test_delivery.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,7 +14,7 @@
 # limitations under the License.
 ##
 
-from twext.web2 import responsecode
+from txweb2 import responsecode
 
 from twisted.internet.defer import inlineCallbacks
 from twisted.trial import unittest

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/implicit.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/implicit.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/implicit.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,11 +15,11 @@
 ##
 
 from twext.python.log import Logger
-from twext.web2.dav.http import ErrorResponse
+from txweb2.dav.http import ErrorResponse
 
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError
+from txweb2 import responsecode
+from txweb2.http import HTTPError
 
 from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.config import config

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/delivery.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/delivery.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/delivery.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -20,15 +20,15 @@
 
 from twext.internet.gaiendpoint import GAIEndpoint
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.client.http import ClientRequest
-from twext.web2.client.http import HTTPClientProtocol
-from twext.web2.dav.http import ErrorResponse
-from twext.web2.dav.util import davXMLFromStream, joinURL, allDataFromStream
-from twext.web2.http import HTTPError
-from twext.web2.http_headers import Headers
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import MemoryStream
+from txweb2 import responsecode
+from txweb2.client.http import ClientRequest
+from txweb2.client.http import HTTPClientProtocol
+from txweb2.dav.http import ErrorResponse
+from txweb2.dav.util import davXMLFromStream, joinURL, allDataFromStream
+from txweb2.http import HTTPError
+from txweb2.http_headers import Headers
+from txweb2.http_headers import MimeType
+from txweb2.stream import MemoryStream
 
 from twisted.internet.defer import inlineCallbacks, DeferredList, returnValue
 from twisted.internet.protocol import Factory

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/dkim.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/dkim.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/dkim.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,11 +15,11 @@
 ##
 
 from twext.python.log import Logger
-from twext.web2.client.http import ClientRequest
-from twext.web2.dav.util import allDataFromStream, joinURL
-from twext.web2.http import Response
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import MemoryStream
+from txweb2.client.http import ClientRequest
+from txweb2.dav.util import allDataFromStream, joinURL
+from txweb2.http import Response
+from txweb2.http_headers import MimeType
+from txweb2.stream import MemoryStream
 
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 from twistedcaldav.client.geturl import getURL
@@ -516,7 +516,7 @@
     def __init__(self, headers, body, key_lookup=None, protocol_debug=False):
         """
         @param headers: The HTTP request headers to process
-        @type headers: L{twext.web2.http_headers.Headers}
+        @type headers: L{txweb2.http_headers.Headers}
         @param body: The HTTP request body to process
         @type body: C{str}
         """

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -17,12 +17,12 @@
 from pycalendar.datetime import DateTime
 from pycalendar.timezone import Timezone
 
-from twext.web2 import responsecode
-from twext.web2.dav.http import ErrorResponse
-from twext.web2.dav.noneprops import NonePropertyStore
-from twext.web2.dav.util import allDataFromStream
-from twext.web2.http import Response, HTTPError, StatusResponse, XMLResponse
-from twext.web2.http_headers import MimeType
+from txweb2 import responsecode
+from txweb2.dav.http import ErrorResponse
+from txweb2.dav.noneprops import NonePropertyStore
+from txweb2.dav.util import allDataFromStream
+from txweb2.http import Response, HTTPError, StatusResponse, XMLResponse
+from txweb2.http_headers import MimeType
 
 from twisted.internet.defer import succeed, returnValue, inlineCallbacks
 from twisted.python.failure import Failure

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/scheduler.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/scheduler.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/scheduler.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,9 +15,9 @@
 ##
 
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError, Response
-from twext.web2.http_headers import MimeType
+from txweb2 import responsecode
+from txweb2.http import HTTPError, Response
+from txweb2.http_headers import MimeType
 
 from twisted.internet.abstract import isIPAddress
 from twisted.internet.defer import inlineCallbacks, returnValue

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -16,9 +16,9 @@
 
 from Crypto.PublicKey import RSA
 
-from twext.web2.dav.util import allDataFromStream
-from twext.web2.http_headers import Headers, MimeType
-from twext.web2.stream import MemoryStream
+from txweb2.dav.util import allDataFromStream
+from txweb2.http_headers import Headers, MimeType
+from txweb2.stream import MemoryStream
 
 from twisted.internet.defer import inlineCallbacks, succeed
 from twisted.names import client

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,7 +14,7 @@
 # limitations under the License.
 ##
 
-from twext.web2.test.test_server import SimpleRequest
+from txweb2.test.test_server import SimpleRequest
 
 from twisted.trial import unittest
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/ischedule/test/test_resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,8 +14,8 @@
 # limitations under the License.
 ##
 
-from twext.web2 import http_headers, responsecode
-from twext.web2.test.test_server import SimpleRequest
+from txweb2 import http_headers, responsecode
+from txweb2.test.test_server import SimpleRequest
 
 from twisted.internet.defer import inlineCallbacks
 
@@ -28,10 +28,10 @@
 from txdav.common.datastore.test.util import populateCalendarsFrom, \
     CommonCommonTests
 from twext.python.clsprop import classproperty
-import twext.web2.dav.test.util
+import txweb2.dav.test.util
 from txdav.caldav.datastore.test.util import buildCalendarStore
 
-class iSchedulePOST (CommonCommonTests, twext.web2.dav.test.util.TestCase):
+class iSchedulePOST (CommonCommonTests, txweb2.dav.test.util.TestCase):
 
     @inlineCallbacks
     def setUp(self):

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/itip.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/itip.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/itip.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -309,8 +309,8 @@
             calendar_master.addProperty(Property("EXDATE", exdates))
 
         # See if there are still components in the calendar - we might have deleted the last overridden instance
-        # in which case the calendar object is empty (except for VTIMEZONEs).
-        if calendar.mainType() is None:
+        # in which case the calendar object is empty (except for VTIMEZONEs) or has only hidden components.
+        if calendar.mainType() is None or calendar.hasPropertyValueInAllComponents(Property(Component.HIDDEN_INSTANCE_PROPERTY, "T")):
             # Delete the now empty calendar object
             return True, True, None
         else:

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/processing.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/processing.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/processing.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -19,8 +19,8 @@
 from pycalendar.timezone import Timezone
 
 from twext.python.log import Logger
-from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
-from twext.web2.http import HTTPError
+from txweb2.dav.method.report import NumberOfMatchesWithinLimits
+from txweb2.http import HTTPError
 
 from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks, returnValue

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/scheduler.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/scheduler.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/scheduler.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -19,11 +19,11 @@
 
 from twext.enterprise.locking import NamedLock
 from twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError, Response
-from twext.web2.http_headers import MimeType
+from txweb2 import responsecode
+from txweb2.http import HTTPError, Response
+from txweb2.http_headers import MimeType
 from txdav.xml import element as davxml
-from twext.web2.dav.http import messageForFailure, statusForFailure, \
+from txweb2.dav.http import messageForFailure, statusForFailure, \
     ErrorResponse
 
 from twistedcaldav import caldavxml

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/test/test_implicit.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/test/test_implicit.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/scheduling/test/test_implicit.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -18,8 +18,8 @@
 from pycalendar.timezone import Timezone
 
 from twext.python.clsprop import classproperty
-from twext.web2 import responsecode
-from twext.web2.http import HTTPError
+from txweb2 import responsecode
+from txweb2.http import HTTPError
 
 from twisted.internet import reactor
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/sql.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/sql.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -14,7 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
-from txdav.xml import element
 
 
 """
@@ -41,9 +40,9 @@
 from twext.python.clsprop import classproperty
 from twext.python.filepath import CachingFilePath
 from twext.python.log import Logger
-from twext.python.vcomponent import VComponent
-from twext.web2.http_headers import MimeType, generateContentType
-from twext.web2.stream import readStream
+from twistedcaldav.ical import Component as VComponent
+from txweb2.http_headers import MimeType, generateContentType
+from txweb2.stream import readStream
 
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 from twisted.python import hashlib
@@ -73,7 +72,7 @@
     AttendeeAllowedError, InvalidPerUserDataMerge, ComponentUpdateState, \
     ValidOrganizerError, ShareeAllowedError, ComponentRemoveState, \
     InvalidDefaultCalendar, \
-    InvalidAttachmentOperation
+    InvalidAttachmentOperation, DuplicatePrivateCommentsError
 from txdav.caldav.icalendarstore import QuotaExceeded
 from txdav.common.datastore.sql import CommonHome, CommonHomeChild, \
     CommonObjectResource, ECALENDARTYPE
@@ -89,6 +88,7 @@
     ObjectResourceNameNotAllowedError, TooManyObjectResourcesError, \
     InvalidUIDError, UIDExistsError, UIDExistsElsewhereError, \
     InvalidResourceMove, InvalidComponentForStoreError
+from txdav.xml import element
 
 from txdav.idav import ChangeCategory
 
@@ -109,6 +109,8 @@
 
 log = Logger()
 
+
+
 class CalendarStoreFeatures(object):
     """
     Manages store-wide operations specific to calendars.
@@ -580,6 +582,14 @@
         returnValue(self._cachedCalendarResourcesForUID[uid])
 
 
+    def removedCalendarResource(self, uid):
+        """
+        Clean-up cache when resource is removed.
+        """
+        if hasattr(self, "_cachedCalendarResourcesForUID") and uid in self._cachedCalendarResourcesForUID:
+            del self._cachedCalendarResourcesForUID[uid]
+
+
     @inlineCallbacks
     def calendarObjectWithDropboxID(self, dropboxID):
         """
@@ -1069,6 +1079,12 @@
         returnValue(objectResource)
 
 
+    @inlineCallbacks
+    def removedObjectResource(self, child):
+        yield super(Calendar, self).removedObjectResource(child)
+        self.viewerHome().removedCalendarResource(child.uid())
+
+
     def calendarObjectsInTimeRange(self, start, end, timeZone):
         raise NotImplementedError()
 
@@ -1790,7 +1806,14 @@
 
             self.hasPrivateComment = new_has_private_comments
 
+            # Some clients appear to be buggy and are duplicating the "X-CALENDARSERVER-ATTENDEE-COMMENT" comment. We want
+            # to raise an error to prevent that so the client bugs can be tracked down.
 
+            # Look for properties with duplicate "X-CALENDARSERVER-ATTENDEE-REF" values in the same component
+            if component.hasDuplicatePrivateComments(doFix=config.RemoveDuplicatePrivateComments):
+                raise DuplicatePrivateCommentsError("Duplicate X-CALENDARSERVER-ATTENDEE-COMMENT properties present.")
+
+
     @inlineCallbacks
     def replaceMissingToDoProperties(self, calendar, inserting, internal_state):
         """
@@ -1970,6 +1993,43 @@
             self._componentChanged = True
 
 
+    def addStructuredLocation(self, component):
+        """
+        Scan the component for ROOM attendees; if any are associated with an
+        address record which has street address and geo coordinates, add an
+        X-APPLE-STRUCTURED-LOCATION property and update the LOCATION property
+        to contain the name and street address.
+        """
+        for sub in component.subcomponents():
+            for attendee in sub.getAllAttendeeProperties():
+                if attendee.parameterValue("CUTYPE") == "ROOM":
+                    value = attendee.value()
+                    if value.startswith("urn:uuid:"):
+                        guid = value[9:]
+                        loc = self.directoryService().recordWithGUID(guid)
+                        if loc is not None:
+                            guid = loc.extras.get("associatedAddress",
+                                None)
+                            if guid is not None:
+                                addr = self.directoryService().recordWithGUID(guid)
+                                if addr is not None:
+                                    street = addr.extras.get("streetAddress", "")
+                                    geo = addr.extras.get("geo", "")
+                                    if street and geo:
+                                        title = attendee.parameterValue("CN")
+                                        params = {
+                                            "X-ADDRESS" : street,
+                                            "X-APPLE-RADIUS" : "71",
+                                            "X-TITLE" : title,
+                                        }
+                                        structured = Property("X-APPLE-STRUCTURED-LOCATION",
+                                            "geo:%s" % (geo,), params=params,
+                                            valuetype=Value.VALUETYPE_URI)
+                                        sub.replaceProperty(structured)
+                                        sub.replaceProperty(Property("LOCATION",
+                                            "%s\n%s" % (title, street)))
+
+
     @inlineCallbacks
     def doImplicitScheduling(self, component, inserting, internal_state, split_details=None):
 
@@ -2182,6 +2242,9 @@
             # Default/duplicate alarms
             self.processAlarms(component, inserting)
 
+            # Process structured location
+            self.addStructuredLocation(component)
+
             # Do scheduling
             implicit_result = (yield self.doImplicitScheduling(component, inserting, internal_state))
             if isinstance(implicit_result, int):
@@ -2242,7 +2305,7 @@
         elif internal_state == ComponentUpdateState.ORGANIZER_ITIP_UPDATE:
             category = ChangeCategory.organizerITIPUpdate
         elif (internal_state == ComponentUpdateState.ATTENDEE_ITIP_UPDATE and
-            hasattr(self._txn, "doing_attende_refresh")):
+            hasattr(self._txn, "doing_attendee_refresh")):
             category = ChangeCategory.attendeeITIPUpdate
 
         yield self._calendar.notifyChanged(category=category)
@@ -2681,6 +2744,19 @@
             yield scheduler.doImplicitScheduling()
 
 
+    def removeNotifyCategory(self):
+        """
+        Indicates what category to use when determining the priority of push
+        notifications when this object is removed.
+
+        @returns: The "inbox" category if this object is in the inbox, otherwise
+            the "default" category
+        @rtype: L{ChangeCategory}
+        """
+        return (ChangeCategory.inbox if self._calendar.isInbox() else
+                ChangeCategory.default)
+
+
     @classproperty
     def _recurrenceMinMaxByIDQuery(cls): #@NoSelf
         """

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/common.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/common.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -27,7 +27,7 @@
 from twisted.python import hashlib
 
 from twext.python.clsprop import classproperty
-from twext.python.vcomponent import VComponent
+from twistedcaldav.ical import Component as VComponent
 from twext.python.filepath import CachingFilePath as FilePath
 from twext.enterprise.ienterprise import AlreadyFinishedError
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_attachments.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_attachments.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_attachments.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -21,8 +21,8 @@
 
 from twext.enterprise.dal.syntax import Delete
 from twext.python.clsprop import classproperty
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import MemoryStream
+from txweb2.http_headers import MimeType
+from txweb2.stream import MemoryStream
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python.filepath import FilePath

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_file.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_file.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_file.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -28,7 +28,7 @@
 
 from twext.python.filepath import CachingFilePath as FilePath
 
-from twext.python.vcomponent import VComponent
+from twistedcaldav.ical import Component as VComponent
 
 from txdav.common.icommondatastore import HomeChildNameNotAllowedError
 from txdav.common.icommondatastore import ObjectResourceNameNotAllowedError

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_sql.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_sql.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -18,7 +18,7 @@
     LocalCalendarUser
 from txdav.caldav.datastore.scheduling.caldav.scheduler import CalDAVScheduler
 from txdav.caldav.datastore.scheduling.scheduler import ScheduleResponseQueue
-from twext.web2 import responsecode
+from txweb2 import responsecode
 from txdav.caldav.datastore.scheduling.itip import iTIPRequestStatus
 from twistedcaldav.instance import InvalidOverriddenInstanceError
 
@@ -32,9 +32,9 @@
 
 from twext.enterprise.dal.syntax import Select, Parameter, Insert, Delete, \
     Update
-from twext.python.vcomponent import VComponent
-from twext.web2.http_headers import MimeType
-from twext.web2.stream import MemoryStream
+from twistedcaldav.ical import Component as VComponent
+from txweb2.http_headers import MimeType
+from txweb2.stream import MemoryStream
 
 from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks, returnValue, DeferredList, \
@@ -64,6 +64,7 @@
     CommonCommonTests
 from txdav.common.icommondatastore import NoSuchObjectResourceError
 from txdav.xml.rfc2518 import GETContentLanguage, ResourceType
+from txdav.idav import ChangeCategory
 
 import datetime
 
@@ -915,6 +916,32 @@
 
 
     @inlineCallbacks
+    def test_removeNotifyCategoryInbox(self):
+        """
+        Inbox object removal should be categorized as ChangeCategory.inbox
+        """
+        home = yield self.homeUnderTest()
+        inbox = yield home.createCalendarWithName("inbox")
+        component = VComponent.fromString(test_event_text)
+        inboxItem = yield inbox.createCalendarObjectWithName("inbox.ics", component)
+        self.assertEquals(ChangeCategory.inbox, inboxItem.removeNotifyCategory())
+        yield self.commit()
+
+
+    @inlineCallbacks
+    def test_removeNotifyCategoryNonInbox(self):
+        """
+        Non-Inbox object removal should be categorized as ChangeCategory.default
+        """
+        home = yield self.homeUnderTest()
+        nonInbox = yield home.createCalendarWithName("noninbox")
+        component = VComponent.fromString(test_event_text)
+        nonInboxItem = yield nonInbox.createCalendarObjectWithName("inbox.ics", component)
+        self.assertEquals(ChangeCategory.default, nonInboxItem.removeNotifyCategory())
+        yield self.commit()
+
+
+    @inlineCallbacks
     def test_directShareCreateConcurrency(self):
         """
         Test that two concurrent attempts to create a direct shared calendar
@@ -2050,7 +2077,82 @@
         self.assertEqual(len(self.flushLoggedErrors(InvalidOverriddenInstanceError)), 1)
 
 
+    @inlineCallbacks
+    def test_setComponent_structuredLocation(self):
+        """
+        Verify ROOM attendees who have street address and geo information
+        within the directory will get X-APPLE-STRUCTURED-LOCATION properties
+        added, as well as updated LOCATION properties.
+        """
 
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//Apple Inc.//Mac OS X 10.9.1//EN
+BEGIN:VEVENT
+UID:561F5DBB-3F38-4B3A-986F-DD05CBAF554F
+DTSTART;TZID=America/Los_Angeles:20131211T164500
+DTEND;TZID=America/Los_Angeles:20131211T174500
+ATTENDEE;CN=Conference Room One;CUTYPE=ROOM;PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPAN
+ T;SCHEDULE-STATUS=2.0:urn:uuid:room1
+ATTENDEE;CN=User 01;CUTYPE=INDIVIDUAL;EMAIL=user01 at example.com;PARTSTAT=AC
+ CEPTED:urn:uuid:user01
+CREATED:20131211T221854Z
+DTSTAMP:20131211T230632Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+RRULE:FREQ=DAILY;COUNT=5
+SEQUENCE:8
+SUMMARY:locations
+TRANSP:OPAQUE
+END:VEVENT
+BEGIN:VEVENT
+UID:561F5DBB-3F38-4B3A-986F-DD05CBAF554F
+RECURRENCE-ID;TZID=America/Los_Angeles:20131214T164500
+DTSTART;TZID=America/Los_Angeles:20131214T160000
+DTEND;TZID=America/Los_Angeles:20131214T170000
+ATTENDEE;CN=Conference Room Two;CUTYPE=ROOM;PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPAN
+ T;SCHEDULE-STATUS=2.0:urn:uuid:room2
+ATTENDEE;CN=User 01;CUTYPE=INDIVIDUAL;EMAIL=user01 at example.com;PARTSTAT=AC
+ CEPTED:urn:uuid:user01
+CREATED:20131211T221854Z
+DTSTAMP:20131211T230632Z
+ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
+SEQUENCE:8
+SUMMARY:locations
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+        calendar = yield self.calendarUnderTest(name="calendar", home="user01")
+        yield calendar.createCalendarObjectWithName("structured.ics",
+            Component.fromString(data))
+        cobj = yield self.calendarObjectUnderTest(name="structured.ics",
+            calendar_name="calendar", home="user01")
+        comp = yield cobj.component()
+        components = list(comp.subcomponents())
+
+        # Check first component
+        locProp = components[0].getProperty("LOCATION")
+        self.assertEquals(locProp.value(),
+            "Conference Room One\n1 Infinite Loop, Cupertino, CA 95014")
+        structProp = components[0].getProperty("X-APPLE-STRUCTURED-LOCATION")
+        self.assertEquals(structProp.value(),
+            "geo:37.331741,-122.030333")
+
+        # Check second component
+        locProp = components[1].getProperty("LOCATION")
+        self.assertEquals(locProp.value(),
+            "Conference Room Two\n2 Infinite Loop, Cupertino, CA 95014")
+        structProp = components[1].getProperty("X-APPLE-STRUCTURED-LOCATION")
+        self.assertEquals(structProp.value(),
+            "geo:37.332633,-122.030502")
+
+        yield self.commit()
+
+
+
+
 class CalendarObjectSplitting(CommonCommonTests, unittest.TestCase):
     """
     CalendarObject splitting tests

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_util.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/test_util.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -22,7 +22,7 @@
 import textwrap
 
 from twisted.trial.unittest import TestCase as BaseTestCase
-from twext.web2.http_headers import MimeType
+from txweb2.http_headers import MimeType
 
 from twisted.internet.defer import inlineCallbacks
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/util.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/test/util.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -62,9 +62,11 @@
         calendarUserAddresses,
         cutype="INDIVIDUAL",
         thisServer=True,
+        extras={},
     ):
 
-        super(TestCalendarStoreDirectoryRecord, self).__init__(uid, shortNames, fullName)
+        super(TestCalendarStoreDirectoryRecord, self).__init__(uid, shortNames,
+            fullName, extras=extras)
         self.uid = uid
         self.shortNames = shortNames
         self.fullName = fullName
@@ -158,6 +160,36 @@
     for uid in homes:
         directory.addRecord(buildDirectoryRecord(uid))
 
+    # Structured Locations
+    directory.addRecord(TestCalendarStoreDirectoryRecord(
+        "il1", ("il1",), "1 Infinite Loop", [],
+        extras={
+            "geo" : "37.331741,-122.030333",
+            "streetAddress" : "1 Infinite Loop, Cupertino, CA 95014",
+        }
+    ))
+    directory.addRecord(TestCalendarStoreDirectoryRecord(
+        "il2", ("il2",), "2 Infinite Loop", [],
+        extras={
+            "geo" : "37.332633,-122.030502",
+            "streetAddress" : "2 Infinite Loop, Cupertino, CA 95014",
+        }
+    ))
+    directory.addRecord(TestCalendarStoreDirectoryRecord(
+        "room1", ("room1",), "Conference Room One",
+        frozenset(("urn:uuid:room1",)),
+        extras={
+            "associatedAddress" : "il1",
+        }
+    ))
+    directory.addRecord(TestCalendarStoreDirectoryRecord(
+        "room2", ("room2",), "Conference Room Two",
+        frozenset(("urn:uuid:room2",)),
+        extras={
+            "associatedAddress" : "il2",
+        }
+    ))
+
     return directory
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/util.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/datastore/util.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -32,10 +32,10 @@
 
 from twext.python.log import Logger
 
-from twext.web2 import http_headers
+from txweb2 import http_headers
 
-from twext.python.vcomponent import InvalidICalendarDataError
-from twext.python.vcomponent import VComponent
+from twistedcaldav.ical import InvalidICalendarDataError
+from twistedcaldav.ical import Component as VComponent
 
 from twistedcaldav import ical
 from twistedcaldav.datafilters.hiddeninstance import HiddenInstanceFilter
@@ -283,7 +283,7 @@
 
 
 
-# MIME helpers - mostly copied from twext.web2.static
+# MIME helpers - mostly copied from txweb2.static
 
 def loadMimeTypes(mimetype_locations=['/etc/mime.types']):
     """
@@ -507,7 +507,7 @@
     def __init__(self, attachment, contentType, dispositionName):
         """
         Create a storage transport with a reference to an L{IAttachment} and a
-        L{twext.web2.http_headers.MimeType}.
+        L{txweb2.http_headers.MimeType}.
         """
         from twisted.internet import reactor
         self._clock = reactor

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/icalendarstore.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/icalendarstore.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/icalendarstore.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -658,7 +658,7 @@
 
         @param contentType: The content type of the data which will be stored.
 
-        @type contentType: L{twext.web2.http_headers.MimeType}
+        @type contentType: L{txweb2.http_headers.MimeType}
 
         @return: A transport which stores the contents written to it.
 
@@ -740,6 +740,13 @@
 
 
 
+class DuplicatePrivateCommentsError(CommonStoreError):
+    """
+    Calendar data cannot contain duplicate private comment properties.
+    """
+
+
+
 class InvalidPerUserDataMerge(CommonStoreError):
     """
     Per-user data merge failed.

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/resource.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/caldav/resource.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -32,9 +32,9 @@
 
 from twext.python.log import Logger
 from txdav.xml.base import dav_namespace
-from twext.web2.http_headers import MimeType
-from twext.web2.http import RedirectResponse, Response
-from twext.web2.stream import MemoryStream
+from txweb2.http_headers import MimeType
+from txweb2.http import RedirectResponse, Response
+from txweb2.stream import MemoryStream
 
 from twistedcaldav import caldavxml
 from twistedcaldav.caldavxml import caldav_namespace

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/file.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/file.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -30,8 +30,8 @@
 from errno import ENOENT
 
 from txdav.xml.rfc2518 import GETContentType
-from twext.web2.dav.resource import TwistedGETContentMD5
-from twext.web2.http_headers import MimeType
+from txweb2.dav.resource import TwistedGETContentMD5
+from txweb2.http_headers import MimeType
 
 from twisted.python import hashlib
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/sql.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/sql.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -32,9 +32,9 @@
     Update, Union, Max, Select, utcNowSQL
 from twext.enterprise.locking import NamedLock
 from twext.python.clsprop import classproperty
-from twext.web2.http import HTTPError
-from twext.web2.http_headers import MimeType
-from twext.web2.responsecode import FORBIDDEN
+from txweb2.http import HTTPError
+from txweb2.http_headers import MimeType
+from txweb2.responsecode import FORBIDDEN
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python import hashlib

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/test/common.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/test/common.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/test/common.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -20,8 +20,8 @@
 
 from twext.python.filepath import CachingFilePath as FilePath
 
-from twext.web2.http import HTTPError
-from twext.web2.responsecode import FORBIDDEN
+from txweb2.http import HTTPError
+from txweb2.responsecode import FORBIDDEN
 
 from twisted.internet.defer import inlineCallbacks, returnValue, maybeDeferred
 from twisted.python import hashlib

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/file.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/file.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -24,8 +24,8 @@
 from twext.python.log import Logger
 from txdav.xml.rfc2518 import GETContentType, HRef
 from txdav.xml.rfc5842 import ResourceID
-from twext.web2.http_headers import generateContentType, MimeType
-from twext.web2.dav.resource import TwistedGETContentMD5, \
+from txweb2.http_headers import generateContentType, MimeType
+from txweb2.dav.resource import TwistedGETContentMD5, \
     TwistedQuotaUsedProperty
 
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -42,7 +42,7 @@
 from twext.internet.decorate import memoizedKey, Memoizable
 from twext.python.clsprop import classproperty
 from twext.python.log import Logger
-from twext.web2.http_headers import MimeType
+from txweb2.http_headers import MimeType
 
 from twisted.application.service import Service
 from twisted.internet import reactor
@@ -4288,7 +4288,7 @@
         if self._objectNames and child.name() in self._objectNames:
             self._objectNames.remove(child.name())
         yield self._deleteRevision(child.name())
-        yield self.notifyChanged()
+        yield self.notifyChanged(category=child.removeNotifyCategory())
 
 
     @classproperty
@@ -5095,6 +5095,18 @@
         self._notificationData = None
 
 
+    def removeNotifyCategory(self):
+        """
+        Indicates what category to use when determining the priority of push
+        notifications when this object is removed.
+
+        @returns: The "default" category (but should be overridden to return
+            values such as "inbox")
+        @rtype: L{ChangeCategory}
+        """
+        return ChangeCategory.default
+
+
     def uid(self):
         return self._uid
 
@@ -5616,6 +5628,8 @@
                 child._notificationType = json.loads(child._notificationType)
             except ValueError:
                 pass
+            if isinstance(child._notificationType, unicode):
+                child._notificationType = child._notificationType.encode("utf-8")
             child._loadPropertyStore(
                 props=propertyStores.get(child._resourceID, None)
             )
@@ -5664,6 +5678,8 @@
                 self._notificationType = json.loads(self._notificationType)
             except ValueError:
                 pass
+            if isinstance(self._notificationType, unicode):
+                self._notificationType = self._notificationType.encode("utf-8")
             self._loadPropertyStore()
             returnValue(self)
         else:
@@ -5777,6 +5793,8 @@
                 self._notificationData = json.loads(self._notificationData)
             except ValueError:
                 pass
+            if isinstance(self._notificationData, unicode):
+                self._notificationData = self._notificationData.encode("utf-8")
         returnValue(self._notificationData)
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/test/util.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/test/util.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -38,10 +38,10 @@
 
 from twext.python.log import Logger
 from twext.python.filepath import CachingFilePath
-from twext.python.vcomponent import VComponent
+from twistedcaldav.ical import Component as VComponent
 from twext.enterprise.adbapi2 import ConnectionPool
 from twext.enterprise.ienterprise import AlreadyFinishedError
-from twext.web2.dav.resource import TwistedGETContentMD5
+from txweb2.dav.resource import TwistedGETContentMD5
 
 from twisted.application.service import Service
 from twisted.internet import reactor
@@ -112,6 +112,11 @@
     def recordWithUID(self, uid):
         return self.records.get(uid)
 
+    def recordWithGUID(self, guid):
+        for record in self.records.itervalues():
+            if record.guid == guid:
+                return record
+        return None
 
     def addRecord(self, record):
         self.records[record.uid] = record
@@ -122,11 +127,13 @@
 
     implements(IStoreDirectoryRecord)
 
-    def __init__(self, uid, shortNames, fullName):
+    def __init__(self, uid, shortNames, fullName, extras={}):
         self.uid = uid
+        self.guid = uid
         self.shortNames = shortNames
         self.fullName = fullName
         self.displayName = self.fullName if self.fullName else self.shortNames[0]
+        self.extras = extras
 
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/upgrade/sql/upgrades/calendar_upgrade_from_4_to_5.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -15,7 +15,7 @@
 # limitations under the License.
 ##
 
-from twext.web2.dav.resource import TwistedQuotaUsedProperty, TwistedGETContentMD5
+from txweb2.dav.resource import TwistedQuotaUsedProperty, TwistedGETContentMD5
 
 from twisted.internet.defer import inlineCallbacks
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/upgrade/test/test_migrate.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/upgrade/test/test_migrate.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/upgrade/test/test_migrate.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -21,7 +21,7 @@
 from twext.enterprise.adbapi2 import Pickle
 from twext.enterprise.dal.syntax import Delete
 from twext.python.filepath import CachingFilePath
-from twext.web2.http_headers import MimeType
+from txweb2.http_headers import MimeType
 
 from twisted.internet.defer import inlineCallbacks, Deferred, returnValue
 from twisted.internet.protocol import Protocol

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/idirectoryservice.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/idirectoryservice.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/idirectoryservice.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -39,8 +39,15 @@
         @rtype: L{IStoreDirectoryRecord}
         """
 
+    def recordWithGUID(guid): #@NoSelf
+        """
+        Return the record for the specified store guid.
 
+        @return: the record.
+        @rtype: L{IStoreDirectoryRecord}
+        """
 
+
 class IStoreDirectoryRecord(Interface):
     """
     Directory record object

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/idav.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/idav.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/idav.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -87,7 +87,7 @@
     using C{abort()}.
 
     Also, keys must be L{IPropertyName} providers and values must be
-    L{twext.web2.element.dav.base.WeDAVElement}s.
+    L{txweb2.element.dav.base.WeDAVElement}s.
     """
     # FIXME: the type for values isn't quite right, there should be some more
     # specific interface for that.

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/base.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/base.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/base.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -51,7 +51,7 @@
 import re
 
 from twext.python.log import Logger
-from twext.web2.http_headers import parseDateTime
+from txweb2.http_headers import parseDateTime
 
 log = Logger()
 

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/rfc2518.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/rfc2518.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/rfc2518.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -33,8 +33,8 @@
 __all__ = []
 
 
-from twext.web2 import responsecode
-from twext.web2.http_headers import MimeType
+from txweb2 import responsecode
+from txweb2.http_headers import MimeType
 
 from txdav.xml.base import WebDAVElement, WebDAVTextElement, PCDATAElement
 from txdav.xml.base import WebDAVEmptyElement, WebDAVOneShotElement
@@ -366,7 +366,7 @@
     def fromResponseCode(clazz, code):
         """
         code must be an integer response code in
-        twext.web2.responsecode.RESPONSES.keys()
+        txweb2.responsecode.RESPONSES.keys()
         """
         if code not in responsecode.RESPONSES:
             raise ValueError("Invalid response code: %r" % (code,))

Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/test/test_xml_rfc3744.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/test/test_xml_rfc3744.py	2013-12-19 03:09:42 UTC (rev 12141)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/xml/test/test_xml_rfc3744.py	2013-12-19 04:51:29 UTC (rev 12142)
@@ -23,7 +23,7 @@
 from twisted.trial import unittest
 
 from txdav.xml import element as davxml
-from twext.web2.dav.resource import davPrivilegeSet
+from txweb2.dav.resource import davPrivilegeSet
 
 
 class XML_3744(unittest.TestCase):


Property changes on: CalendarServer/branches/users/gaya/sharedgroupfixes/txweb2
___________________________________________________________________
Added: svn:ignore
   + *.pyc

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/927d53d3/attachment.html>


More information about the calendarserver-changes mailing list