[CalendarServer-changes] [10867] CalendarServer/branches/users/gaya/sharedgroups

source_changes at macosforge.org source_changes at macosforge.org
Thu Mar 7 14:42:21 PST 2013


Revision: 10867
          http://trac.calendarserver.org//changeset/10867
Author:   gaya at apple.com
Date:     2013-03-07 14:42:21 -0800 (Thu, 07 Mar 2013)
Log Message:
-----------
merge from trunk

Modified Paths:
--------------
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-no-master/14.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitattendeedelete.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitrecur2.xml
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/dsquery.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/setup_directory.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/setup_testusers.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/test/test_opendirectory.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/amppush.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/applepush.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_amppush.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_applepush.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_notifier.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/caldav.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/util.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/ampnotifications.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/anonymize.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/backup_pg.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/bootstrapdatabase.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/calverify.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/calverify_diff.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/changeip_calendar.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/cmdline.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/config.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dbinspect.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dkimtool.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/doublequotefix.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/export.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/fixcalendardata.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/gateway.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/icalsplit.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/loadaugmentdb.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/managepostgres.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/managetimezones.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/migrate.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/migrate_verify.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/notifications.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/obliterate.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/principals.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/purge.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/push.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/resources.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/shell/terminal.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_calverify.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_gateway.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/upgrade.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/util.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/validcalendardata.py
    CalendarServer/branches/users/gaya/sharedgroups/conf/caldavd-apple.plist
    CalendarServer/branches/users/gaya/sharedgroups/conf/caldavd-test.plist
    CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarcommonextra.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendardemotion.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarmigrator.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarpromotion.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/test/test_migrator.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/benchlib.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/benchmark.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/compare.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/display-calendar-events.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/httpauth.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/ampsim.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/ical.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/population.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/sim.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/massupload.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/report.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/sqlusage/sqlusage.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/sqlwatch.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/stats.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/upload.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/anonymous_log.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/dtraceanalyze.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/fakecalendardata.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/harpoon.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/monitoranalysis.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/monitorsplit.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/netstatus.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/pg_stats_analysis.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/protocolanalysis.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/readStats.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/request_monitor.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/sortrecurrences.py
    CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/sqldata_from_path.py
    CalendarServer/branches/users/gaya/sharedgroups/setup.py
    CalendarServer/branches/users/gaya/sharedgroups/support/version.py
    CalendarServer/branches/users/gaya/sharedgroups/test
    CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/parseschema.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/record.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/test/test_record.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/queue.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/internet/gaiendpoint.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/python/_plistlib.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/python/log.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/python/memcacheclient.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/web2/dav/resource.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/web2/fileupload.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/web2/http_headers.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/web2/server.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/web2/test/test_client.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/__init__.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/directory.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/idirectory.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/index.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_directory.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_xml.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/util.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/xml.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/backup.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/datafilters/hiddeninstance.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/datafilters/test/test_hiddeninstances.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_guidchange.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_ldapdirectory.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_livedirectory.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_principal.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/extensions.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/ical.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/localization.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/method/put.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/query/expression.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/query/sqlgenerator.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/resource.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/icaldiff.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/outbound.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/implicit.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/itip.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/processing.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_icaldiff.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_itip.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_utils.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/stdconfig.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/test/util.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/base/datastore/file.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/test/util.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/test/test_upgrade.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/upgrade.py

Added Paths:
-----------
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/10.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/11.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/12.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/13.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/14.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/15.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/16.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/17.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/5.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/6.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/7.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/8.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/9.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/10.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/11.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/12.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/5.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/6.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/7.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/8.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/9.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/5.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/6.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/7.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/8.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitauto10.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitautopast.xml
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/aggregate.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/expression.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_aggregate.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_expression.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_util.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/test/test_inbound.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/test/test_outbound.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/old/oracle-dialect/v16.sql
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/old/postgres-dialect/v16.sql
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_16_to_17.sql
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_16_to_17.sql
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/others/test/
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/others/test/__init__.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/others/test/test_attachment_migration.py

Removed Paths:
-------------
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/10.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/11.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/12.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/13.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/14.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/15.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/16.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/17.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/5.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/6.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/7.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/8.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/9.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/10.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/11.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/12.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/5.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/6.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/7.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/8.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/9.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/5.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/6.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/7.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/8.ics
    CalendarServer/branches/users/gaya/sharedgroups/bin/calendarserver_warmup
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/_sacl.so
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/warmup.py
    CalendarServer/branches/users/gaya/sharedgroups/doc/datafilters/
    CalendarServer/branches/users/gaya/sharedgroups/support/directorysetup.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/resource.py

Property Changed:
----------------
    CalDAVTester/branches/users/gaya/sharedgroupstester/
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/1.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/10.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/11.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/12.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/13.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/14.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/15.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/16.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/17.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/18.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/19.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/2.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/20.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/21.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/22.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/23.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/24.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/25.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/26.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/27.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/28.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/29.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/3.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/30.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/31.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/32.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/5.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/6.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/7.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/8.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/9.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics
    CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitoptions.xml
    CalendarServer/branches/users/gaya/sharedgroups/
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/
    CalendarServer/branches/users/gaya/sharedgroups/conf/


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester
___________________________________________________________________
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/trunk:10010-10782
   + /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/trunk:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/1.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/1.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/1.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/1.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/1.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/1.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/1.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/1.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/1.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/1.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/1.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/1.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/1.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/1.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/1.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/1.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/1.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/1.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/1.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/1.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/1.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/10.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/10.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/10.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/10.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/10.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/10.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/10.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/10.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/10.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/10.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/10.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/10.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/10.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/10.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/10.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/10.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/10.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/10.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/10.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/10.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/10.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/11.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/11.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/11.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/11.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/11.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/11.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/11.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/11.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/11.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/11.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/11.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/11.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/11.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/11.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/11.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/11.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/11.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/11.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/11.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/11.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/11.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/12.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/12.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/12.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/12.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/12.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/12.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/12.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/12.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/12.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/12.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/12.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/12.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/12.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/12.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/12.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/12.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/12.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/12.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/12.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/12.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/12.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/13.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/13.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/13.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/13.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/13.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/13.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/13.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/13.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/13.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/13.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/13.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/13.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/13.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/13.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/13.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/13.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/13.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/13.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/13.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/13.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/13.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/14.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/14.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/14.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/14.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/14.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/14.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/14.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/14.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/14.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/14.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/14.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/14.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/14.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/14.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/14.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/14.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/14.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/14.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/14.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/14.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/14.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/15.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/15.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/15.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/15.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/15.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/15.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/15.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/15.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/15.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/15.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/15.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/15.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/15.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/15.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/15.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/15.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/15.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/15.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/15.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/15.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/15.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/16.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/16.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/16.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/16.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/16.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/16.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/16.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/16.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/16.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/16.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/16.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/16.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/16.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/16.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/16.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/16.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/16.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/16.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/16.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/16.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/16.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/17.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/17.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/17.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/17.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/17.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/17.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/17.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/17.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/17.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/17.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/17.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/17.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/17.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/17.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/17.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/17.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/17.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/17.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/17.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/17.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/17.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/18.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/18.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/18.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/18.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/18.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/18.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/18.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/18.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/18.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/18.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/18.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/18.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/18.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/18.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/18.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/18.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/18.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/18.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/18.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/18.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/18.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/19.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/19.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/19.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/19.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/19.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/19.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/19.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/19.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/19.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/19.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/19.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/19.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/19.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/19.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/19.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/19.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/19.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/19.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/19.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/19.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/19.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/2.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/2.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/2.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/2.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/2.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/2.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/2.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/2.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/2.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/2.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/2.ics:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/2.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/2.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/2.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/2.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/2.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/2.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/2.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/2.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/2.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/2.ics:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/20.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/20.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/20.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/20.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/20.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/20.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/20.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/20.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/20.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/20.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/20.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/20.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/20.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/20.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/20.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/20.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/20.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/20.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/20.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/20.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/20.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/21.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/21.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/21.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/21.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/21.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/21.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/21.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/21.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/21.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/21.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/21.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/21.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/21.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/21.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/21.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/21.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/21.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/21.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/21.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/21.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/21.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/22.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/22.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/22.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/22.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/22.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/22.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/22.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/22.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/22.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/22.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/22.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/22.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/22.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/22.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/22.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/22.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/22.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/22.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/22.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/22.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/22.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/23.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/23.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/23.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/23.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/23.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/23.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/23.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/23.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/23.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/23.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/23.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/23.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/23.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/23.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/23.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/23.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/23.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/23.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/23.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/23.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/23.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/24.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/24.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/24.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/24.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/24.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/24.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/24.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/24.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/24.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/24.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/24.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/24.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/24.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/24.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/24.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/24.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/24.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/24.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/24.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/24.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/24.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/25.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/25.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/25.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/25.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/25.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/25.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/25.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/25.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/25.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/25.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/25.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/25.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/25.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/25.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/25.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/25.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/25.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/25.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/25.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/25.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/25.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/26.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/26.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/26.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/26.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/26.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/26.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/26.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/26.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/26.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/26.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/26.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/26.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/26.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/26.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/26.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/26.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/26.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/26.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/26.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/26.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/26.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/27.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/27.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/27.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/27.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/27.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/27.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/27.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/27.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/27.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/27.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/27.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/27.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/27.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/27.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/27.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/27.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/27.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/27.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/27.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/27.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/27.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/28.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/28.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/28.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/28.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/28.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/28.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/28.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/28.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/28.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/28.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/28.ics:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/28.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/28.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/28.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/28.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/28.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/28.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/28.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/28.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/28.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/28.ics:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/29.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/29.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/29.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/29.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/29.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/29.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/29.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/29.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/29.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/29.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/29.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/29.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/29.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/29.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/29.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/29.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/29.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/29.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/29.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/29.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/29.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/3.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/3.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/3.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/3.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/3.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/3.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/3.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/3.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/3.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/3.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/3.ics:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/3.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/3.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/3.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/3.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/3.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/3.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/3.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/3.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/3.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/3.ics:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/30.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/30.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/30.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/30.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/30.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/30.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/30.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/30.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/30.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/30.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/30.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/30.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/30.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/30.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/30.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/30.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/30.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/30.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/30.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/30.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/30.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/31.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/31.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/31.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/31.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/31.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/31.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/31.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/31.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/31.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/31.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/31.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/31.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/31.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/31.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/31.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/31.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/31.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/31.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/31.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/31.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/31.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/32.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/32.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/32.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/32.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/32.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/32.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/32.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/32.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/32.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/32.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/32.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/32.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/32.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/32.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/32.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/32.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/32.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/32.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/32.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/32.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/32.xml:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/4.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/4.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/4.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/4.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/4.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/4.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/4.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/4.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/4.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/4.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/4.ics:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/4.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/4.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/4.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/4.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/4.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/4.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/4.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/4.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/4.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/4.ics:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/5.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/5.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/5.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/5.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/5.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/5.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/5.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/5.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/5.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/5.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/5.ics:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/5.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/5.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/5.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/5.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/5.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/5.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/5.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/5.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/5.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/5.ics:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/6.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/6.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/6.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/6.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/6.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/6.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/6.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/6.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/6.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/6.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/6.ics:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/6.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/6.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/6.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/6.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/6.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/6.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/6.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/6.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/6.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/6.ics:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/7.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/7.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/7.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/7.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/7.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/7.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/7.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/7.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/7.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/7.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/7.ics:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/7.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/7.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/7.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/7.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/7.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/7.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/7.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/7.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/7.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/7.ics:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/8.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/8.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/8.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/8.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/8.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/8.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/8.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/8.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/8.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/8.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/8.ics:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/8.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/8.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/8.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/8.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/8.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/8.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/8.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/8.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/8.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/8.ics:10010-10865


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/errors/9.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/9.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/9.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/9.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/9.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/9.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/9.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/9.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/9.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/9.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/9.ics:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/errors/9.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/errors/9.txt:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/errors/9.txt:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/errors/9.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/errors/9.txt:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/errors/9.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/errors/9.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/errors/9.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/errors/9.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/errors/9.ics:10010-10865

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/1.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/1.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,61 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ORGANIZER;CN=$username1::$cuaddr1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr3:
-RRULE:FREQ=DAILY
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ORGANIZER;CN=$username1::$cuaddr1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr3:
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ORGANIZER;CN=$username1::$cuaddr1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr3:
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/1.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/1.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/1.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,61 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ORGANIZER;CN=$username1::$cuaddr1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr3:
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ORGANIZER;CN=$username1::$cuaddr1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr3:
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ORGANIZER;CN=$username1::$cuaddr1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr3:
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/10.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/10.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/10.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,64 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY
-SEQUENCE:1
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:1
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:1
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/10.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/10.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/10.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/10.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,64 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY
+SEQUENCE:1
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:1
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/11.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/11.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/11.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,37 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:1
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/11.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/11.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/11.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/11.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,37 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/12.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/12.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/12.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,64 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY
-SEQUENCE:2
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T120000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:2
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:2
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/12.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/12.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/12.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/12.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,64 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY
+SEQUENCE:2
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T120000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:2
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/13.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/13.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/13.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,65 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY
-SEQUENCE:2
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T120000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:2
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:2
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/13.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/13.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/13.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/13.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,65 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY
+SEQUENCE:2
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T120000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:2
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/14.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/14.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/14.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,52 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T120000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:2
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:2
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/14.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/14.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/14.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/14.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,52 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T120000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:2
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/15.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/15.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/15.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,64 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY
-SEQUENCE:2
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T120000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:2
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:2
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/15.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/15.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/15.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/15.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,64 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY
+SEQUENCE:2
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T120000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:2
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/16.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/16.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/16.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,64 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY
-SEQUENCE:2
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T140000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:3
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-2
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:2
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/16.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/16.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/16.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/16.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,64 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY
+SEQUENCE:2
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T140000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:3
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-2
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/17.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/17.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/17.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,38 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T140000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:3
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/17.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/17.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/17.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/17.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,38 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T140000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:3
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/2.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/2.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,61 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/2.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/2.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/2.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,61 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/3.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/3.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,37 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/3.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/3.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/3.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,37 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/4.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/4.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,61 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/4.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/4.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/4.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,61 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/5.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/5.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/5.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,36 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/5.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/5.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/5.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/5.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,36 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/6.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/6.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/6.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,61 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/6.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/6.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/6.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/6.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,61 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/7.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/7.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/7.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,67 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY
-SEQUENCE:1
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:1
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:1
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/7.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/7.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/7.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/7.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,67 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY
+SEQUENCE:1
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:1
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:1
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/8.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/8.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/8.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,37 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:1
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/8.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/8.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/8.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/8.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,37 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/9.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/9.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/9.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,64 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY
-SEQUENCE:1
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:1
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
-DURATION:PT1H
-SUMMARY:event 1-1
-UID:event1 at ninevah.local
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-SEQUENCE:1
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/9.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/9.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/9.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/9.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,64 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY
+SEQUENCE:1
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=DECLINED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:1
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0103T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0103T100000
+DURATION:PT1H
+SUMMARY:event 1-1
+UID:event1 at ninevah.local
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$username3:;PARTSTAT=ACCEPTED;EMAIL=$email3::$cuaddrurn3:
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR

Modified: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-no-master/14.ics
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-no-master/14.ics	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/attendeedelete/recurring-no-master/14.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -31,7 +31,7 @@
 ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
 ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
 ATTENDEE;CN=$username3:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email3::$cuaddrurn3:
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
 SEQUENCE:2
 TRANSP:TRANSPARENT
 END:VEVENT

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/1.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/1.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,18 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-1
-DTSTART:$now.8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
-ATTENDEE;CN=$resourcename8::$rcuaddralt8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1::$cuaddralt1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/1.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/1.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/1.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,18 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-1
+DTSTART:$now.8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
+ATTENDEE;CN=$resourcename8::$rcuaddralt8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1::$cuaddralt1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/10.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/10.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/10.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.8:T203000Z
-DURATION:PT30M
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename8:;PARTSTAT=ACCEPTED:$rcuaddrurn8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/10.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/10.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/10.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/10.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.8:T203000Z
+DURATION:PT30M
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename8:;PARTSTAT=ACCEPTED:$rcuaddrurn8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/11.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/11.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/11.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,18 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-1
-DTSTART:$now.8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$resourcename8:;RSVP=TRUE;SCHEDULE-STATUS=1.2:$rcuaddrurn8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/11.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/11.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/11.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/11.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,18 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-1
+DTSTART:$now.8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$resourcename8:;RSVP=TRUE;SCHEDULE-STATUS=1.2:$rcuaddrurn8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/12.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/12.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/12.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,18 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-1
-DTSTART:$now.8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$resourcename8:;RSVP=TRUE:$rcuaddrurn8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/12.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/12.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/12.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/12.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,18 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-1
+DTSTART:$now.8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$resourcename8:;RSVP=TRUE:$rcuaddrurn8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/2.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/2.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,18 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-1
-DTSTART:$now.8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$resourcename8:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0:$rcuaddrurn8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/2.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/2.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/2.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,18 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-1
+DTSTART:$now.8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$resourcename8:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0:$rcuaddrurn8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/3.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/3.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,18 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-1
-DTSTART:$now.8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$resourcename8:;PARTSTAT=ACCEPTED:$rcuaddrurn8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/3.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/3.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/3.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,18 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-1
+DTSTART:$now.8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$resourcename8:;PARTSTAT=ACCEPTED:$rcuaddrurn8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/4.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/4.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.8:T203000Z
-DURATION:PT30M
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
-ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
-ATTENDEE;CN=$resourcename8::$rcuaddralt8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1::$cuaddralt1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/4.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/4.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/4.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.8:T203000Z
+DURATION:PT30M
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
+ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
+ATTENDEE;CN=$resourcename8::$rcuaddralt8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1::$cuaddralt1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/5.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/5.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/5.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.8:T203000Z
-DURATION:PT30M
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename8:;RSVP=TRUE;SCHEDULE-STATUS=1.2:$rcuaddrurn8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/5.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/5.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/5.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/5.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.8:T203000Z
+DURATION:PT30M
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename8:;RSVP=TRUE;SCHEDULE-STATUS=1.2:$rcuaddrurn8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/6.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/6.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/6.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.8:T203000Z
-DURATION:PT30M
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename8:;RSVP=TRUE:$rcuaddrurn8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/6.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/6.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/6.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/6.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.8:T203000Z
+DURATION:PT30M
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename8:;RSVP=TRUE:$rcuaddrurn8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/7.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/7.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/7.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.8:T203000Z
-DURATION:PT30M
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename8:;RSVP=TRUE:$rcuaddrurn8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/7.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/7.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/7.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/7.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.8:T203000Z
+DURATION:PT30M
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename8:;RSVP=TRUE:$rcuaddrurn8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/8.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/8.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/8.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.8:T203000Z
-DURATION:PT30M
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename8:;PARTSTAT=DECLINED:$rcuaddrurn8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/8.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/8.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/8.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/8.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.8:T203000Z
+DURATION:PT30M
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename8:;PARTSTAT=DECLINED:$rcuaddrurn8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/9.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/9.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/9.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.8:T203000Z
-DURATION:PT30M
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename8:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0:$rcuaddrurn8:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/9.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/auto10/suite1/9.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/9.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/auto10/suite1/9.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.8:T203000Z
+DURATION:PT30M
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename8:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0:$rcuaddrurn8:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/1.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite1/1.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-1
-DTSTART:$now.-8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
-ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
-ATTENDEE;CN=$resourcename1::$rcuaddralt1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1::$cuaddralt1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/1.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite1/1.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/1.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-1
+DTSTART:$now.-8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
+ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
+ATTENDEE;CN=$resourcename1::$rcuaddralt1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1::$cuaddralt1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/2.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite1/2.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-1
-DTSTART:$now.-8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;RSVP=TRUE;SCHEDULE-STATUS=1.2:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/2.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite1/2.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/2.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-1
+DTSTART:$now.-8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;RSVP=TRUE;SCHEDULE-STATUS=1.2:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/3.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite1/3.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-1
-DTSTART:$now.-8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/3.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite1/3.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/3.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-1
+DTSTART:$now.-8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/4.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite1/4.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,19 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-1
-DTSTART:$now.-8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/4.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite1/4.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/4.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite1/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,19 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-1
+DTSTART:$now.-8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/1.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite2/1.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,36 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.-9:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
-ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
-ATTENDEE;CN=$resourcename1::$rcuaddralt1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1::$cuaddralt1:
-RRULE:FREQ=DAILY;COUNT=5
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-BEGIN:VEVENT
-UID:event-2
-RECURRENCE-ID:$now.-8:T210000Z
-DTSTART:$now.-8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
-ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
-ATTENDEE;CN=$resourcename1::$rcuaddralt1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1::$cuaddralt1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/1.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite2/1.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/1.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,36 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.-9:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
+ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
+ATTENDEE;CN=$resourcename1::$rcuaddralt1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1::$cuaddralt1:
+RRULE:FREQ=DAILY;COUNT=5
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+BEGIN:VEVENT
+UID:event-2
+RECURRENCE-ID:$now.-8:T210000Z
+DTSTART:$now.-8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
+ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
+ATTENDEE;CN=$resourcename1::$rcuaddralt1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1::$cuaddralt1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/2.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite2/2.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,36 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.-9:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;RSVP=TRUE;SCHEDULE-STATUS=1.2:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY;COUNT=5
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-BEGIN:VEVENT
-UID:event-2
-RECURRENCE-ID:$now.-8:T210000Z
-DTSTART:$now.-8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;RSVP=TRUE;SCHEDULE-STATUS=1.2:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/2.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite2/2.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/2.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,36 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.-9:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;RSVP=TRUE;SCHEDULE-STATUS=1.2:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY;COUNT=5
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+BEGIN:VEVENT
+UID:event-2
+RECURRENCE-ID:$now.-8:T210000Z
+DTSTART:$now.-8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;RSVP=TRUE;SCHEDULE-STATUS=1.2:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/3.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite2/3.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,36 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.-9:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY;COUNT=5
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-UID:event-2
-RECURRENCE-ID:$now.-8:T210000Z
-DTSTART:$now.-8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/3.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite2/3.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/3.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,36 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.-9:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY;COUNT=5
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+UID:event-2
+RECURRENCE-ID:$now.-8:T210000Z
+DTSTART:$now.-8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/4.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite2/4.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,36 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-2
-DTSTART:$now.-9:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=DAILY;COUNT=5
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-UID:event-2
-RECURRENCE-ID:$now.-8:T210000Z
-DTSTART:$now.-8:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/4.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite2/4.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/4.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite2/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,36 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-2
+DTSTART:$now.-9:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=DAILY;COUNT=5
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+UID:event-2
+RECURRENCE-ID:$now.-8:T210000Z
+DTSTART:$now.-8:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/1.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite3/1.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,36 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-3
-DTSTART:$now.-12:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
-ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
-ATTENDEE;CN=$resourcename1::$rcuaddralt1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1::$cuaddralt1:
-RRULE:FREQ=WEEKLY;COUNT=5
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-BEGIN:VEVENT
-UID:event-3
-RECURRENCE-ID:$now.-5:T210000Z
-DTSTART:$now.-5:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
-ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
-ATTENDEE;CN=$resourcename1::$rcuaddralt1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1::$cuaddralt1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/1.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite3/1.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/1.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,36 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-3
+DTSTART:$now.-12:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
+ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
+ATTENDEE;CN=$resourcename1::$rcuaddralt1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1::$cuaddralt1:
+RRULE:FREQ=WEEKLY;COUNT=5
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+BEGIN:VEVENT
+UID:event-3
+RECURRENCE-ID:$now.-5:T210000Z
+DTSTART:$now.-5:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddralt1:
+ATTENDEE;CN=$username2:;RSVP=TRUE:$cuaddralt2:
+ATTENDEE;CN=$resourcename1::$rcuaddralt1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1::$cuaddralt1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/2.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite3/2.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,52 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Example Inc.//Example Calendar//EN
-BEGIN:VEVENT
-UID:event-3
-DTSTART:$now.-12:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=WEEKLY;COUNT=5
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-BEGIN:VEVENT
-UID:event-3
-RECURRENCE-ID:$now.-12:T210000Z
-DTSTART:$now.-12:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=2.0:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-BEGIN:VEVENT
-UID:event-3
-RECURRENCE-ID:$now.-5:T210000Z
-DTSTART:$now.-5:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;SCHEDULE-STATUS=2.0:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/2.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite3/2.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/2.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,52 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Example Inc.//Example Calendar//EN
+BEGIN:VEVENT
+UID:event-3
+DTSTART:$now.-12:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=WEEKLY;COUNT=5
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+BEGIN:VEVENT
+UID:event-3
+RECURRENCE-ID:$now.-12:T210000Z
+DTSTART:$now.-12:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=2.0:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+BEGIN:VEVENT
+UID:event-3
+RECURRENCE-ID:$now.-5:T210000Z
+DTSTART:$now.-5:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;SCHEDULE-STATUS=2.0:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/3.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite3/3.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,52 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-3
-DTSTART:$now.-12:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;PARTSTAT=ACCEPTED:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=WEEKLY;COUNT=5
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-UID:event-3
-RECURRENCE-ID:$now.-12:T210000Z
-DTSTART:$now.-12:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;PARTSTAT=NEEDS-ACTION:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-UID:event-3
-RECURRENCE-ID:$now.-5:T210000Z
-DTSTART:$now.-5:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/3.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite3/3.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/3.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,52 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-3
+DTSTART:$now.-12:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;PARTSTAT=ACCEPTED:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=WEEKLY;COUNT=5
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+UID:event-3
+RECURRENCE-ID:$now.-12:T210000Z
+DTSTART:$now.-12:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;PARTSTAT=NEEDS-ACTION:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+UID:event-3
+RECURRENCE-ID:$now.-5:T210000Z
+DTSTART:$now.-5:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/4.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite3/4.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,52 +0,0 @@
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
-BEGIN:VEVENT
-UID:event-3
-DTSTART:$now.-12:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;PARTSTAT=ACCEPTED:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-RRULE:FREQ=WEEKLY;COUNT=5
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:OPAQUE
-END:VEVENT
-BEGIN:VEVENT
-UID:event-3
-RECURRENCE-ID:$now.-12:T210000Z
-DTSTART:$now.-12:T210000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-UID:event-3
-RECURRENCE-ID:$now.-5:T210000Z
-DTSTART:$now.-5:T200000Z
-DURATION:PT1H
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
-ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
-CREATED:20060110T231240Z
-DESCRIPTION:Call-in
-DTSTAMP:20060309T185105Z
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-STATUS:CONFIRMED
-SUMMARY:Example
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/4.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/autopast/suite3/4.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/4.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/autopast/suite3/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,52 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:event-3
+DTSTART:$now.-12:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;PARTSTAT=ACCEPTED:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+RRULE:FREQ=WEEKLY;COUNT=5
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:OPAQUE
+END:VEVENT
+BEGIN:VEVENT
+UID:event-3
+RECURRENCE-ID:$now.-12:T210000Z
+DTSTART:$now.-12:T210000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+UID:event-3
+RECURRENCE-ID:$now.-5:T210000Z
+DTSTART:$now.-5:T200000Z
+DURATION:PT1H
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;EMAIL=$email2::$cuaddrurn2:
+ATTENDEE;CN=$resourcename1:;RSVP=TRUE:$rcuaddrurn1:
+CREATED:20060110T231240Z
+DESCRIPTION:Call-in
+DTSTAMP:20060309T185105Z
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+STATUS:CONFIRMED
+SUMMARY:Example
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/1.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/1.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,47 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1::$cuaddr1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr2:
-RRULE:FREQ=DAILY;COUNT=5
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T110000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1::$cuaddr1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr2:
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/1.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/1.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/1.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/1.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,47 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1::$cuaddr1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr2:
+RRULE:FREQ=DAILY;COUNT=5
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T110000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1::$cuaddr1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:$cuaddr2:
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/2.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/2.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,47 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-RRULE:FREQ=DAILY;COUNT=5
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T110000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/2.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/2.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/2.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/2.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,47 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+RRULE:FREQ=DAILY;COUNT=5
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T110000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/3.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/3.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,49 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
-RRULE:FREQ=DAILY;COUNT=5
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T110000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/3.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/3.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/3.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/3.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,49 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
+RRULE:FREQ=DAILY;COUNT=5
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T110000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/4.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/4.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,49 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-RRULE:FREQ=DAILY;COUNT=5
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T110000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/4.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/4.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/4.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/4.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,49 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+RRULE:FREQ=DAILY;COUNT=5
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T110000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/5.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/5.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/5.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,47 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
-RRULE:FREQ=DAILY;COUNT=5
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T110000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/5.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/5.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/5.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/5.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,47 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
+RRULE:FREQ=DAILY;COUNT=5
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T110000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0;EMAIL=$email2::$cuaddrurn2:
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/6.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/6.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/6.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,35 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1::$cuaddr1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED:$cuaddr2:
-RRULE:FREQ=DAILY;COUNT=5
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/6.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/6.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/6.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/6.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,35 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1::$cuaddr1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED:$cuaddr1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED:$cuaddr2:
+RRULE:FREQ=DAILY;COUNT=5
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/7.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/7.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/7.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,49 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-RRULE:FREQ=DAILY;COUNT=5
-SEQUENCE:1
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
-SEQUENCE:1
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/7.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/7.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/7.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/7.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,49 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+RRULE:FREQ=DAILY;COUNT=5
+SEQUENCE:1
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;SCHEDULE-STATUS=1.2;EMAIL=$email2::$cuaddrurn2:
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR

Deleted: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/8.ics
===================================================================
--- CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/8.ics	2013-03-07 18:25:19 UTC (rev 10865)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/8.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,50 +0,0 @@
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-PRODID:-//Example Inc.//Example Calendar//EN
-VERSION:2.0
-BEGIN:VTIMEZONE
-LAST-MODIFIED:20040110T032845Z
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-DTSTART:20000404T020000
-RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-DTSTART:20001026T020000
-RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
-RRULE:FREQ=DAILY;COUNT=5
-TRANSP:TRANSPARENT
-END:VEVENT
-BEGIN:VEVENT
-DTSTAMP:20051222T205953Z
-CREATED:20060101T150000Z
-RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
-DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
-DURATION:PT1H
-SUMMARY:event 2
-UID:event2 at ninevah.local
-ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
-ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
-SEQUENCE:1
-TRANSP:TRANSPARENT
-END:VEVENT
-END:VCALENDAR

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/8.ics (from rev 10865, CalDAVTester/trunk/Resource/CalDAV/implicit/recur2/override_remove/8.ics)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/8.ics	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/recur2/override_remove/8.ics	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,50 @@
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:$now.year.1:0101T100000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;PARTSTAT=ACCEPTED;EMAIL=$email2::$cuaddrurn2:
+RRULE:FREQ=DAILY;COUNT=5
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+RECURRENCE-ID;TZID=US/Eastern:$now.year.1:0102T100000
+DTSTART;TZID=US/Eastern:$now.year.1:0102T100000
+DURATION:PT1H
+SUMMARY:event 2
+UID:event2 at ninevah.local
+ORGANIZER;CN=$username1:;SCHEDULE-STATUS=1.2;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username1:;PARTSTAT=ACCEPTED;EMAIL=$email1::$cuaddrurn1:
+ATTENDEE;CN=$username2:;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;EMAIL=$email2::$cuaddrurn2:
+SEQUENCE:1
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/1.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/1.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/1.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/1.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/1.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:10010-10782
/CalDAVTester/trunk/Resource/implicit/schedulechanges/1.ics:2451,3035,3142,3165,3190,3405,3432
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/1.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/1.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/1.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/1.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/1.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/1.ics:10010-10865
/CalDAVTester/trunk/Resource/implicit/schedulechanges/1.ics:2451,3035,3142,3165,3190,3405,3432


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/2.xml:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/2.xml:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/2.xml:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/2.xml:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/2.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:10010-10782
/CalDAVTester/trunk/Resource/implicit/schedulechanges/2.xml:2451,3035,3142,3165,3190,3405,3432
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/2.xml:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/2.xml:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/2.xml:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/2.xml:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/2.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/2.xml:10010-10865
/CalDAVTester/trunk/Resource/implicit/schedulechanges/2.xml:2451,3035,3142,3165,3190,3405,3432


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/3.xml:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/3.xml:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/3.xml:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/3.xml:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/3.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:10010-10782
/CalDAVTester/trunk/Resource/implicit/schedulechanges/3.xml:2451,3035,3142,3165,3190,3405,3432
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/3.xml:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/3.xml:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/3.xml:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/3.xml:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/3.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/3.xml:10010-10865
/CalDAVTester/trunk/Resource/implicit/schedulechanges/3.xml:2451,3035,3142,3165,3190,3405,3432


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/4.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/4.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/4.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/4.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/4.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:10010-10782
/CalDAVTester/trunk/Resource/implicit/schedulechanges/4.ics:2451,3035,3142,3165,3190,3405,3432
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/4.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/4.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/4.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/4.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/4.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/4.ics:10010-10865
/CalDAVTester/trunk/Resource/implicit/schedulechanges/4.ics:2451,3035,3142,3165,3190,3405,3432


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/5.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/5.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/5.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/5.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/5.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:10010-10782
/CalDAVTester/trunk/Resource/implicit/schedulechanges/5.ics:2451,3035,3142,3165,3190,3405,3432
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/5.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/5.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/5.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/5.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/5.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/5.ics:10010-10865
/CalDAVTester/trunk/Resource/implicit/schedulechanges/5.ics:2451,3035,3142,3165,3190,3405,3432


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/6.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/6.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/6.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/6.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/6.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:10010-10782
/CalDAVTester/trunk/Resource/implicit/schedulechanges/6.ics:2451,3035,3142,3165,3190,3405,3432
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/6.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/6.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/6.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/6.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/6.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/6.ics:10010-10865
/CalDAVTester/trunk/Resource/implicit/schedulechanges/6.ics:2451,3035,3142,3165,3190,3405,3432


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/7.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/7.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/7.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/7.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/7.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:10010-10782
/CalDAVTester/trunk/Resource/implicit/schedulechanges/7.ics:2451,3035,3142,3165,3190,3405,3432
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/7.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/7.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/7.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/7.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/7.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/7.ics:10010-10865
/CalDAVTester/trunk/Resource/implicit/schedulechanges/7.ics:2451,3035,3142,3165,3190,3405,3432


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/8.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/8.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/8.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/8.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/8.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:10010-10782
/CalDAVTester/trunk/Resource/implicit/schedulechanges/8.ics:2451,3035,3142,3165,3190,3405,3432
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:7584
/CalDAVTester/branches/users/cdaboo/attendee-comments-2887/Resource/implicit/schedulechanges/8.ics:2888-2910
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/Resource/implicit/schedulechanges/8.ics:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:8221-8346
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/Resource/implicit/schedulechanges/8.ics:2949-2989
/CalDAVTester/branches/users/cdaboo/location-partial-accept-3574/Resource/implicit/schedulechanges/8.ics:3575-3581
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/Resource/implicit/schedulechanges/8.ics:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:5229-5440
/CalDAVTester/trunk/Resource/CalDAV/implicit/schedulechanges/organizerchange/8.ics:10010-10865
/CalDAVTester/trunk/Resource/implicit/schedulechanges/8.ics:2451,3035,3142,3165,3190,3405,3432

Modified: CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitattendeedelete.xml
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitattendeedelete.xml	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitattendeedelete.xml	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1649,6 +1649,572 @@
 		</test>
 	</test-suite>
 	
+	<test-suite name='Recurring without master - delete of undeclined instance' ignore='no'>
+		<test name='1'>
+			<description>Organizer stores event</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/1.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:/1.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Attendee 2 Inbox Item</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath2:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$inboxpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>204</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4'>
+			<description>Attendee 2 -> Remove one</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/implicit/attendeedelete/recurring-delete-instance/3.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+				<graburi>$attendee2_event:</graburi>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Organizer Inbox Item</description>
+			<request print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$inboxpath1:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request print-response='no'>
+				<method>DELETE</method>
+				<ruri>$</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>204</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Organizer data changed</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/attendeedelete/recurring-delete-instance/4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='7'>
+			<description>Attendee 2 -> accept remaining instance</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$attendee2_event:</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/attendeedelete/recurring-no-master/5.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='8'>
+			<description>Organizer Inbox Item</description>
+			<request print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$inboxpath1:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request print-response='no'>
+				<method>DELETE</method>
+				<ruri>$</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>204</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='9'>
+			<description>Organizer changes subject</description>
+			<request user="$userid3:" pswd="$pswd3:">
+				<method>DELETEALL</method>
+				<ruri>$inboxpath3:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/6.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='10'>
+			<description>Attendee 3 Inbox Item</description>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath3:/</ruri>
+			</request>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$inboxpath3:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>204</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='11'>
+			<description>Attendee 3 has data</description>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$calendarpath3:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/7.ics</value>
+					</arg>
+				</verify>
+				<graburi>$attendee3_event:</graburi>
+			</request>
+		</test>
+		<test name='12'>
+			<description>Attendee 2 Inbox Item</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath2:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$inboxpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>204</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='13'>
+			<description>Attendee 2 has data</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$attendee2_event:</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/8.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='14'>
+			<description>Attendee 3 -> Accepted</description>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>PUT</method>
+				<ruri>$attendee3_event:</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/9.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='15'>
+			<description>Organizer Inbox Item</description>
+			<request print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$inboxpath1:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request print-response='no'>
+				<method>DELETE</method>
+				<ruri>$</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>204</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='16'>
+			<description>Organizer data changed</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/attendeedelete/recurring-delete-instance/10.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='17'>
+			<description>Attendee 2 No Inbox Item</description>
+			<request print-response='no'>
+				<method>DELAY</method>
+				<ruri>1</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath2:/</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='18'>
+			<description>Attendee 2 has data</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$attendee2_event:</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/11.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='19'>
+			<description>Organizer changes time of declined instance</description>
+			<request user="$userid3:" pswd="$pswd3:">
+				<method>DELETEALL</method>
+				<ruri>$inboxpath3:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/12.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='20'>
+			<description>Attendee 3 Inbox Item</description>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath3:/</ruri>
+			</request>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$inboxpath3:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>204</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='21'>
+			<description>Attendee 3 has data</description>
+			<request user="$userid3:" pswd="$pswd3:" print-response='no'>
+				<method>GET</method>
+				<ruri>$attendee3_event:</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/13.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='22'>
+			<description>Attendee 2 Inbox Item</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath2:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$inboxpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>204</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='23'>
+			<description>Attendee 2 has data</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>GET</method>
+				<ruri>$attendee2_event:</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/14.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='24'>
+			<description>Attendee 2 -> DELETE</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$attendee2_event:</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='25'>
+			<description>Organizer Inbox Item</description>
+			<request print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$inboxpath1:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request print-response='no'>
+				<method>DELETE</method>
+				<ruri>$</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>204</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='26'>
+			<description>Organizer data changed</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/attendeedelete/recurring-delete-instance/15.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='27'>
+			<description>Organizer changes time of one declined instance, summary of other</description>
+			<request user="$userid3:" pswd="$pswd3:">
+				<method>DELETEALL</method>
+				<ruri>$inboxpath3:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/attendeedelete/recurring-delete-instance/16.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='28'>
+			<description>Attendee 2 Inbox Item</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath2:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>GETNEW</method>
+				<ruri>$inboxpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>DELETE</method>
+				<ruri>$</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>204</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='29'>
+			<description>Attendee 2 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/implicit/attendeedelete/recurring-delete-instance/17.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='-1'>
+			<description>Clean-up</description>
+			<request user="$userid1:" pswd="$pswd1:">
+				<method>DELETEALL</method>
+				<ruri>$calendarpath1:/</ruri>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>DELETEALL</method>
+				<ruri>$calendarpath2:/</ruri>
+				<ruri>$inboxpath2:/</ruri>
+			</request>
+			<request user="$userid3:" pswd="$pswd3:">
+				<method>DELETEALL</method>
+				<ruri>$calendarpath3:/</ruri>
+				<ruri>$inboxpath3:/</ruri>
+			</request>
+		</test>
+	</test-suite>
+	
 	<end/>
 	
 </caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitauto10.xml (from rev 10865, CalDAVTester/trunk/scripts/tests/CalDAV/implicitauto10.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitauto10.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitauto10.xml	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,539 @@
+<?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 change occurs during attendee refresh</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>$rinboxpath8:/</ruri>
+		</request>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$rcalendarpath8:/</ruri>
+		</request>
+	</start>
+	
+	<test-suite name='#1 Non-recurring' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>Create new blocking event - just resource</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/auto10/suite1/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>One item in user01 Inbox</description>
+			<request print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath1:/</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>
+			<request>
+				<method>DELETEALL</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/auto10/suite1/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>No items in resource08 Inbox</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$rinboxpath8:/</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 resource08 Calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GETNEW</method>
+				<ruri>$rcalendarpath8:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto10/suite1/3.ics</value>
+					</arg>
+				</verify>
+				<graburi>$r1:</graburi>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Create new conflicting event with attendee</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/auto10/suite1/4.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='7' ignore='no'>
+			<description>No item in user01 Inbox</description>
+			<request print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath1:/</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='8' ignore='no'>
+			<description>One item in user01 Calendar</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto10/suite1/5.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='9' ignore='no'>
+			<description>One item in user02 Inbox</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath2:/</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>
+			<request>
+				<method>DELETEALL</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+		</test>
+		<test name='10' ignore='no'>
+			<description>One item in user02 calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GETNEW</method>
+				<ruri>$calendarpath2:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto10/suite1/6.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='11' ignore='no'>
+			<description>One item in resource08 Inbox</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$rinboxpath8:/</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>
+			<request>
+				<method>DELETEALL</method>
+				<ruri>$rinboxpath8:/</ruri>
+			</request>
+		</test>
+		<test name='12' ignore='no'>
+			<description>One item in resource08 Calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GETNEW</method>
+				<ruri>$rcalendarpath8:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto10/suite1/7.ics</value>
+					</arg>
+				</verify>
+				<graburi>$r2:</graburi>
+			</request>
+		</test>
+		<test name='13' ignore='no'>
+			<description>Cancel blocking event</description>
+			<request>
+				<method>DELETE</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='14' ignore='no'>
+			<description>No items in resource08 Inbox</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$rinboxpath8:/</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='15' ignore='no'>
+			<description>No item in resource08 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='16'>
+			<description>Attendee -> Accepted</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/implicit/auto10/suite1/8.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request>
+				<method>DELAY</method>
+				<ruri>10</ruri>
+			</request>
+			<request>
+				<method>WAITCOUNT 2</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+		</test>
+		<test name='17' ignore='no'>
+			<description>Two items in user01 Inbox - one is reply from resource</description>
+			<request print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath1:/</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>
+			<request>
+				<method>DELETEALL</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+		</test>
+		<test name='18' ignore='no'>
+			<description>One item in user01 Calendar</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto10/suite1/9.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='19' ignore='no'>
+			<description>One item in resource08 Calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GET</method>
+				<ruri>$r2:</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto10/suite1/10.ics</value>
+					</arg>
+				</verify>
+				<graburi>$r2:</graburi>
+			</request>
+		</test>
+		<test name='20' ignore='no'>
+			<description>Re-create new blocking event</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/auto10/suite1/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='21' ignore='no'>
+			<description>No item in user01 Inbox</description>
+			<request print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath1:/</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='22' 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/auto10/suite1/11.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='23' ignore='no'>
+			<description>One item in resource08 Inbox</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$rinboxpath8:/</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>
+			<request>
+				<method>DELETEALL</method>
+				<ruri>$rinboxpath8:/</ruri>
+			</request>
+		</test>
+		<test name='24' ignore='no'>
+			<description>One item in resource08 Calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GETNEW</method>
+				<ruri>$rcalendarpath8:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/auto10/suite1/12.ics</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>$rinboxpath8:/</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>$rinboxpath8:/</ruri>
+			<ruri>$rcalendarpath8:/</ruri>
+		</request>
+	</end>
+	
+</caldavtest>

Copied: CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitautopast.xml (from rev 10865, CalDAVTester/trunk/scripts/tests/CalDAV/implicitautopast.xml)
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitautopast.xml	                        (rev 0)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitautopast.xml	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,504 @@
+<?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 implicit scheduling for auto-accept location, with past event</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>
+			<ruri>$rcalendarpath1:/</ruri>
+		</request>
+	</start>
+	
+	<test-suite name='#1 Non-recurring past event' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>Create new event</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/1.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/autopast/suite1/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request>
+				<method>DELAY</method>
+				<ruri>1</ruri>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>No item in user01 Inbox</description>
+			<request print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath1:/</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='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/autopast/suite1/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>One item in user02 Inbox</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath2:/</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='5' ignore='no'>
+			<description>One item in user02 calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GETNEW</method>
+				<ruri>$calendarpath2:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/autopast/suite1/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' 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='7' 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/autopast/suite1/4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8' 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>
+	
+	<test-suite name='#2 Recurring all in the past' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>Create new event</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/autopast/suite2/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request>
+				<method>DELAY</method>
+				<ruri>1</ruri>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>No item in user01 Inbox</description>
+			<request print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath1:/</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='3' ignore='no'>
+			<description>One item in user01 Calendar</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/autopast/suite2/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>One item in user02 Inbox</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath2:/</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='5' ignore='no'>
+			<description>One item in user02 calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GETNEW</method>
+				<ruri>$calendarpath2:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/autopast/suite2/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' 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='7' 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/autopast/suite2/4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8' 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>
+	
+	<test-suite name='#3 Recurring some in the past' ignore='no'>
+		<test name='1' ignore='no'>
+			<description>Create new event</description>
+			<request>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/3.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/autopast/suite3/1.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+			<request>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>One item in user01 Inbox</description>
+			<request print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath1:/</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='3' ignore='no'>
+			<description>One item in user01 Calendar</description>
+			<request print-response="no">
+				<method>GET</method>
+				<ruri>$calendarpath1:/3.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/autopast/suite3/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>One item in user02 Inbox</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>PROPFIND</method>
+				<ruri>$inboxpath2:/</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='5' ignore='no'>
+			<description>One item in user02 calendar</description>
+			<request user="$useradmin:" pswd="$pswdadmin:" print-response="no">
+				<method>GETNEW</method>
+				<ruri>$calendarpath2:/</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/autopast/suite3/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' 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='7' 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/autopast/suite3/4.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8' 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>


Property changes on: CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitoptions.xml
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalDAVTester/branches/release/CalDAVTester-3.0-dev/scripts/tests/CalDAV/implicitoptions.xml:7584
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/scripts/tests/implicitoptions.xml:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/scripts/tests/CalDAV/implicitoptions.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/conditional-4466/scripts/tests/implicitoptions.xml:4467-4469
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/scripts/tests/implicitoptions.xml:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/scripts/tests/implicitoptions.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/scripts/tests/CalDAV/implicitoptions.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/scripts/tests/CalDAV/implicitoptions.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/scripts/tests/CalDAV/implicitoptions.xml:5229-5440
/CalDAVTester/trunk/scripts/tests/CalDAV/implicitoptions.xml:10010-10782
   + /CalDAVTester/branches/release/CalDAVTester-3.0-dev/scripts/tests/CalDAV/implicitoptions.xml:7584
/CalDAVTester/branches/users/cdaboo/better-proxy-3148/scripts/tests/implicitoptions.xml:3149-3163
/CalDAVTester/branches/users/cdaboo/component-set-fixes/scripts/tests/CalDAV/implicitoptions.xml:8221-8346
/CalDAVTester/branches/users/cdaboo/conditional-4466/scripts/tests/implicitoptions.xml:4467-4469
/CalDAVTester/branches/users/cdaboo/implicitauto-2948/scripts/tests/implicitoptions.xml:2949-2989
/CalDAVTester/branches/users/cdaboo/normalize-cuaddr-3533/scripts/tests/implicitoptions.xml:3534-3558
/CalDAVTester/branches/users/cdaboo/pycalendar/scripts/tests/CalDAV/implicitoptions.xml:7160-7206
/CalDAVTester/branches/users/cdaboo/pycard/scripts/tests/CalDAV/implicitoptions.xml:7226-7237
/CalDAVTester/branches/users/cdaboo/sharing-5228/scripts/tests/CalDAV/implicitoptions.xml:5229-5440
/CalDAVTester/trunk/scripts/tests/CalDAV/implicitoptions.xml:10010-10865

Modified: CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitrecur2.xml
===================================================================
--- CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitrecur2.xml	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalDAVTester/branches/users/gaya/sharedgroupstester/scripts/tests/CalDAV/implicitrecur2.xml	2013-03-07 22:42:21 UTC (rev 10867)
@@ -562,6 +562,197 @@
 			</request>
 		</test>
 	</test-suite>
+	
+	<test-suite name='Organizer override remove' only='yes'>
+		<test name='1'>
+			<description>Organizer invites Attendee 2 with override</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/recur2/override_remove/1.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:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/recur2/override_remove/2.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3'>
+			<description>Attendee Inbox Items</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$inboxpath2:/</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>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>DELETEALL</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/implicit/recur2/override_remove/3.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5'>
+			<description>Attendee -> Accepted</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/implicit/recur2/override_remove/4.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='6'>
+			<description>Organizer Inbox Item</description>
+			<request print-response='no'>
+				<method>WAITCOUNT 1</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+			<request print-response='no'>
+				<method>DELETEALL</method>
+				<ruri>$inboxpath1:/</ruri>
+			</request>
+		</test>
+		<test name='7'>
+			<description>Organizer data changed</description>
+			<request print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/recur2/override_remove/5.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='8'>
+			<description>Organizer removes override</description>
+			<request print-response='no'>
+				<method>PUT</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<data>
+					<content-type>text/calendar; charset=utf-8</content-type>
+					<filepath>Resource/CalDAV/implicit/recur2/override_remove/6.ics</filepath>
+				</data>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='9'>
+			<description>Organizer checks data</description>
+			<request print-response='no'>
+				<method>GET</method>
+				<ruri>$calendarpath1:/2.ics</ruri>
+				<verify>
+					<callback>calendarDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CalDAV/implicit/recur2/override_remove/7.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='10'>
+			<description>Attendee Inbox Items</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>PROPFIND</method>
+				<ruri>$inboxpath2:/</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='11'>
+			<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/implicit/recur2/override_remove/8.ics</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='12'>
+			<description>Attendee delete Inbox Items</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>DELETEALL</method>
+				<ruri>$inboxpath2:/</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
 		
 	<end>
 		<request user="$userid1:" pswd="$pswd1:">


Property changes on: CalendarServer/branches/users/gaya/sharedgroups
___________________________________________________________________
Modified: svn:mergeinfo
   - /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/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/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/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/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/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/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/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/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/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/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/wsanchez/transations:5515-5593
/CalendarServer/trunk:9885-10758
   + /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/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/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/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/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/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/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/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/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/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/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:9885-10865

Deleted: CalendarServer/branches/users/gaya/sharedgroups/bin/calendarserver_warmup
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/bin/calendarserver_warmup	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/bin/calendarserver_warmup	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,33 +0,0 @@
-#!/usr/bin/env python
-
-##
-# 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.
-##
-
-import sys
-
-#PYTHONPATH
-
-if __name__ == "__main__":
-    if "PYTHONPATH" in globals():
-        sys.path.insert(0, PYTHONPATH)
-    else:
-        try:
-            import _calendarserver_preamble
-        except ImportError:
-            sys.exc_clear()
-
-    from calendarserver.tools.warmup import main
-    main()

Deleted: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/_sacl.so
===================================================================
(Binary files differ)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/dsquery.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/dsquery.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/dsquery.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # limitations under the License.
 #
 ##
+from __future__ import print_function
 
 """
 Compound query builder. We do this in Python to avoid having to mess
@@ -130,5 +131,5 @@
     for expr, result in exprs:
         gen = expr.generate()
         if gen != result:
-            print "Generate expression %s != %s" % (gen, result,)
-    print "Done."
+            print("Generate expression %s != %s" % (gen, result,))
+    print("Done.")

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/setup_directory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/setup_directory.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/setup_directory.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import os
 import sys
@@ -204,12 +205,12 @@
 
 def usage(e=None):
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] local_user local_password odmaster_user odmaster_password" % (name,)
-    print ""
-    print " Configures local and OD master directories for testing"
-    print ""
-    print "options:"
-    print " -h --help: print this help and exit"
+    print("usage: %s [options] local_user local_password odmaster_user odmaster_password" % (name,))
+    print("")
+    print(" Configures local and OD master directories for testing")
+    print("")
+    print("options:")
+    print(" -h --help: print this help and exit")
     if e:
         sys.exit(1)
     else:
@@ -246,7 +247,7 @@
         attrs,
         None)
     if error:
-        print error
+        print(error)
         raise ODError(error)
     return record
 
@@ -295,7 +296,7 @@
 
         node, error = odframework.ODNode.nodeWithSession_name_error_(session, nodeName, None)
         if error:
-            print error
+            print(error)
             raise ODError(error)
 
         result, error = node.setCredentialsWithRecordType_recordName_password_error_(
@@ -305,45 +306,45 @@
             None
         )
         if error:
-            print "Unable to authenticate with directory %s: %s" % (nodeName, error)
+            print("Unable to authenticate with directory %s: %s" % (nodeName, error))
             raise ODError(error)
 
-        print "Successfully authenticated with directory %s" % (nodeName,)
+        print("Successfully authenticated with directory %s" % (nodeName,))
 
-        print "Creating users within %s:" % (nodeName,)
+        print("Creating users within %s:" % (nodeName,))
         for recordName, attrs in users:
             record = lookupRecordName(node, dsattributes.kDSStdRecordTypeUsers, recordName)
             if record is None:
-                print "Creating user %s" % (recordName,)
+                print("Creating user %s" % (recordName,))
                 try:
                     record = createRecord(node, dsattributes.kDSStdRecordTypeUsers, recordName, attrs)
-                    print "Successfully created user %s" % (recordName,)
+                    print("Successfully created user %s" % (recordName,))
                     result, error = record.changePassword_toPassword_error_(
                         None, "password", None)
                     if error or not result:
-                        print "Failed to set password for %s: %s" % (recordName, error)
+                        print("Failed to set password for %s: %s" % (recordName, error))
                     else:
-                        print "Successfully set password for %s" % (recordName,)
+                        print("Successfully set password for %s" % (recordName,))
                 except ODError, e:
-                    print "Failed to create user %s: %s" % (recordName, e)
+                    print("Failed to create user %s: %s" % (recordName, e))
             else:
-                print "User %s already exists" % (recordName,)
+                print("User %s already exists" % (recordName,))
 
             if record is not None:
                 userRecords.append(record)
 
-        print "Creating groups within %s:" % (nodeName,)
+        print("Creating groups within %s:" % (nodeName,))
         for recordName, attrs in groups:
             record = lookupRecordName(node, dsattributes.kDSStdRecordTypeGroups, recordName)
             if record is None:
-                print "Creating group %s" % (recordName,)
+                print("Creating group %s" % (recordName,))
                 try:
                     record = createRecord(node, dsattributes.kDSStdRecordTypeGroups, recordName, attrs)
-                    print "Successfully created group %s" % (recordName,)
+                    print("Successfully created group %s" % (recordName,))
                 except ODError, e:
-                    print "Failed to create group %s: %s" % (recordName, e)
+                    print("Failed to create group %s: %s" % (recordName, e))
             else:
-                print "Group %s already exists" % (recordName,)
+                print("Group %s already exists" % (recordName,))
 
         print
 
@@ -359,18 +360,18 @@
         for saclGroupName in saclGroupNames:
             saclGroupRecord = lookupRecordName(node, dsattributes.kDSStdRecordTypeGroups, saclGroupName)
             if saclGroupRecord:
-                print "Populating %s SACL group:" % (saclGroupName,)
+                print("Populating %s SACL group:" % (saclGroupName,))
                 for userRecord in userRecords:
                     details, error = userRecord.recordDetailsForAttributes_error_(None, None)
                     recordName = details.get(dsattributes.kDSNAttrRecordName, [None])[0]
                     result, error = saclGroupRecord.isMemberRecord_error_(userRecord, None)
                     if result:
-                        print "%s is already in the %s SACL group" % (recordName, saclGroupName)
+                        print("%s is already in the %s SACL group" % (recordName, saclGroupName))
                     else:
                         result, error = saclGroupRecord.addMemberRecord_error_(userRecord, None)
-                        print "Adding %s to the %s SACL group" % (recordName, saclGroupName)
+                        print("Adding %s to the %s SACL group" % (recordName, saclGroupName))
 
-            print
+            print("")
 
 class ODError(Exception):
     def __init__(self, error):

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/setup_testusers.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/setup_testusers.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/setup_testusers.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import os
 import sys
@@ -23,12 +24,12 @@
 
 def usage(e=None):
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] local_user local_password" % (name,)
-    print ""
-    print " Configures local directory for test users"
-    print ""
-    print "options:"
-    print " -h --help: print this help and exit"
+    print("usage: %s [options] local_user local_password" % (name,))
+    print("")
+    print(" Configures local directory for test users")
+    print("")
+    print("options:")
+    print(" -h --help: print this help and exit")
     if e:
         sys.exit(1)
     else:
@@ -65,7 +66,7 @@
         attrs,
         None)
     if error:
-        print error
+        print(error)
         raise ODError(error)
     return record
 
@@ -90,7 +91,7 @@
     nodeName = "/Local/Default"
     node, error = odframework.ODNode.nodeWithSession_name_error_(session, nodeName, None)
     if error:
-        print error
+        print(error)
         raise ODError(error)
 
     result, error = node.setCredentialsWithRecordType_recordName_password_error_(
@@ -100,12 +101,12 @@
         None
     )
     if error:
-        print "Unable to authenticate with directory %s: %s" % (nodeName, error)
+        print("Unable to authenticate with directory %s: %s" % (nodeName, error))
         raise ODError(error)
 
-    print "Successfully authenticated with directory %s" % (nodeName,)
+    print("Successfully authenticated with directory %s" % (nodeName,))
 
-    print "Creating users within %s:" % (nodeName,)
+    print("Creating users within %s:" % (nodeName,))
     for i in xrange(99):
         j = i+1
         recordName = "user%02d" % (j,)
@@ -120,20 +121,20 @@
 
         record = lookupRecordName(node, dsattributes.kDSStdRecordTypeUsers, recordName)
         if record is None:
-            print "Creating user %s" % (recordName,)
+            print("Creating user %s" % (recordName,))
             try:
                 record = createRecord(node, dsattributes.kDSStdRecordTypeUsers, recordName, attrs)
-                print "Successfully created user %s" % (recordName,)
+                print("Successfully created user %s" % (recordName,))
                 result, error = record.changePassword_toPassword_error_(
                     None, password, None)
                 if error or not result:
-                    print "Failed to set password for %s: %s" % (recordName, error)
+                    print("Failed to set password for %s: %s" % (recordName, error))
                 else:
-                    print "Successfully set password for %s" % (recordName,)
+                    print("Successfully set password for %s" % (recordName,))
             except ODError, e:
-                print "Failed to create user %s: %s" % (recordName, e)
+                print("Failed to create user %s: %s" % (recordName, e))
         else:
-            print "User %s already exists" % (recordName,)
+            print("User %s already exists" % (recordName,))
 
 
 class ODError(Exception):

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/test/test_opendirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/test/test_opendirectory.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/od/test/test_opendirectory.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from twistedcaldav.test.util import TestCase
 import hashlib
@@ -41,10 +42,10 @@
     if "odtestalbert" in recordNames:
         runTests = True
     else:
-        print "Please run setup_directory.py to populate OD"
+        print("Please run setup_directory.py to populate OD")
 
 except ImportError:
-    print "Unable to import OpenDirectory framework"
+    print("Unable to import OpenDirectory framework")
 
 
 def generateNonce():

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/amppush.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/amppush.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/amppush.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -16,9 +16,8 @@
 
 from calendarserver.push.util import PushScheduler
 from twext.python.log import Logger, LoggingMixIn
-from twisted.application.internet import StreamServerEndpointService
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twisted.internet.endpoints import TCP4ClientEndpoint, TCP4ServerEndpoint
+from twisted.internet.endpoints import TCP4ClientEndpoint 
 from twisted.internet.protocol import Factory, ServerFactory
 from twisted.protocols import amp
 import time
@@ -28,6 +27,10 @@
 log = Logger()
 
 
+# Control socket message-routing constants
+PUSH_ROUTE = "push"
+
+
 # AMP Commands sent to server
 
 class SubscribeToID(amp.Command):
@@ -40,7 +43,7 @@
     response = [('status', amp.String())]
 
 
-# AMP Commands sent to client
+# AMP Commands sent to client (and forwarded to Master)
 
 class NotificationForID(amp.Command):
     arguments = [('id', amp.String()), ('dataChangedTimestamp', amp.Integer())]
@@ -49,29 +52,88 @@
 
 # Server classes
 
+class AMPPushForwardingFactory(Factory, LoggingMixIn):
 
-class AMPPushNotifierService(StreamServerEndpointService, LoggingMixIn):
+    def __init__(self, forwarder):
+        self.forwarder = forwarder
+
+    def buildProtocol(self, addr):
+        protocol = amp.AMP()
+        self.forwarder.protocols.append(protocol)
+        return protocol
+
+class AMPPushForwarder(LoggingMixIn):
     """
+    Runs in the slaves, forwards notifications to the master via AMP
+    """
+    def __init__(self, controlSocket):
+        self.protocols = []
+        controlSocket.addFactory(PUSH_ROUTE, AMPPushForwardingFactory(self))
+
+    @inlineCallbacks
+    def enqueue(self, id, dataChangedTimestamp=None):
+        if dataChangedTimestamp is None:
+            dataChangedTimestamp = int(time.time())
+        for protocol in self.protocols:
+            yield protocol.callRemote(NotificationForID, id=id,
+                dataChangedTimestamp=dataChangedTimestamp)
+
+
+
+class AMPPushMasterListeningProtocol(amp.AMP, LoggingMixIn):
+    """
+    Listens for notifications coming in over AMP from the slaves
+    """
+    def __init__(self, master):
+        super(AMPPushMasterListeningProtocol, self).__init__()
+        self.master = master
+
+    @NotificationForID.responder
+    def enqueueFromWorker(self, id, dataChangedTimestamp=None):
+        if dataChangedTimestamp is None:
+            dataChangedTimestamp = int(time.time())
+        self.master.enqueue(id, dataChangedTimestamp=dataChangedTimestamp)
+        return {"status" : "OK"}
+ 
+
+class AMPPushMasterListenerFactory(Factory, LoggingMixIn):
+
+    def __init__(self, master):
+        self.master = master
+
+    def buildProtocol(self, addr):
+        protocol = AMPPushMasterListeningProtocol(self.master)
+        return protocol
+
+
+class AMPPushMaster(LoggingMixIn):
+    """
     AMPPushNotifierService allows clients to use AMP to subscribe to,
     and receive, change notifications.
     """
 
-    @classmethod
-    def makeService(cls, settings, ignored, reactor=None):
-        return cls(settings, reactor=reactor)
-
-    def __init__(self, settings, reactor=None):
+    def __init__(self, controlSocket, parentService, port, enableStaggering,
+        staggerSeconds, reactor=None):
         if reactor is None:
             from twisted.internet import reactor
-        factory = AMPPushNotifierFactory(self)
-        endpoint = TCP4ServerEndpoint(reactor, settings["Port"])
-        super(AMPPushNotifierService, self).__init__(endpoint, factory)
+        from twisted.application.strports import service as strPortsService
+
+        if port:
+            # Service which listens for client subscriptions and sends
+            # notifications to them
+            strPortsService(str(port), AMPPushNotifierFactory(self),
+                reactor=reactor).setServiceParent(parentService)
+
+        if controlSocket is not None:
+            # Set up the listener which gets notifications from the slaves
+            controlSocket.addFactory(PUSH_ROUTE,
+                AMPPushMasterListenerFactory(self))
+
         self.subscribers = []
-        self.dataHost = settings["DataHost"]
 
-        if settings["EnableStaggering"]:
+        if enableStaggering:
             self.scheduler = PushScheduler(reactor, self.sendNotification,
-                staggerSeconds=settings["StaggerSeconds"])
+                staggerSeconds=staggerSeconds)
         else:
             self.scheduler = None
 
@@ -83,45 +145,32 @@
         self.log_debug("Removed subscriber")
         self.subscribers.remove(p)
 
-    def enqueue(self, id, dataChangedTimestamp=None):
+    def enqueue(self, pushKey, dataChangedTimestamp=None):
         """
-        Sends an AMP push notification to any clients subscribing to this id.
+        Sends an AMP push notification to any clients subscribing to this pushKey.
 
-        @param id: The identifier of the resource that was updated, including
+        @param pushKey: The identifier of the resource that was updated, including
             a prefix indicating whether this is CalDAV or CardDAV related.
-            The prefix is separated from the id with "|", e.g.:
 
-            "CalDAV|abc/def"
+            "/CalDAV/abc/def/"
 
-            The id is an opaque token as far as this code is concerned, and
-            is used in conjunction with the prefix and the server hostname
-            to build the actual key value that devices subscribe to.
-        @type id: C{str}
+        @type pushKey: C{str}
         @param dataChangedTimestamp: Timestamp (epoch seconds) for the data change
             which triggered this notification (Only used for unit tests)
             @type key: C{int}
         """
 
-        try:
-            protocol, id = id.split("|", 1)
-        except ValueError:
-            # id has no protocol, so we can't do anything with it
-            self.log_error("Notification id '%s' is missing protocol" % (id,))
-            return
-
         # Unit tests can pass this value in; otherwise it defaults to now
         if dataChangedTimestamp is None:
             dataChangedTimestamp = int(time.time())
 
-        id = "/%s/%s/%s/" % (protocol, self.dataHost, id)
-
         tokens = []
         for subscriber in self.subscribers:
-            token = subscriber.subscribedToID(id)
+            token = subscriber.subscribedToID(pushKey)
             if token is not None:
                 tokens.append(token)
         if tokens:
-            return self.scheduleNotifications(tokens, id, dataChangedTimestamp)
+            return self.scheduleNotifications(tokens, pushKey, dataChangedTimestamp)
 
 
     @inlineCallbacks

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/applepush.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/applepush.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/applepush.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -88,7 +88,6 @@
         service.store = store
         service.providers = {}
         service.feedbacks = {}
-        service.dataHost = settings["DataHost"]
         service.purgeCall = None
         service.purgeIntervalSeconds = settings["SubscriptionPurgeIntervalSeconds"]
         service.purgeSeconds = settings["SubscriptionPurgeSeconds"]
@@ -177,31 +176,27 @@
 
 
     @inlineCallbacks
-    def enqueue(self, id, dataChangedTimestamp=None):
+    def enqueue(self, pushKey, dataChangedTimestamp=None):
         """
         Sends an Apple Push Notification to any device token subscribed to
-        this id.
+        this pushKey.
 
-        @param id: The identifier of the resource that was updated, including
+        @param pushKey: The identifier of the resource that was updated, including
             a prefix indicating whether this is CalDAV or CardDAV related.
-            The prefix is separated from the id with "|", e.g.:
 
-            "CalDAV|abc/def"
+            "/CalDAV/abc/def/"
 
-            The id is an opaque token as far as this code is concerned, and
-            is used in conjunction with the prefix and the server hostname
-            to build the actual key value that devices subscribe to.
-        @type id: C{str}
+        @type pushKey: C{str}
         @param dataChangedTimestamp: Timestamp (epoch seconds) for the data change
             which triggered this notification (Only used for unit tests)
         @type key: C{int}
         """
 
         try:
-            protocol, id = id.split("|", 1)
+            protocol = pushKey.split("/")[1]
         except ValueError:
-            # id has no protocol, so we can't do anything with it
-            self.log_error("Notification id '%s' is missing protocol" % (id,))
+            # pushKey has no protocol, so we can't do anything with it
+            self.log_error("Push key '%s' is missing protocol" % (pushKey,))
             return
 
         # Unit tests can pass this value in; otherwise it defaults to now
@@ -210,23 +205,22 @@
 
         provider = self.providers.get(protocol, None)
         if provider is not None:
-            key = "/%s/%s/%s/" % (protocol, self.dataHost, id)
 
             # Look up subscriptions for this key
             txn = self.store.newTransaction()
-            subscriptions = (yield txn.apnSubscriptionsByKey(key))
+            subscriptions = (yield txn.apnSubscriptionsByKey(pushKey))
             yield txn.commit()
 
             numSubscriptions = len(subscriptions)
             if numSubscriptions > 0:
                 self.log_debug("Sending %d APNS notifications for %s" %
-                    (numSubscriptions, key))
+                    (numSubscriptions, pushKey))
                 tokens = []
                 for token, uid in subscriptions:
                     if token and uid:
                         tokens.append(token)
                 if tokens:
-                    provider.scheduleNotifications(tokens, key, dataChangedTimestamp)
+                    provider.scheduleNotifications(tokens, pushKey, dataChangedTimestamp)
 
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_amppush.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_amppush.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_amppush.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,30 +14,18 @@
 # limitations under the License.
 ##
 
-from calendarserver.push.amppush import AMPPushNotifierService, AMPPushNotifierProtocol
+from calendarserver.push.amppush import AMPPushMaster, AMPPushNotifierProtocol
 from calendarserver.push.amppush import NotificationForID
 from twistedcaldav.test.util import TestCase
-from twisted.internet.defer import inlineCallbacks
 from twisted.internet.task import Clock
 
-class AMPPushNotifierServiceTests(TestCase):
+class AMPPushMasterTests(TestCase):
 
-    @inlineCallbacks
-    def test_AMPPushNotifierService(self):
+    def test_AMPPushMaster(self):
 
-        settings = {
-            "Service" : "calendarserver.push.amppush.AMPPushNotifierService",
-            "Enabled" : True,
-            "Port" : 62311,
-            "EnableStaggering" : True,
-            "StaggerSeconds" : 3,
-            "DataHost" : "localhost",
-        }
-
         # Set up the service
         clock = Clock()
-        service = (yield AMPPushNotifierService.makeService(settings,
-            None, reactor=clock))
+        service = AMPPushMaster(None, None, 0, True, 3, reactor=clock)
 
         self.assertEquals(service.subscribers, [])
 
@@ -69,7 +57,7 @@
         self.assertTrue(client3.subscribedToID("/CalDAV/localhost/user03/"))
 
         dataChangedTimestamp = 1354815999
-        service.enqueue("CalDAV|user01", dataChangedTimestamp=dataChangedTimestamp)
+        service.enqueue("/CalDAV/localhost/user01/", dataChangedTimestamp=dataChangedTimestamp)
         self.assertEquals(len(client1.history), 0)
         self.assertEquals(len(client2.history), 0)
         self.assertEquals(len(client3.history), 0)
@@ -86,7 +74,7 @@
         client1.reset()
         client2.reset()
         client2.unsubscribe("token2", "/CalDAV/localhost/user01/")
-        service.enqueue("CalDAV|user01", dataChangedTimestamp=dataChangedTimestamp)
+        service.enqueue("/CalDAV/localhost/user01/", dataChangedTimestamp=dataChangedTimestamp)
         self.assertEquals(len(client1.history), 0)
         clock.advance(1)
         self.assertEquals(client1.history, [(NotificationForID, {'id': '/CalDAV/localhost/user01/', 'dataChangedTimestamp' : 1354815999})])
@@ -99,7 +87,7 @@
         client1.reset()
         client2.reset()
         client2.subscribe("token2", "/CalDAV/localhost/user01/")
-        service.enqueue("CalDAV|user01", dataChangedTimestamp=dataChangedTimestamp)
+        service.enqueue("/CalDAV/localhost/user01/", dataChangedTimestamp=dataChangedTimestamp)
         self.assertEquals(client1.history, [(NotificationForID, {'id': '/CalDAV/localhost/user01/', 'dataChangedTimestamp' : 1354815999})])
         self.assertEquals(client2.history, [(NotificationForID, {'id': '/CalDAV/localhost/user01/', 'dataChangedTimestamp' : 1354815999})])
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_applepush.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_applepush.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_applepush.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -38,12 +38,10 @@
     def test_ApplePushNotifierService(self):
 
         settings = {
-            "Service" : "calendarserver.push.applepush.ApplePushNotifierService",
             "Enabled" : True,
             "SubscriptionURL" : "apn",
             "SubscriptionPurgeSeconds" : 24 * 60 * 60,
             "SubscriptionPurgeIntervalSeconds" : 24 * 60 * 60,
-            "DataHost" : "calendars.example.com",
             "ProviderHost" : "gateway.push.apple.com",
             "ProviderPort" : 2195,
             "FeedbackHost" : "feedback.push.apple.com",
@@ -127,7 +125,7 @@
 
         # Notification arrives from calendar server
         dataChangedTimestamp = 1354815999
-        yield service.enqueue("CalDAV|user01/calendar",
+        yield service.enqueue("/CalDAV/calendars.example.com/user01/calendar/",
             dataChangedTimestamp=dataChangedTimestamp)
 
         # The notifications should be in the queue
@@ -167,7 +165,7 @@
         # Reset sent data
         providerConnector.transport.data = None
         # Send notification while service is connected
-        yield service.enqueue("CalDAV|user01/calendar")
+        yield service.enqueue("/CalDAV/calendars.example.com/user01/calendar/")
         clock.advance(1) # so that first push is sent
         self.assertEquals(len(providerConnector.transport.data), 183)
         # Reset sent data

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_notifier.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_notifier.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_notifier.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,15 +15,16 @@
 ##
 
 from twistedcaldav.test.util import TestCase
+from calendarserver.push.notifier import PushDistributor
+from calendarserver.push.notifier import getPubSubAPSConfiguration
+from calendarserver.push.notifier import PushNotificationWork
+from twisted.internet.defer import inlineCallbacks, succeed
 from twistedcaldav.config import ConfigDict
-from calendarserver.push.notifier import PushService
-from twisted.internet.defer import inlineCallbacks, succeed
-from twisted.application import service
+from txdav.common.datastore.test.util import buildStore
 
-class StubService(service.Service):
-    def __init__(self, settings, store):
-        self.settings = settings
-        self.store = store
+
+class StubService(object):
+    def __init__(self):
         self.reset()
 
     def reset(self):
@@ -33,25 +34,89 @@
         self.history.append(id)
         return(succeed(None))
 
-    @classmethod
-    def makeService(cls, settings, store):
-        return cls(settings, store)
+class PushDistributorTests(TestCase):
 
-class PushServiceTests(TestCase):
-
     @inlineCallbacks
     def test_enqueue(self):
-        settings = ConfigDict({
-            "Services" : {
-                "Stub" : {
-                    "Service" : "calendarserver.push.test.test_notifier.StubService",
-                    "Enabled" : True,
-                    "Foo" : "Bar",
+        stub = StubService()
+        dist = PushDistributor([stub])
+        yield dist.enqueue("testing")
+        self.assertEquals(stub.history, ["testing"])
+
+    def test_getPubSubAPSConfiguration(self):
+        config = ConfigDict({
+            "EnableSSL" : True,
+            "ServerHostName" : "calendars.example.com",
+            "SSLPort" : 8443,
+            "HTTPPort" : 8008,
+            "Notifications" : {
+                "Services" : {
+                    "APNS" : {
+                        "CalDAV" : {
+                            "Topic" : "test topic",
+                        },
+                        "SubscriptionRefreshIntervalSeconds" : 42,
+                        "SubscriptionURL" : "apns",
+                        "Environment" : "prod",
+                        "Enabled" : True,
+                    },
                 },
             },
         })
-        svc = PushService.makeService(settings, None)
-        yield svc.enqueue("testing")
-        self.assertEquals(svc.subServices[0].history, ["testing"])
+        result = getPubSubAPSConfiguration("CalDAV|foo", config)
+        self.assertEquals(
+            result,
+            {
+                "SubscriptionRefreshIntervalSeconds": 42, 
+                "SubscriptionURL": "https://calendars.example.com:8443/apns", 
+                "APSBundleID": "test topic", 
+                "APSEnvironment": "prod"
+            }
+        )
 
 
+class StubDistributor(object):
+    def __init__(self):
+        self.reset()
+
+    def reset(self):
+        self.history = []
+
+    def enqueue(self, pushID):
+        self.history.append(pushID)
+
+class PushNotificationWorkTests(TestCase):
+
+    @inlineCallbacks
+    def test_work(self):
+        self.store = yield buildStore(self, None)
+
+        pushDistributor = StubDistributor()
+
+        def decorateTransaction(txn):
+            txn._pushDistributor = pushDistributor
+
+        self.store.callWithNewTransactions(decorateTransaction)
+
+        txn = self.store.newTransaction()
+        wp = (yield txn.enqueue(PushNotificationWork,
+            pushID="/CalDAV/localhost/foo/",
+        ))
+        yield txn.commit()
+        yield wp.whenExecuted()
+        self.assertEquals(pushDistributor.history, ["/CalDAV/localhost/foo/"])
+
+        pushDistributor.reset()
+        txn = self.store.newTransaction()
+        wp = (yield txn.enqueue(PushNotificationWork,
+            pushID="/CalDAV/localhost/bar/",
+        ))
+        wp = (yield txn.enqueue(PushNotificationWork,
+            pushID="/CalDAV/localhost/bar/",
+        ))
+        wp = (yield txn.enqueue(PushNotificationWork,
+            pushID="/CalDAV/localhost/bar/",
+        ))
+        yield txn.commit()
+        yield wp.whenExecuted()
+        self.assertEquals(pushDistributor.history, ["/CalDAV/localhost/bar/"])

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/caldav.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/caldav.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 __all__ = [
     "CalDAVService",
@@ -105,7 +106,9 @@
 from calendarserver.tap.util import oracleConnectorFromConfig
 from calendarserver.tap.cfgchild import ConfiguredChildSpawner
 from calendarserver.tools.util import checkDirectory
-from calendarserver.push.notifier import PushService
+from calendarserver.push.notifier import PushDistributor
+from calendarserver.push.amppush import AMPPushMaster, AMPPushForwarder
+from calendarserver.push.applepush import ApplePushNotifierService
 from twistedcaldav.scheduling.imip.inbound import MailRetriever
 
 try:
@@ -366,7 +369,7 @@
             self.loadConfiguration()
             self.checkConfiguration()
         except ConfigurationError, e:
-            print "Invalid configuration: %s" % (e,)
+            print("Invalid configuration: %s" % (e,))
             sys.exit(1)
 
 
@@ -375,7 +378,7 @@
             raise ConfigurationError("Config file %s not found. Exiting."
                                      % (self["config"],))
 
-        print "Reading configuration from file: %s" % (self["config"],)
+        print("Reading configuration from file: %s" % (self["config"],))
 
         config.load(self["config"])
         config.updateDefaults(self.overrides)
@@ -390,7 +393,7 @@
         # Having CalDAV *and* CardDAV both disabled is an illegal configuration
         # for a running server (but is fine for command-line utilities)
         if not config.EnableCalDAV and not config.EnableCardDAV:
-            print "Neither EnableCalDAV nor EnableCardDAV are set to True."
+            print("Neither EnableCalDAV nor EnableCardDAV are set to True.")
             sys.exit(1)
 
         uid, gid = None, None
@@ -539,7 +542,6 @@
             )
             self.monitor.addProcessObject(process, PARENT_ENVIRONMENT)
 
-
         if config.GroupCaching.Enabled and config.GroupCaching.EnableUpdater:
             self.maker.log_info("Adding group caching service")
 
@@ -710,18 +712,56 @@
         """
         pool, txnFactory = getDBPool(config)
         store = storeFromConfig(config, txnFactory)
-        result = self.requestProcessingService(options, store)
+        logObserver = AMPCommonAccessLoggingObserver()
+        result = self.requestProcessingService(options, store, logObserver)
         directory = result.rootResource.getDirectory()
         if pool is not None:
             pool.setServiceParent(result)
 
+        if config.ControlSocket:
+            id = config.ControlSocket
+            self.log_info("Control via AF_UNIX: %s" % (id,))
+            endpointFactory = lambda reactor: UNIXClientEndpoint(
+                reactor, id)
+        else:
+            id = int(config.ControlPort)
+            self.log_info("Control via AF_INET: %d" % (id,))
+            endpointFactory = lambda reactor: TCP4ClientEndpoint(
+                reactor, "127.0.0.1", id)
+        controlSocketClient = ControlSocket()
+        class LogClient(AMP):
+            def startReceivingBoxes(self, sender):
+                super(LogClient, self).startReceivingBoxes(sender)
+                logObserver.addClient(self)
+        f = Factory()
+        f.protocol = LogClient
+        controlSocketClient.addFactory(_LOG_ROUTE, f)
+        from txdav.common.datastore.sql import CommonDataStore as SQLStore
+        if isinstance(store, SQLStore):
+            def queueMasterAvailable(connectionFromMaster):
+                store.queuer = store.queuer.transferProposalCallbacks(connectionFromMaster)
+            queueFactory = QueueWorkerFactory(store.newTransaction, schema,
+                                              queueMasterAvailable)
+            controlSocketClient.addFactory(_QUEUE_ROUTE, queueFactory)
+        controlClient = ControlSocketConnectingService(
+            endpointFactory, controlSocketClient
+        )
+        controlClient.setServiceParent(result)
 
         # Optionally set up push notifications
+        pushDistributor = None
         if config.Notifications.Enabled:
-            pushService = PushService.makeService(config.Notifications, store)
-            pushService.setServiceParent(result)
-        else:
-            pushService = None
+            observers = []
+            if config.Notifications.Services.APNS.Enabled:
+                pushSubService = ApplePushNotifierService.makeService(
+                    config.Notifications.Services.APNS, store)
+                observers.append(pushSubService)
+                pushSubService.setServiceParent(result)
+            if config.Notifications.Services.AMP.Enabled:
+                pushSubService = AMPPushForwarder(controlSocketClient)
+                observers.append(pushSubService)
+            if observers:
+                pushDistributor = PushDistributor(observers)
 
         # Optionally set up mail retrieval
         if config.Scheduling.iMIP.Enabled:
@@ -732,7 +772,7 @@
             mailRetriever = None
 
         def decorateTransaction(txn):
-            txn._pushService = pushService
+            txn._pushDistributor = pushDistributor
             txn._rootResource = result.rootResource
             txn._mailRetriever = mailRetriever
 
@@ -755,15 +795,15 @@
                     "passwd" : config.Manhole.PasswordFilePath,
                 })
                 manholeService.setServiceParent(result)
-                # Using print because logging isn't ready at this point
-                print "Manhole access enabled: %s" % (portString,)
+                # Using print(because logging isn't ready at this point)
+                print("Manhole access enabled: %s" % (portString,))
             except ImportError:
-                print "Manhole access could not enabled because manhole_tap could not be imported"
+                print("Manhole access could not enabled because manhole_tap could not be imported")
 
         return result
 
 
-    def requestProcessingService(self, options, store):
+    def requestProcessingService(self, options, store, logObserver):
         """
         Make a service that will actually process HTTP requests.
 
@@ -787,52 +827,8 @@
         #
         self.log_info("Setting up service")
 
-        bonusServices = []
-
-        if config.ProcessType == "Slave":
-            logObserver = AMPCommonAccessLoggingObserver()
-
-            if config.ControlSocket:
-                id = config.ControlSocket
-                self.log_info("Control via AF_UNIX: %s" % (id,))
-                endpointFactory = lambda reactor: UNIXClientEndpoint(
-                    reactor, id)
-            else:
-                id = int(config.ControlPort)
-                self.log_info("Control via AF_INET: %d" % (id,))
-                endpointFactory = lambda reactor: TCP4ClientEndpoint(
-                    reactor, "127.0.0.1", id)
-            controlSocketClient = ControlSocket()
-            class LogClient(AMP):
-                def startReceivingBoxes(self, sender):
-                    super(LogClient, self).startReceivingBoxes(sender)
-                    logObserver.addClient(self)
-            f = Factory()
-            f.protocol = LogClient
-            controlSocketClient.addFactory(_LOG_ROUTE, f)
-            from txdav.common.datastore.sql import CommonDataStore as SQLStore
-            if isinstance(store, SQLStore):
-                def queueMasterAvailable(connectionFromMaster):
-                    store.queuer = store.queuer.transferProposalCallbacks(connectionFromMaster)
-                queueFactory = QueueWorkerFactory(store.newTransaction, schema,
-                                                  queueMasterAvailable)
-                controlSocketClient.addFactory(_QUEUE_ROUTE, queueFactory)
-            controlClient = ControlSocketConnectingService(
-                endpointFactory, controlSocketClient
-            )
-            bonusServices.append(controlClient)
-        elif config.ProcessType == "Single":
-            # Make sure no old socket files are lying around.
-            self.deleteStaleSocketFiles()
-            logObserver = RotatingFileAccessLoggingObserver(
-                config.AccessLogFile,
-            )
-
         self.log_info("Configuring access log observer: %s" % (logObserver,))
-
         service = CalDAVService(logObserver)
-        for bonus in bonusServices:
-            bonus.setServiceParent(service)
 
         rootResource = getRootResource(config, store, additional)
         service.rootResource = rootResource
@@ -1019,13 +1015,57 @@
         Create a service to be used in a single-process, stand-alone
         configuration.
         """
-        def slaveSvcCreator(pool, store):
-            return self.requestProcessingService(options, store)
+        def slaveSvcCreator(pool, store, logObserver):
+            result = self.requestProcessingService(options, store, logObserver)
 
+            # Optionally set up push notifications
+            pushDistributor = None
+            if config.Notifications.Enabled:
+                observers = []
+                if config.Notifications.Services.APNS.Enabled:
+                    pushSubService = ApplePushNotifierService.makeService(
+                        config.Notifications.Services.APNS, store)
+                    observers.append(pushSubService)
+                    pushSubService.setServiceParent(result)
+                if config.Notifications.Services.AMP.Enabled:
+                    pushSubService = AMPPushMaster(None, result,
+                        config.Notifications.Services.AMP.Port,
+                        config.Notifications.Services.AMP.EnableStaggering,
+                        config.Notifications.Services.AMP.StaggerSeconds
+                        )
+                    observers.append(pushSubService)
+                if observers:
+                    pushDistributor = PushDistributor(observers)
+
+            # Optionally set up mail retrieval
+            if config.Scheduling.iMIP.Enabled:
+                directory = result.rootResource.getDirectory()
+                mailRetriever = MailRetriever(store, directory,
+                    config.Scheduling.iMIP.Receiving)
+                mailRetriever.setServiceParent(result)
+            else:
+                mailRetriever = None
+
+            def decorateTransaction(txn):
+                txn._pushDistributor = pushDistributor
+                txn._rootResource = result.rootResource
+                txn._mailRetriever = mailRetriever
+
+            store.callWithNewTransactions(decorateTransaction)
+
+            return result 
+
         uid, gid = getSystemIDs(config.UserName, config.GroupName)
-        return self.storageService(slaveSvcCreator, uid=uid, gid=gid)
 
+        # Make sure no old socket files are lying around.
+        self.deleteStaleSocketFiles()
+        logObserver = RotatingFileAccessLoggingObserver(
+            config.AccessLogFile,
+        )
 
+        return self.storageService(slaveSvcCreator, logObserver, uid=uid, gid=gid)
+
+
     def makeService_Utility(self, options):
         """
         Create a service to be used in a command-line utility
@@ -1034,14 +1074,14 @@
         When created, that service will have access to the storage facilities.
         """
 
-        def toolServiceCreator(pool, store):
+        def toolServiceCreator(pool, store, ignored):
             return config.UtilityServiceClass(store)
 
         uid, gid = getSystemIDs(config.UserName, config.GroupName)
-        return self.storageService(toolServiceCreator, uid=uid, gid=gid)
+        return self.storageService(toolServiceCreator, None, uid=uid, gid=gid)
 
 
-    def storageService(self, createMainService, uid=None, gid=None):
+    def storageService(self, createMainService, logObserver, uid=None, gid=None):
         """
         If necessary, create a service to be started used for storage; for
         example, starting a database backend.  This service will then start the
@@ -1080,7 +1120,7 @@
                                     maxConnections=config.MaxDBConnectionsPerPool)
                 cp.setServiceParent(ms)
                 store = storeFromConfig(config, cp.connection)
-                mainService = createMainService(cp, store)
+                mainService = createMainService(cp, store, logObserver)
                 if config.SharedConnectionPool:
                     dispenser = ConnectionDispenser(cp)
                 else:
@@ -1111,6 +1151,7 @@
                             store, uid=overrideUID, gid=overrideGID,
                         ),
                         store, uid=overrideUID, gid=overrideGID,
+                        failIfUpgradeNeeded=config.FailIfUpgradeNeeded,
                     )
                 )
                 upgradeSvc.setServiceParent(ms)
@@ -1153,7 +1194,7 @@
                 raise UsageError("Unknown database type %r" (config.DBType,))
         else:
             store = storeFromConfig(config, None)
-            return createMainService(None, store)
+            return createMainService(None, store, logObserver)
 
 
     def makeService_Combined(self, options):
@@ -1196,6 +1237,17 @@
 
         controlSocket = ControlSocket()
         controlSocket.addFactory(_LOG_ROUTE, logger)
+
+        # Optionally set up AMPPushMaster
+        if config.Notifications.Enabled and config.Notifications.Services.AMP.Enabled:
+            ampSettings = config.Notifications.Services.AMP
+            AMPPushMaster(
+                controlSocket,
+                s,
+                ampSettings["Port"],
+                ampSettings["EnableStaggering"],
+                ampSettings["StaggerSeconds"]
+            )
         if config.ControlSocket:
             controlSocketService = GroupOwnedUNIXServer(
                 gid, config.ControlSocket, controlSocket, mode=0660
@@ -1324,10 +1376,10 @@
                     "passwd" : config.Manhole.PasswordFilePath,
                 })
                 manholeService.setServiceParent(s)
-                # Using print because logging isn't ready at this point
-                print "Manhole access enabled: %s" % (portString,)
+                # Using print(because logging isn't ready at this point)
+                print("Manhole access enabled: %s" % (portString,))
             except ImportError:
-                print "Manhole access could not enabled because manhole_tap could not be imported"
+                print("Manhole access could not enabled because manhole_tap could not be imported")
 
 
         # Finally, let's get the real show on the road.  Create a service that
@@ -1338,7 +1390,7 @@
         # to), and second, the service which does an upgrade from the
         # filesystem to the database (if that's necessary, and there is
         # filesystem data in need of upgrading).
-        def spawnerSvcCreator(pool, store):
+        def spawnerSvcCreator(pool, store, ignored):
             from twisted.internet import reactor
             pool = PeerConnectionPool(reactor, store.newTransaction,
                                       7654, schema)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/util.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/util.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -225,7 +225,8 @@
     if config.Notifications.Enabled:
         # FIXME: NotifierFactory needs reference to the store in order
         # to get a txn in order to create a Work item
-        notifierFactory = NotifierFactory(None, config.ServerHostName)
+        notifierFactory = NotifierFactory(None, config.ServerHostName,
+            config.Notifications.CoalesceSeconds)
     else:
         notifierFactory = None
     quota = config.UserQuota
@@ -654,7 +655,7 @@
     #
     # Apple Push Notification Subscriptions
     #
-    apnConfig = config.Notifications.Services["ApplePushNotifier"]
+    apnConfig = config.Notifications.Services.APNS
     if apnConfig.Enabled:
         log.info("Setting up APNS resource at /%s" %
             (apnConfig["SubscriptionURL"],))


Property changes on: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools
___________________________________________________________________
Modified: svn:ignore
   - *.pyc

   + *.pyc
config.py.edited


Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/ampnotifications.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/ampnotifications.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/ampnotifications.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from calendarserver.push.amppush import subscribeToIDs
 from calendarserver.tools.cmdline import utilityMain
@@ -34,17 +35,17 @@
 def usage(e=None):
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] [pushkey ...]" % (name,)
-    print ""
-    print "  Monitor AMP Push Notifications"
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -f --config <path>: Specify caldavd.plist configuration path"
-    print "  -p --port <port>: AMP port to connect to"
-    print "  -s --server <hostname>: AMP server to connect to"
-    print "  --debug: verbose logging"
-    print ""
+    print("usage: %s [options] [pushkey ...]" % (name,))
+    print("")
+    print("  Monitor AMP Push Notifications")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -f --config <path>: Specify caldavd.plist configuration path")
+    print("  -p --port <port>: AMP port to connect to")
+    print("  -s --server <hostname>: AMP server to connect to")
+    print("  --debug: verbose logging")
+    print("")
 
     if e:
         sys.stderr.write("%s\n" % (e,))
@@ -141,13 +142,13 @@
 
 
 def notificationCallback(id, dataChangedTimestamp):
-    print "Received notification for:", id
+    print("Received notification for:", id)
     return succeed(True)
 
 
 
 @inlineCallbacks
 def monitorAMPNotifications(hostname, port, ids):
-    print "Subscribing to notifications..."
+    print("Subscribing to notifications...")
     yield subscribeToIDs(hostname, port, ids, notificationCallback)
-    print "Waiting for notifications..."
+    print("Waiting for notifications...")

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/anonymize.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/anonymize.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/anonymize.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,7 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
-
+from __future__ import print_function
 from __future__ import with_statement
 
 from getopt import getopt, GetoptError
@@ -47,20 +47,20 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] source destination" % (name,)
-    print ""
-    print "  Anonymizes calendar data"
-    print ""
-    print "  source and destination should refer to document root directories"
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -n --node <node>: Directory node (defaults to /Search)"
-    print ""
+    print("usage: %s [options] source destination" % (name,))
+    print("")
+    print("  Anonymizes calendar data")
+    print("")
+    print("  source and destination should refer to document root directories")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -n --node <node>: Directory node (defaults to /Search)")
+    print("")
 
     if e:
         sys.exit(64)
@@ -110,14 +110,14 @@
 def anonymizeRoot(directoryMap, sourceDirectory, destDirectory):
     # sourceDirectory and destDirectory are DocumentRoots
 
-    print "Anonymizing calendar data from %s into %s" % (sourceDirectory, destDirectory)
+    print("Anonymizing calendar data from %s into %s" % (sourceDirectory, destDirectory))
 
     homes = 0
     calendars = 0
     resources = 0
 
     if not os.path.exists(sourceDirectory):
-        print "Can't find source: %s" % (sourceDirectory,)
+        print("Can't find source: %s" % (sourceDirectory,))
         sys.exit(1)
 
     if not os.path.exists(destDirectory):
@@ -147,7 +147,7 @@
                         for home in os.listdir(secondPath):
                             record = directoryMap.lookupCUA(home)
                             if not record:
-                                print "Couldn't find %s, skipping." % (home,)
+                                print("Couldn't find %s, skipping." % (home,))
                                 continue
                             sourceHome = os.path.join(secondPath, home)
                             destHome = os.path.join(destUidHomes,
@@ -162,13 +162,13 @@
                     continue
                 record = directoryMap.lookupCUA(home)
                 if not record:
-                    print "Couldn't find %s, skipping." % (home,)
+                    print("Couldn't find %s, skipping." % (home,))
                     continue
                 sourceHome = os.path.join(sourceUidHomes, home)
                 destHome = os.path.join(destUidHomes, record['guid'])
                 homeList.append((sourceHome, destHome, record))
 
-        print "Processing %d calendar homes..." % (len(homeList),)
+        print("Processing %d calendar homes..." % (len(homeList),))
 
         for sourceHome, destHome, record in homeList:
             quotaUsed = 0
@@ -268,23 +268,23 @@
             )
 
             if not (homes % 100):
-                print " %d..." % (homes,)
+                print(" %d..." % (homes,))
 
-    print "Done."
-    print ""
+    print("Done.")
+    print("")
 
-    print "Calendar totals:"
-    print " Calendar homes: %d" % (homes,)
-    print " Calendars: %d" % (calendars,)
-    print " Events: %d" % (resources,)
-    print ""
+    print("Calendar totals:")
+    print(" Calendar homes: %d" % (homes,))
+    print(" Calendars: %d" % (calendars,))
+    print(" Events: %d" % (resources,))
+    print("")
 
 
 def anonymizeData(directoryMap, data):
     try:
         pyobj = PyCalendar.parseText(data)
     except Exception, e:
-        print "Failed to parse (%s): %s" % (e, data)
+        print("Failed to parse (%s): %s" % (e, data))
         return None
 
     # Delete property from the top level
@@ -303,7 +303,7 @@
                     cua = prop.getValue().getValue()
                     record = directoryMap.lookupCUA(cua)
                     if record is None:
-                        # print "Can't find record for", cua
+                        # print("Can't find record for", cua)
                         record = directoryMap.addRecord(cua=cua)
                         if record is None:
                             comp.removeProperty(prop)
@@ -371,10 +371,10 @@
             'resources' : ('Resources', 'resource'),
         }
 
-        print "Fetching records from directory: %s" % (node,)
+        print("Fetching records from directory: %s" % (node,))
 
         for internalType, (recordType, friendlyType) in self.strings.iteritems():
-            print " %s..." % (internalType,)
+            print(" %s..." % (internalType,))
             child = Popen(
                 args = [
                     "/usr/bin/dscl", "-plist", node, "-readall",
@@ -402,8 +402,8 @@
                         names=origRecordNames, emails=origEmails,
                         members=origMembers)
 
-        print "Done."
-        print ""
+        print("Done.")
+        print("")
 
     def addRecord(self, internalType="users", guid=None, names=None,
         emails=None, members=None, cua=None):
@@ -450,7 +450,7 @@
                     name = urllib.quote(name).lower()
                     keys.append(name)
                 except:
-                    # print "Failed to urllib.quote( ) %s. Skipping." % (name,)
+                    # print("Failed to urllib.quote( ) %s. Skipping." % (name,))
                     pass
         if emails:
             for email in emails:
@@ -483,13 +483,13 @@
 
 
     def printStats(self):
-        print "Directory totals:"
+        print("Directory totals:")
         for internalType, (recordType, ignore) in self.strings.iteritems():
-            print " %s: %d" % (recordType, self.counts[internalType])
+            print(" %s: %d" % (recordType, self.counts[internalType]))
 
         unknown = self.counts['unknown']
         if unknown:
-            print " Principals not found in directory: %d" % (unknown,)
+            print(" Principals not found in directory: %d" % (unknown,))
 
     def dumpDsImports(self, dirPath):
         if not os.path.exists(dirPath):
@@ -587,7 +587,7 @@
         try:
             text = text.encode('utf-8')
         except UnicodeEncodeError:
-            print "Failed to anonymize:", text
+            print("Failed to anonymize:", text)
             text = "Anonymize me!"
     h = hashlib.md5(text)
     h = h.hexdigest()

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/backup_pg.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/backup_pg.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/backup_pg.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from getopt import getopt, GetoptError
 import os
@@ -38,19 +39,19 @@
 
 def usage(e=None):
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] command backup-file" % (name,)
-    print ""
-    print " Backup or restore calendar and addressbook data"
-    print ""
-    print "options:"
-    print "  -f --config <path>: Specify caldavd.plist configuration path"
-    print "  -h --help: print this help and exit"
-    print "  -v --verbose: print additional information"
-    print ""
-    print "commands:"
-    print "  backup: create backup-file in compressed tar format (tgz)"
-    print "  restore: restore from backup-file"
-    print ""
+    print("usage: %s [options] command backup-file" % (name,))
+    print("")
+    print(" Backup or restore calendar and addressbook data")
+    print("")
+    print("options:")
+    print("  -f --config <path>: Specify caldavd.plist configuration path")
+    print("  -h --help: print this help and exit")
+    print("  -v --verbose: print additional information")
+    print("")
+    print("commands:")
+    print("  backup: create backup-file in compressed tar format (tgz)")
+    print("  restore: restore from backup-file")
+    print("")
 
     if e:
         sys.stderr.write("%s\n" % (e,))
@@ -75,14 +76,14 @@
     ]
     try:
         if verbose:
-            print "\nDumping data to %s" % (dumpFile,)
-            print "Executing: %s" % (" ".join(cmdArgs))
+            print("\nDumping data to %s" % (dumpFile,))
+            print("Executing: %s" % (" ".join(cmdArgs)))
         out = subprocess.check_output(cmdArgs, stderr=subprocess.STDOUT)
         if verbose:
-            print out
+            print(out)
     except subprocess.CalledProcessError, e:
         if verbose:
-            print e.output
+            print(e.output)
         raise BackupError(
             "%s failed:\n%s (exit code = %d)" %
             (PGDUMP, e.output, e.returncode)
@@ -102,14 +103,14 @@
     ]
     try:
         if verbose:
-            print "\nLoading data from %s" % (dumpFile,)
-            print "Executing: %s" % (" ".join(cmdArgs))
+            print("\nLoading data from %s" % (dumpFile,))
+            print("Executing: %s" % (" ".join(cmdArgs)))
         out = subprocess.check_output(cmdArgs, stderr=subprocess.STDOUT)
         if verbose:
-            print out
+            print(out)
     except subprocess.CalledProcessError, e:
         if verbose:
-            print e.output
+            print(e.output)
         raise BackupError(
             "%s failed:\n%s (exit code = %d)" %
             (PSQL, e.output, e.returncode)
@@ -168,24 +169,24 @@
             dumpData(dumpPath, verbose=verbose)
 
             if verbose:
-                print "Creating %s" % (filename,)
+                print("Creating %s" % (filename,))
             tar = tarfile.open(filename, "w:gz")
 
             if verbose:
-                print "Adding %s" % (serverRoot,)
+                print("Adding %s" % (serverRoot,))
             tar.add(serverRoot)
 
             if not dataRoot.startswith(serverRoot):
                 # DataRoot is not contained within ServerRoot (i.e, it's on
                 # another volume)
                 if verbose:
-                    print "Adding %s" % (dataRoot,)
+                    print("Adding %s" % (dataRoot,))
                 tar.add(dataRoot)
 
             tar.close()
 
             if verbose:
-                print "Done"
+                print("Done")
         except BackupError, e:
             error("Failed to dump database; error: %s" % (e,))
 
@@ -195,13 +196,13 @@
             tar = tarfile.open(filename, "r:gz")
 
             if verbose:
-                print "Extracting from backup file: %s" % (filename,)
+                print("Extracting from backup file: %s" % (filename,))
             tar.extractall(path="/")
 
             loadData(dumpPath, verbose=verbose)
 
             if verbose:
-                print "Cleaning up database dump file: %s" % (dumpPath,)
+                print("Cleaning up database dump file: %s" % (dumpPath,))
             os.remove(dumpPath)
 
         except BackupError, e:

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/bootstrapdatabase.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/bootstrapdatabase.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/bootstrapdatabase.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from getopt import getopt, GetoptError
 import os
@@ -33,14 +34,14 @@
 
 def usage(e=None):
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] username" % (name,)
-    print ""
-    print " Bootstrap calendar server postgres database and schema"
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -v --verbose: print additional information"
-    print ""
+    print("usage: %s [options] username" % (name,))
+    print("")
+    print(" Bootstrap calendar server postgres database and schema")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -v --verbose: print additional information")
+    print("")
 
     if e:
         sys.stderr.write("%s\n" % (e,))
@@ -66,15 +67,15 @@
     ]
     try:
         if verbose:
-            print "\nAttempting to create user..."
-            print "Executing: %s" % (" ".join(cmdArgs))
+            print("\nAttempting to create user...")
+            print("Executing: %s" % (" ".join(cmdArgs)))
         out = subprocess.check_output(cmdArgs, stderr=subprocess.STDOUT)
         if verbose:
-            print out
+            print(out)
         return True
     except subprocess.CalledProcessError, e:
         if verbose:
-            print e.output
+            print(e.output)
         if "already exists" in e.output:
             return False
         raise BootstrapError(
@@ -98,15 +99,15 @@
     ]
     try:
         if verbose:
-            print "\nAttempting to create database..."
-            print "Executing: %s" % (" ".join(cmdArgs))
+            print("\nAttempting to create database...")
+            print("Executing: %s" % (" ".join(cmdArgs)))
         out = subprocess.check_output(cmdArgs, stderr=subprocess.STDOUT)
         if verbose:
-            print out
+            print(out)
         return True
     except subprocess.CalledProcessError, e:
         if verbose:
-            print e.output
+            print(e.output)
         if "already exists" in e.output:
             return False
         raise BootstrapError(
@@ -131,14 +132,14 @@
     ]
     try:
         if verbose:
-            print "\nAttempting to read schema version..."
-            print "Executing: %s" % (" ".join(cmdArgs))
+            print("\nAttempting to read schema version...")
+            print("Executing: %s" % (" ".join(cmdArgs)))
         out = subprocess.check_output(cmdArgs, stderr=subprocess.STDOUT)
         if verbose:
-            print out
+            print(out)
     except subprocess.CalledProcessError, e:
         if verbose:
-            print e.output
+            print(e.output)
         raise BootstrapError(
             "%s failed:\n%s (exit code = %d)" %
             (PSQL, e.output, e.returncode)
@@ -167,16 +168,16 @@
     ]
     try:
         if verbose:
-            print "Executing: %s" % (" ".join(cmdArgs))
+            print("Executing: %s" % (" ".join(cmdArgs)))
         out = subprocess.check_output(cmdArgs, stderr=subprocess.STDOUT)
         if verbose:
-            print out
+            print(out)
         if "already exists" in out:
             return False
         return True
     except subprocess.CalledProcessError, e:
         if verbose:
-            print e.output
+            print(e.output)
         raise BootstrapError(
             "%s failed:\n%s (exit code = %d)" %
             (PSQL, e.output, e.returncode)
@@ -216,9 +217,9 @@
     try:
         newlyCreated = createUser(verbose=verbose)
         if newlyCreated:
-            print "Database user '%s' created" % (USERNAME,)
+            print("Database user '%s' created" % (USERNAME,))
         else:
-            print "Database User '%s' exists" % (USERNAME,)
+            print("Database User '%s' exists" % (USERNAME,))
     except BootstrapError, e:
         error("Failed to create database user '%s': %s" % (USERNAME, e))
 
@@ -226,9 +227,9 @@
     try:
         newlyCreated = createDatabase(verbose=verbose)
         if newlyCreated:
-            print "Database '%s' created" % (DATABASENAME,)
+            print("Database '%s' created" % (DATABASENAME,))
         else:
-            print "Database '%s' exists" % (DATABASENAME,)
+            print("Database '%s' exists" % (DATABASENAME,))
     except BootstrapError, e:
         error("Failed to create database '%s': %s" % (DATABASENAME, e))
 
@@ -242,20 +243,20 @@
     try:
         data = open(SCHEMAFILE).read()
     except IOError:
-        print "Unable to open the schema file: %s" % (SCHEMAFILE,)
+        print("Unable to open the schema file: %s" % (SCHEMAFILE,))
     else:
         found = re.search("insert into CALENDARSERVER values \('VERSION', '(\d+)'\);", data)
         if found is None:
-            print "Schema is missing required schema VERSION insert statement: %s" % (SCHEMAFILE,)
+            print("Schema is missing required schema VERSION insert statement: %s" % (SCHEMAFILE,))
         else:
             required_version = int(found.group(1))
             if version == required_version:
-                print "Latest schema version (%d) is installed" % (version,)
+                print("Latest schema version (%d) is installed" % (version,))
         
             elif version == 0: # No schema installed
                 installSchema(verbose=verbose)
                 version = getSchemaVersion(verbose=verbose)
-                print "Successfully installed schema version %d" % (version,)
+                print("Successfully installed schema version %d" % (version,))
         
             else: # upgrade needed
                 error(

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/calverify.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/calverify.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/calverify.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,7 +15,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
+from twistedcaldav.directory.directory import DirectoryService
+from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
+
 """
 This tool scans the calendar store to analyze organizer/attendee event
 states to verify that the organizer's view of attendee state matches up
@@ -49,7 +53,7 @@
 from pycalendar.timezone import PyCalendarTimezone
 from twext.enterprise.dal.syntax import Select, Parameter, Count
 from twisted.application.service import Service
-from twisted.internet.defer import inlineCallbacks, returnValue, succeed
+from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python import log, usage
 from twisted.python.usage import Options
 from twistedcaldav import caldavxml
@@ -191,12 +195,12 @@
 if not hasattr(Component, "maxAlarmCounts"):
     Component.hasDuplicateAlarms = new_hasDuplicateAlarms
 
-VERSION = "8"
+VERSION = "9"
 
 def printusage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
     try:
         CalVerifyOptions().opt_help()
     except SystemExit:
@@ -223,6 +227,7 @@
 --mismatch          : verify scheduling state.
 --missing           : display orphaned calendar homes - can be used.
                       with either --ical or --mismatch.
+--double            : detect double-bookings.
 
 --nuke PATH|RID     : remove specific calendar resources - can
                       only be used by itself. PATH is the full
@@ -249,11 +254,22 @@
 --details  : log extended details on each mismatch.
 --tzid     : timezone to adjust details to.
 
+Options for --double:
+
+--uuid     : only scan specified calendar homes. Can be a partial GUID
+             to scan all GUIDs with that as a prefix or "*" for all GUIDS
+             (that are marked as resources or locations in the directory).
+--tzid     : timezone to adjust details to.
+--summary  : report only which GUIDs have double-bookings - no details.
+--days     : number of days ahead to scan [DEFAULT: 365]
+
 CHANGES
 v8: Detects ORGANIZER or ATTENDEE properties with mailto: calendar user
     addresses for users that have valid directory records. Fix is to
     replace the value with a urn:uuid: form.
 
+v9: Detects double-bookings.
+
 """ % (VERSION,)
 
 
@@ -276,9 +292,11 @@
         ['nobase64', 'n', "Do not apply CALENDARSERVER-OLD-CUA base64 transform when fixing."],
         ['mismatch', 's', "Detect organizer/attendee mismatches."],
         ['missing', 'm', "Show 'orphaned' homes."],
+        ['double', 'd', "Detect double-bookings."],
         ['fix', 'x', "Fix problems."],
         ['verbose', 'v', "Verbose logging."],
         ['details', 'V', "Detailed logging."],
+        ['summary', 'S', "Summary of double-bookings."],
         ['tzid', 't', "Timezone to adjust displayed times to."],
     ]
 
@@ -286,7 +304,8 @@
         ['config', 'f', DEFAULT_CONFIG_FILE, "Specify caldavd.plist configuration path."],
         ['uuid', 'u', "", "Only check this user."],
         ['uid', 'U', "", "Only this event UID."],
-        ['nuke', 'e', "", "Remove event given its path"]
+        ['nuke', 'e', "", "Remove event given its path."],
+        ['days', 'T', "365", "Number of days for scanning events into the future."]
     ]
 
 
@@ -321,25 +340,9 @@
 
 class CalVerifyService(Service, object):
     """
-    Service which runs, exports the appropriate records, then stops the reactor.
+    Base class for common service behaviors.
     """
 
-    metadata = {
-        "accessMode": "PUBLIC",
-        "isScheduleObject": True,
-        "scheduleTag": "abc",
-        "scheduleEtags": (),
-        "hasPrivateComment": False,
-    }
-
-    metadata_inbox = {
-        "accessMode": "PUBLIC",
-        "isScheduleObject": False,
-        "scheduleTag": "",
-        "scheduleEtags": (),
-        "hasPrivateComment": False,
-    }
-
     def __init__(self, store, options, output, reactor, config):
         super(CalVerifyService, self).__init__()
         self.store = store
@@ -350,16 +353,9 @@
         self._directory = None
 
         self.cuaCache = {}
-        self.validForCalendaringUUIDs = {}
 
         self.results = {}
         self.summary = []
-        self.fixAttendeesForOrganizerMissing = 0
-        self.fixAttendeesForOrganizerMismatch = 0
-        self.fixOrganizersForAttendeeMissing = 0
-        self.fixOrganizersForAttendeeMismatch = 0
-        self.fixFailed = 0
-        self.fixedAutoAccepts = []
         self.total = 0
         self.totalErrors = None
         self.totalExceptions = None
@@ -373,25 +369,31 @@
         self.doCalVerify()
 
 
+    def stopService(self):
+        """
+        Stop the service.  Nothing to do; everything should be finished by this
+        time.
+        """
+        # TODO: stopping this service mid-export should really stop the export
+        # loop, but this is not implemented because nothing will actually do it
+        # except hitting ^C (which also calls reactor.stop(), so that will exit
+        # anyway).
+        pass
+
+
+    def title(self):
+        return ""
+
+
     @inlineCallbacks
     def doCalVerify(self):
         """
-        Do the export, stopping the reactor when done.
+        Do the operation stopping the reactor when done.
         """
-        self.output.write("\n---- CalVerify version: %s ----\n" % (VERSION,))
+        self.output.write("\n---- CalVerify %s version: %s ----\n" % (self.title(), VERSION,))
 
         try:
-            if self.options["nuke"]:
-                yield self.doNuke()
-            else:
-                if self.options["missing"]:
-                    yield self.doOrphans()
-
-                if self.options["mismatch"] or self.options["ical"] or self.options["badcua"]:
-                    yield self.doScan(self.options["ical"] or self.options["badcua"], self.options["mismatch"], self.options["fix"])
-
-                self.printSummary()
-
+            yield self.doAction()
             self.output.close()
         except:
             log.err()
@@ -399,154 +401,35 @@
         self.reactor.stop()
 
 
-    @inlineCallbacks
-    def doNuke(self):
+    def directoryService(self):
         """
-        Remove a resource using either its path or resource id. When doing this do not
-        read the iCalendar data which may be corrupt.
+        Get an appropriate directory service for this L{CalVerifyService}'s
+        configuration, creating one first if necessary.
         """
+        if self._directory is None:
+            self._directory = getDirectory(self.config) #directoryFromConfig(self.config)
+        return self._directory
 
-        self.output.write("\n---- Removing calendar resource ----\n")
-        self.txn = self.store.newTransaction()
 
-        nuke = self.options["nuke"]
-        if nuke.startswith("/calendars/__uids__/"):
-            pathbits = nuke.split("/")
-            if len(pathbits) != 6:
-                printusage("Not a valid calendar object resource path: %s" % (nuke,))
-            homeName = pathbits[3]
-            calendarName = pathbits[4]
-            resourceName = pathbits[5]
-
-            rid = yield self.getResourceID(homeName, calendarName, resourceName)
-            if rid is None:
-                yield self.txn.commit()
-                self.txn = None
-                self.output.write("\n")
-                self.output.write("Path does not exist. Nothing nuked.\n")
-                returnValue(None)
-            rid = int(rid)
-        else:
-            try:
-                rid = int(nuke)
-            except ValueError:
-                printusage("nuke argument must be a calendar object path or an SQL resource-id")
-
-        if self.options["fix"]:
-            result = yield self.fixByRemovingEvent(rid)
-            if result:
-                self.output.write("\n")
-                self.output.write("Removed resource: %s.\n" % (rid,))
-        else:
-            self.output.write("\n")
-            self.output.write("Resource: %s.\n" % (rid,))
-        yield self.txn.commit()
-        self.txn = None
-
-
     @inlineCallbacks
-    def doOrphans(self):
-        """
-        Report on home collections for which there are no directory records, or record is for user on
-        a different pod, or a user not enabled for calendaring.
-        """
-        self.output.write("\n---- Finding calendar homes with missing or disabled directory records ----\n")
-        self.txn = self.store.newTransaction()
+    def getAllHomeUIDs(self):
+        ch = schema.CALENDAR_HOME
+        rows = (yield Select(
+            [ch.OWNER_UID, ],
+            From=ch,
+        ).on(self.txn))
+        returnValue(tuple([uid[0] for uid in rows]))
 
-        if self.options["verbose"]:
-            t = time.time()
-        uids = yield self.getAllHomeUIDs()
-        if self.options["verbose"]:
-            self.output.write("getAllHomeUIDs time: %.1fs\n" % (time.time() - t,))
-        missing = []
-        wrong_server = []
-        disabled = []
-        uids_len = len(uids)
-        uids_div = 1 if uids_len < 100 else uids_len / 100
-        self.addToSummary("Total Homes", uids_len)
 
-        for ctr, uid in enumerate(uids):
-            if self.options["verbose"] and divmod(ctr, uids_div)[1] == 0:
-                self.output.write(("\r%d of %d (%d%%)" % (
-                    ctr + 1,
-                    uids_len,
-                    ((ctr + 1) * 100 / uids_len),
-                )).ljust(80))
-                self.output.flush()
-
-            record = self.directoryService().recordWithGUID(uid)
-            if record is None:
-                contents = yield self.countHomeContents(uid)
-                missing.append((uid, contents,))
-            elif not record.thisServer():
-                contents = yield self.countHomeContents(uid)
-                wrong_server.append((uid, contents,))
-            elif not record.enabledForCalendaring:
-                contents = yield self.countHomeContents(uid)
-                disabled.append((uid, contents,))
-
-            # To avoid holding locks on all the rows scanned, commit every 100 resources
-            if divmod(ctr, 100)[1] == 0:
-                yield self.txn.commit()
-                self.txn = self.store.newTransaction()
-
-        yield self.txn.commit()
-        self.txn = None
-        if self.options["verbose"]:
-            self.output.write("\r".ljust(80) + "\n")
-
-        # Print table of results
-        table = tables.Table()
-        table.addHeader(("Owner UID", "Calendar Objects"))
-        for uid, count in sorted(missing, key=lambda x: x[0]):
-            table.addRow((
-                uid,
-                count,
-            ))
-
-        self.output.write("\n")
-        self.output.write("Homes without a matching directory record (total=%d):\n" % (len(missing),))
-        table.printTable(os=self.output)
-        self.addToSummary("Homes without a matching directory record", len(missing), uids_len)
-
-        # Print table of results
-        table = tables.Table()
-        table.addHeader(("Owner UID", "Calendar Objects"))
-        for uid, count in sorted(wrong_server, key=lambda x: x[0]):
-            record = self.directoryService().recordWithGUID(uid)
-            table.addRow((
-                "%s/%s (%s)" % (record.recordType if record else "-", record.shortNames[0] if record else "-", uid,),
-                count,
-            ))
-
-        self.output.write("\n")
-        self.output.write("Homes not hosted on this server (total=%d):\n" % (len(wrong_server),))
-        table.printTable(os=self.output)
-        self.addToSummary("Homes not hosted on this server", len(wrong_server), uids_len)
-
-        # Print table of results
-        table = tables.Table()
-        table.addHeader(("Owner UID", "Calendar Objects"))
-        for uid, count in sorted(disabled, key=lambda x: x[0]):
-            record = self.directoryService().recordWithGUID(uid)
-            table.addRow((
-                "%s/%s (%s)" % (record.recordType if record else "-", record.shortNames[0] if record else "-", uid,),
-                count,
-            ))
-
-        self.output.write("\n")
-        self.output.write("Homes without an enabled directory record (total=%d):\n" % (len(disabled),))
-        table.printTable(os=self.output)
-        self.addToSummary("Homes without an enabled directory record", len(disabled), uids_len)
-
-
     @inlineCallbacks
-    def getAllHomeUIDs(self):
+    def getMatchingHomeUIDs(self, uuid):
         ch = schema.CALENDAR_HOME
+        kwds = {"uuid": uuid}
         rows = (yield Select(
             [ch.OWNER_UID, ],
             From=ch,
-        ).on(self.txn))
+            Where=(ch.OWNER_UID.StartsWith(Parameter("uuid"))),
+        ).on(self.txn, **kwds))
         returnValue(tuple([uid[0] for uid in rows]))
 
 
@@ -568,102 +451,6 @@
 
 
     @inlineCallbacks
-    def doScan(self, ical, mismatch, fix, start=None):
-
-        self.output.write("\n---- Scanning calendar data ----\n")
-
-        self.now = PyCalendarDateTime.getNowUTC()
-        self.start = start if start is not None else PyCalendarDateTime.getToday()
-        self.start.setDateOnly(False)
-        self.end = self.start.duplicate()
-        self.end.offsetYear(1)
-        self.fix = fix
-
-        self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
-
-        self.txn = self.store.newTransaction()
-
-        if self.options["verbose"]:
-            t = time.time()
-        descriptor = None
-        if ical:
-            if self.options["uuid"]:
-                rows = yield self.getAllResourceInfoWithUUID(self.options["uuid"], inbox=True)
-                descriptor = "getAllResourceInfoWithUUID"
-            elif self.options["uid"]:
-                rows = yield self.getAllResourceInfoWithUID(self.options["uid"], inbox=True)
-                descriptor = "getAllResourceInfoWithUID"
-            else:
-                rows = yield self.getAllResourceInfo(inbox=True)
-                descriptor = "getAllResourceInfo"
-        else:
-            if self.options["uid"]:
-                rows = yield self.getAllResourceInfoWithUID(self.options["uid"])
-                descriptor = "getAllResourceInfoWithUID"
-            else:
-                rows = yield self.getAllResourceInfoTimeRange(self.start)
-                descriptor = "getAllResourceInfoTimeRange"
-
-        yield self.txn.commit()
-        self.txn = None
-
-        if self.options["verbose"]:
-            self.output.write("%s time: %.1fs\n" % (descriptor, time.time() - t,))
-
-        self.total = len(rows)
-        self.output.write("Number of events to process: %s\n" % (len(rows,)))
-        self.results["Number of events to process"] = len(rows)
-        self.addToSummary("Number of events to process", self.total)
-
-        # Split into organizer events and attendee events
-        self.organized = []
-        self.organized_byuid = {}
-        self.attended = []
-        self.attended_byuid = collections.defaultdict(list)
-        self.matched_attendee_to_organizer = collections.defaultdict(set)
-        skipped, inboxes = self.buildResourceInfo(rows)
-
-        self.output.write("Number of organizer events to process: %s\n" % (len(self.organized),))
-        self.output.write("Number of attendee events to process: %s\n" % (len(self.attended,)))
-        self.results["Number of organizer events to process"] = len(self.organized)
-        self.results["Number of attendee events to process"] = len(self.attended)
-        self.results["Number of skipped events"] = skipped
-        self.results["Number of inbox events"] = inboxes
-        self.addToSummary("Number of organizer events to process", len(self.organized), self.total)
-        self.addToSummary("Number of attendee events to process", len(self.attended), self.total)
-        self.addToSummary("Number of skipped events", skipped, self.total)
-        if ical:
-            self.addToSummary("Number of inbox events", inboxes, self.total)
-        self.addSummaryBreak()
-
-        if ical:
-            yield self.calendarDataCheck(rows)
-        elif mismatch:
-            self.totalErrors = 0
-            yield self.verifyAllAttendeesForOrganizer()
-            yield self.verifyAllOrganizersForAttendee()
-
-            # Need to add fix summary information
-            if fix:
-                self.addSummaryBreak()
-                self.results["Fixed missing attendee events"] = self.fixAttendeesForOrganizerMissing
-                self.results["Fixed mismatched attendee events"] = self.fixAttendeesForOrganizerMismatch
-                self.results["Fixed missing organizer events"] = self.fixOrganizersForAttendeeMissing
-                self.results["Fixed mismatched organizer events"] = self.fixOrganizersForAttendeeMismatch
-                self.results["Fix failures"] = self.fixFailed
-                self.results["Fixed Auto-Accepts"] = self.fixedAutoAccepts
-                self.addToSummary("Fixed missing attendee events", self.fixAttendeesForOrganizerMissing)
-                self.addToSummary("Fixed mismatched attendee events", self.fixAttendeesForOrganizerMismatch)
-                self.addToSummary("Fixed missing organizer events", self.fixOrganizersForAttendeeMissing)
-                self.addToSummary("Fixed mismatched organizer events", self.fixOrganizersForAttendeeMismatch)
-                self.addToSummary("Fix failures", self.fixFailed)
-
-                self.printAutoAccepts()
-
-        yield succeed(None)
-
-
-    @inlineCallbacks
     def getAllResourceInfo(self, inbox=False):
         co = schema.CALENDAR_OBJECT
         cb = schema.CALENDAR_BIND
@@ -737,7 +524,7 @@
                     cb.CALENDAR_RESOURCE_NAME != "inbox").And(
                     co.ORGANIZER != "")).join(
                 tr, type="left", on=(co.RESOURCE_ID == tr.CALENDAR_OBJECT_RESOURCE_ID)),
-            Where=(tr.START_DATE >= Parameter("Start")).Or(co.RECURRANCE_MAX == Parameter("Max")),
+            Where=(tr.START_DATE >= Parameter("Start")).Or(co.RECURRANCE_MAX <= Parameter("Start")),
             GroupBy=(ch.OWNER_UID, co.RESOURCE_ID, co.ICALENDAR_UID, cb.CALENDAR_RESOURCE_NAME, co.MD5, co.ORGANIZER, co.CREATED, co.MODIFIED,),
         ).on(self.txn, **kwds))
         returnValue(tuple(rows))
@@ -772,6 +559,44 @@
 
 
     @inlineCallbacks
+    def getAllResourceInfoTimeRangeWithUUID(self, start, uuid):
+        co = schema.CALENDAR_OBJECT
+        cb = schema.CALENDAR_BIND
+        ch = schema.CALENDAR_HOME
+        tr = schema.TIME_RANGE
+
+        cojoin = (cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID).And(
+                cb.BIND_MODE == _BIND_MODE_OWN).And(
+                cb.CALENDAR_RESOURCE_NAME != "inbox")
+
+        kwds = {
+            "Start" : pyCalendarTodatetime(start),
+            "Max"   : pyCalendarTodatetime(PyCalendarDateTime(1900, 1, 1, 0, 0, 0)),
+            "UUID" : uuid,
+        }
+        rows = (yield Select(
+            [ch.OWNER_UID, co.RESOURCE_ID, co.ICALENDAR_UID, cb.CALENDAR_RESOURCE_NAME, co.MD5, co.ORGANIZER, co.CREATED, co.MODIFIED],
+            From=ch.join(
+                cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID)).join(
+                co, type="inner", on=cojoin),
+            Where=(co.ICALENDAR_UID.In(Select(
+                [co.ICALENDAR_UID],
+                From=ch.join(
+                    cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID)).join(
+                    co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID).And(
+                        cb.BIND_MODE == _BIND_MODE_OWN).And(
+                        cb.CALENDAR_RESOURCE_NAME != "inbox").And(
+                        co.ORGANIZER != "")).join(
+                    tr, type="left", on=(co.RESOURCE_ID == tr.CALENDAR_OBJECT_RESOURCE_ID)),
+                Where=(ch.OWNER_UID == Parameter("UUID")).And((tr.START_DATE >= Parameter("Start")).Or(co.RECURRANCE_MAX <= Parameter("Start"))),
+                GroupBy=(ch.OWNER_UID, co.RESOURCE_ID, co.ICALENDAR_UID, cb.CALENDAR_RESOURCE_NAME, co.MD5, co.ORGANIZER, co.CREATED, co.MODIFIED,),
+            ))),
+            GroupBy=(ch.OWNER_UID, co.RESOURCE_ID, co.ICALENDAR_UID, cb.CALENDAR_RESOURCE_NAME, co.MD5, co.ORGANIZER, co.CREATED, co.MODIFIED,),
+        ).on(self.txn, **kwds))
+        returnValue(tuple(rows))
+
+
+    @inlineCallbacks
     def getAllResourceInfoForResourceID(self, resid):
         co = schema.CALENDAR_OBJECT
         cb = schema.CALENDAR_BIND
@@ -812,57 +637,410 @@
         returnValue(rows[0][0] if rows else None)
 
 
-    def buildResourceInfo(self, rows, onlyOrganizer=False, onlyAttendee=False):
-        skipped = 0
-        inboxes = 0
-        for owner, resid, uid, calname, md5, organizer, created, modified in rows:
+    @inlineCallbacks
+    def getCalendar(self, resid, doFix=False):
+        co = schema.CALENDAR_OBJECT
+        kwds = {"ResourceID" : resid}
+        rows = (yield Select(
+            [co.ICALENDAR_TEXT],
+            From=co,
+            Where=(
+                co.RESOURCE_ID == Parameter("ResourceID")
+            ),
+        ).on(self.txn, **kwds))
+        try:
+            caldata = PyCalendar.parseText(rows[0][0]) if rows else None
+        except PyCalendarError:
+            caltxt = rows[0][0] if rows else None
+            if caltxt:
+                caltxt = caltxt.replace("\r\n ", "")
+                if caltxt.find("CALENDARSERVER-OLD-CUA=\"//") != -1:
+                    if doFix:
+                        caltxt = (yield self.fixBadOldCua(resid, caltxt))
+                        try:
+                            caldata = PyCalendar.parseText(caltxt) if rows else None
+                        except PyCalendarError:
+                            self.parseError = "No fix bad CALENDARSERVER-OLD-CUA"
+                            returnValue(None)
+                    else:
+                        self.parseError = "Bad CALENDARSERVER-OLD-CUA"
+                        returnValue(None)
 
-            # Skip owners not enabled for calendaring
-            if not self.testForCalendaringUUID(owner):
-                skipped += 1
-                continue
+            self.parseError = "Failed to parse"
+            returnValue(None)
 
-            # Skip inboxes
-            if calname == "inbox":
-                inboxes += 1
-                continue
+        self.parseError = None
+        returnValue(caldata)
 
-            # If targeting a specific organizer, skip events belonging to others
-            if self.options["uuid"]:
-                if not organizer.startswith("urn:uuid:") or self.options["uuid"] != organizer[9:]:
-                    continue
 
-            # Cache organizer/attendee states
-            if organizer.startswith("urn:uuid:") and owner == organizer[9:]:
-                if not onlyAttendee:
-                    self.organized.append((owner, resid, uid, md5, organizer, created, modified,))
-                    self.organized_byuid[uid] = (owner, resid, uid, md5, organizer, created, modified,)
-            else:
-                if not onlyOrganizer:
-                    self.attended.append((owner, resid, uid, md5, organizer, created, modified,))
-                    self.attended_byuid[uid].append((owner, resid, uid, md5, organizer, created, modified,))
+    @inlineCallbacks
+    def getCalendarForOwnerByUID(self, owner, uid):
+        co = schema.CALENDAR_OBJECT
+        cb = schema.CALENDAR_BIND
+        ch = schema.CALENDAR_HOME
 
-        return skipped, inboxes
+        kwds = {"OWNER": owner, "UID": uid}
+        rows = (yield Select(
+            [co.ICALENDAR_TEXT, co.RESOURCE_ID, co.CREATED, co.MODIFIED, ],
+            From=ch.join(
+                cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID)).join(
+                co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID).And(
+                    cb.BIND_MODE == _BIND_MODE_OWN).And(
+                    cb.CALENDAR_RESOURCE_NAME != "inbox")),
+            Where=(ch.OWNER_UID == Parameter("OWNER")).And(co.ICALENDAR_UID == Parameter("UID")),
+        ).on(self.txn, **kwds))
 
+        try:
+            caldata = PyCalendar.parseText(rows[0][0]) if rows else None
+        except PyCalendarError:
+            returnValue((None, None, None, None,))
 
-    def testForCalendaringUUID(self, uuid):
+        returnValue((caldata, rows[0][1], rows[0][2], rows[0][3],) if rows else (None, None, None, None,))
+
+
+    @inlineCallbacks
+    def fixBadOldCua(self, resid, caltxt):
         """
-        Determine if the specified directory UUID is valid for calendaring. Keep a cache of
-        valid and invalid so we can do this quickly.
+        Fix bad CALENDARSERVER-OLD-CUA lines and write fixed data to store. Assumes iCalendar data lines unfolded.
+        """
 
-        @param uuid: the directory UUID to test
-        @type uuid: C{str}
+        # Get store objects
+        homeID, calendarID = yield self.getAllResourceInfoForResourceID(resid)
+        home = yield self.txn.calendarHomeWithResourceID(homeID)
+        calendar = yield home.childWithID(calendarID)
+        calendarObj = yield calendar.objectResourceWithID(resid)
 
-        @return: C{True} if valid, C{False} if not
+        # Do raw data fix one line at a time
+        caltxt = self.fixBadOldCuaLines(caltxt)
+
+        # Re-parse
+        try:
+            component = Component.fromString(caltxt)
+        except InvalidICalendarDataError:
+            returnValue(None)
+
+        # Write out fix, commit and get a new transaction
+        # Use _migrating to ignore possible overridden instance errors - we are either correcting or ignoring those
+        self.txn._migrating = True
+        component = yield calendarObj.setComponent(component)
+        yield self.txn.commit()
+        self.txn = self.store.newTransaction()
+
+        returnValue(caltxt)
+
+
+    def fixBadOldCuaLines(self, caltxt):
         """
+        Fix bad CALENDARSERVER-OLD-CUA lines. Assumes iCalendar data lines unfolded.
+        """
 
-        if uuid not in self.validForCalendaringUUIDs:
-            record = self.directoryService().recordWithGUID(uuid)
-            self.validForCalendaringUUIDs[uuid] = record is not None and record.enabledForCalendaring and record.thisServer()
-        return self.validForCalendaringUUIDs[uuid]
+        # Do raw data fix one line at a time
+        lines = caltxt.splitlines()
+        for ctr, line in enumerate(lines):
+            startpos = line.find(";CALENDARSERVER-OLD-CUA=\"//")
+            if startpos != -1:
+                endpos = line.find("urn:uuid:")
+                if endpos != -1:
+                    endpos += len("urn:uuid:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\"")
+                    badparam = line[startpos + len(";CALENDARSERVER-OLD-CUA=\""):endpos]
+                    endbadparam = badparam.find(";")
+                    if endbadparam != -1:
+                        badparam = badparam[:endbadparam].replace("\\", "")
+                        if badparam.find("8443") != -1:
+                            badparam = "https:" + badparam
+                        else:
+                            badparam = "http:" + badparam
+                        if self.options["nobase64"]:
+                            badparam = "\"" + badparam + "\""
+                        else:
+                            badparam = "base64-%s" % (base64.b64encode(badparam),)
+                        badparam = ";CALENDARSERVER-OLD-CUA=" + badparam
+                        lines[ctr] = line[:startpos] + badparam + line[endpos:]
+        caltxt = "\r\n".join(lines) + "\r\n"
+        return caltxt
 
 
     @inlineCallbacks
+    def removeEvent(self, resid):
+        """
+        Remove the calendar resource specified by resid - this is a force remove - no implicit
+        scheduling is required so we use store apis directly.
+        """
+
+        try:
+            homeID, calendarID = yield self.getAllResourceInfoForResourceID(resid)
+            home = yield self.txn.calendarHomeWithResourceID(homeID)
+            calendar = yield home.childWithID(calendarID)
+            calendarObj = yield calendar.objectResourceWithID(resid)
+            objname = calendarObj.name()
+            yield calendar.removeObjectResource(calendarObj)
+            yield self.txn.commit()
+            self.txn = self.store.newTransaction()
+
+            self.results.setdefault("Fix remove", set()).add((home.name(), calendar.name(), objname,))
+
+            returnValue(True)
+        except Exception, e:
+            print("Failed to remove resource whilst fixing: %d\n%s" % (resid, e,))
+            returnValue(False)
+
+
+    def logResult(self, key, value, total=None):
+        self.output.write("%s: %s\n" % (key, value,))
+        self.results[key] = value
+        self.addToSummary(key, value, total)
+
+
+    def addToSummary(self, title, count, total=None):
+        if total is not None:
+            percent = safePercent(count, total),
+        else:
+            percent = ""
+        self.summary.append((title, count, percent))
+
+
+    def addSummaryBreak(self):
+        self.summary.append(None)
+
+
+    def printSummary(self):
+        # Print summary of results
+        table = tables.Table()
+        table.addHeader(("Item", "Count", "%"))
+        table.setDefaultColumnFormats(
+            (
+                tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.LEFT_JUSTIFY),
+                tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%.1f%%", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+            )
+        )
+        for item in self.summary:
+            table.addRow(item)
+
+        if self.totalErrors is not None:
+            table.addRow(None)
+            table.addRow(("Total Errors", self.totalErrors, safePercent(self.totalErrors, self.total),))
+
+        self.output.write("\n")
+        self.output.write("Overall Summary:\n")
+        table.printTable(os=self.output)
+
+
+
+class NukeService(CalVerifyService):
+    """
+    Service which removes specific events.
+    """
+
+    def title(self):
+        return "Nuke Service"
+
+
+    @inlineCallbacks
+    def doAction(self):
+        """
+        Remove a resource using either its path or resource id. When doing this do not
+        read the iCalendar data which may be corrupt.
+        """
+
+        self.output.write("\n---- Removing calendar resource ----\n")
+        self.txn = self.store.newTransaction()
+
+        nuke = self.options["nuke"]
+        if nuke.startswith("/calendars/__uids__/"):
+            pathbits = nuke.split("/")
+            if len(pathbits) != 6:
+                printusage("Not a valid calendar object resource path: %s" % (nuke,))
+            homeName = pathbits[3]
+            calendarName = pathbits[4]
+            resourceName = pathbits[5]
+
+            rid = yield self.getResourceID(homeName, calendarName, resourceName)
+            if rid is None:
+                yield self.txn.commit()
+                self.txn = None
+                self.output.write("\n")
+                self.output.write("Path does not exist. Nothing nuked.\n")
+                returnValue(None)
+            rid = int(rid)
+        else:
+            try:
+                rid = int(nuke)
+            except ValueError:
+                printusage("nuke argument must be a calendar object path or an SQL resource-id")
+
+        if self.options["fix"]:
+            result = yield self.removeEvent(rid)
+            if result:
+                self.output.write("\n")
+                self.output.write("Removed resource: %s.\n" % (rid,))
+        else:
+            self.output.write("\n")
+            self.output.write("Resource: %s.\n" % (rid,))
+        yield self.txn.commit()
+        self.txn = None
+
+
+
+class OrphansService(CalVerifyService):
+    """
+    Service which detects orphaned calendar homes.
+    """
+
+    def title(self):
+        return "Orphans Service"
+
+
+    @inlineCallbacks
+    def doAction(self):
+        """
+        Report on home collections for which there are no directory records, or record is for user on
+        a different pod, or a user not enabled for calendaring.
+        """
+        self.output.write("\n---- Finding calendar homes with missing or disabled directory records ----\n")
+        self.txn = self.store.newTransaction()
+
+        if self.options["verbose"]:
+            t = time.time()
+        uids = yield self.getAllHomeUIDs()
+        if self.options["verbose"]:
+            self.output.write("getAllHomeUIDs time: %.1fs\n" % (time.time() - t,))
+        missing = []
+        wrong_server = []
+        disabled = []
+        uids_len = len(uids)
+        uids_div = 1 if uids_len < 100 else uids_len / 100
+        self.addToSummary("Total Homes", uids_len)
+
+        for ctr, uid in enumerate(uids):
+            if self.options["verbose"] and divmod(ctr, uids_div)[1] == 0:
+                self.output.write(("\r%d of %d (%d%%)" % (
+                    ctr + 1,
+                    uids_len,
+                    ((ctr + 1) * 100 / uids_len),
+                )).ljust(80))
+                self.output.flush()
+
+            record = self.directoryService().recordWithGUID(uid)
+            if record is None:
+                contents = yield self.countHomeContents(uid)
+                missing.append((uid, contents,))
+            elif not record.thisServer():
+                contents = yield self.countHomeContents(uid)
+                wrong_server.append((uid, contents,))
+            elif not record.enabledForCalendaring:
+                contents = yield self.countHomeContents(uid)
+                disabled.append((uid, contents,))
+
+            # To avoid holding locks on all the rows scanned, commit every 100 resources
+            if divmod(ctr, 100)[1] == 0:
+                yield self.txn.commit()
+                self.txn = self.store.newTransaction()
+
+        yield self.txn.commit()
+        self.txn = None
+        if self.options["verbose"]:
+            self.output.write("\r".ljust(80) + "\n")
+
+        # Print table of results
+        table = tables.Table()
+        table.addHeader(("Owner UID", "Calendar Objects"))
+        for uid, count in sorted(missing, key=lambda x: x[0]):
+            table.addRow((
+                uid,
+                count,
+            ))
+
+        self.output.write("\n")
+        self.logResult("Homes without a matching directory record", len(missing), uids_len)
+        table.printTable(os=self.output)
+
+        # Print table of results
+        table = tables.Table()
+        table.addHeader(("Owner UID", "Calendar Objects"))
+        for uid, count in sorted(wrong_server, key=lambda x: x[0]):
+            record = self.directoryService().recordWithGUID(uid)
+            table.addRow((
+                "%s/%s (%s)" % (record.recordType if record else "-", record.shortNames[0] if record else "-", uid,),
+                count,
+            ))
+
+        self.output.write("\n")
+        self.logResult("Homes not hosted on this server", len(wrong_server), uids_len)
+        table.printTable(os=self.output)
+
+        # Print table of results
+        table = tables.Table()
+        table.addHeader(("Owner UID", "Calendar Objects"))
+        for uid, count in sorted(disabled, key=lambda x: x[0]):
+            record = self.directoryService().recordWithGUID(uid)
+            table.addRow((
+                "%s/%s (%s)" % (record.recordType if record else "-", record.shortNames[0] if record else "-", uid,),
+                count,
+            ))
+
+        self.output.write("\n")
+        self.logResult("Homes without an enabled directory record", len(disabled), uids_len)
+        table.printTable(os=self.output)
+
+        self.printSummary()
+
+
+
+class BadDataService(CalVerifyService):
+    """
+    Service which scans for bad calendar data.
+    """
+
+    def title(self):
+        return "Bad Data Service"
+
+
+    @inlineCallbacks
+    def doAction(self):
+
+        self.output.write("\n---- Scanning calendar data ----\n")
+
+        self.now = PyCalendarDateTime.getNowUTC()
+        self.start = PyCalendarDateTime.getToday()
+        self.start.setDateOnly(False)
+        self.end = self.start.duplicate()
+        self.end.offsetYear(1)
+        self.fix = self.options["fix"]
+
+        self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
+
+        self.txn = self.store.newTransaction()
+
+        if self.options["verbose"]:
+            t = time.time()
+        descriptor = None
+        if self.options["uuid"]:
+            rows = yield self.getAllResourceInfoWithUUID(self.options["uuid"], inbox=True)
+            descriptor = "getAllResourceInfoWithUUID"
+        elif self.options["uid"]:
+            rows = yield self.getAllResourceInfoWithUID(self.options["uid"], inbox=True)
+            descriptor = "getAllResourceInfoWithUID"
+        else:
+            rows = yield self.getAllResourceInfo(inbox=True)
+            descriptor = "getAllResourceInfo"
+
+        yield self.txn.commit()
+        self.txn = None
+
+        if self.options["verbose"]:
+            self.output.write("%s time: %.1fs\n" % (descriptor, time.time() - t,))
+
+        self.total = len(rows)
+        self.logResult("Number of events to process", self.total)
+        self.addSummaryBreak()
+
+        yield self.calendarDataCheck(rows)
+
+        self.printSummary()
+
+
+    @inlineCallbacks
     def calendarDataCheck(self, rows):
         """
         Check each calendar resource for valid iCalendar data.
@@ -886,7 +1064,7 @@
                 result = False
                 message = "Exception for validCalendarData"
                 if self.options["verbose"]:
-                    print e
+                    print(e)
             if not result:
                 results_bad.append((owner, uid, resid, message))
                 badlen += 1
@@ -934,12 +1112,10 @@
             ))
 
         self.output.write("\n")
-        self.output.write("Bad iCalendar data (total=%d):\n" % (len(results_bad),))
+        self.logResult("Bad iCalendar data", len(results_bad), total)
+        self.results["Bad iCalendar data"] = results_bad
         table.printTable(os=self.output)
 
-        self.results["Bad iCalendar data"] = results_bad
-        self.addToSummary("Bad iCalendar data", len(results_bad), total)
-
         if self.options["verbose"]:
             diff_time = time.time() - t
             self.output.write("Time: %.2f s  Average: %.1f ms/resource\n" % (
@@ -1122,8 +1298,8 @@
                 self.txn._migrating = True
                 component = yield calendarObj.setComponent(component)
             except Exception, e:
-                print e, component
-                print traceback.print_exc()
+                print(e, component)
+                print(traceback.print_exc())
                 result = False
                 message = "Exception fix: "
             yield self.txn.commit()
@@ -1132,66 +1308,178 @@
         returnValue((result, message,))
 
 
+
+class SchedulingMismatchService(CalVerifyService):
+    """
+    Service which detects mismatched scheduled events.
+    """
+
+    metadata = {
+        "accessMode": "PUBLIC",
+        "isScheduleObject": True,
+        "scheduleTag": "abc",
+        "scheduleEtags": (),
+        "hasPrivateComment": False,
+    }
+
+    metadata_inbox = {
+        "accessMode": "PUBLIC",
+        "isScheduleObject": False,
+        "scheduleTag": "",
+        "scheduleEtags": (),
+        "hasPrivateComment": False,
+    }
+
+    def __init__(self, store, options, output, reactor, config):
+        super(SchedulingMismatchService, self).__init__(store, options, output, reactor, config)
+
+        self.validForCalendaringUUIDs = {}
+
+        self.fixAttendeesForOrganizerMissing = 0
+        self.fixAttendeesForOrganizerMismatch = 0
+        self.fixOrganizersForAttendeeMissing = 0
+        self.fixOrganizersForAttendeeMismatch = 0
+        self.fixFailed = 0
+        self.fixedAutoAccepts = []
+
+
+    def title(self):
+        return "Scheduling Mismatch Service"
+
+
     @inlineCallbacks
-    def fixBadOldCua(self, resid, caltxt):
+    def doAction(self):
+
+        self.output.write("\n---- Scanning calendar data ----\n")
+
+        self.now = PyCalendarDateTime.getNowUTC()
+        self.start = self.options["start"] if "start" in self.options else PyCalendarDateTime.getToday()
+        self.start.setDateOnly(False)
+        self.end = self.start.duplicate()
+        self.end.offsetYear(1)
+        self.fix = self.options["fix"]
+
+        self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
+
+        self.txn = self.store.newTransaction()
+
+        if self.options["verbose"]:
+            t = time.time()
+        descriptor = None
+        if self.options["uid"]:
+            rows = yield self.getAllResourceInfoWithUID(self.options["uid"])
+            descriptor = "getAllResourceInfoWithUID"
+        elif self.options["uuid"]:
+            rows = yield self.getAllResourceInfoTimeRangeWithUUID(self.start, self.options["uuid"])
+            descriptor = "getAllResourceInfoTimeRangeWithUUID"
+            self.options["uuid"] = None
+        else:
+            rows = yield self.getAllResourceInfoTimeRange(self.start)
+            descriptor = "getAllResourceInfoTimeRange"
+
+        yield self.txn.commit()
+        self.txn = None
+
+        if self.options["verbose"]:
+            self.output.write("%s time: %.1fs\n" % (descriptor, time.time() - t,))
+
+        self.total = len(rows)
+        self.logResult("Number of events to process", self.total)
+
+        # Split into organizer events and attendee events
+        self.organized = []
+        self.organized_byuid = {}
+        self.attended = []
+        self.attended_byuid = collections.defaultdict(list)
+        self.matched_attendee_to_organizer = collections.defaultdict(set)
+        skipped, inboxes = self.buildResourceInfo(rows)
+
+        self.logResult("Number of organizer events to process", len(self.organized), self.total)
+        self.logResult("Number of attendee events to process", len(self.attended), self.total)
+        self.logResult("Number of skipped events", skipped, self.total)
+        self.logResult("Number of inbox events", inboxes)
+        self.addSummaryBreak()
+
+        self.totalErrors = 0
+        yield self.verifyAllAttendeesForOrganizer()
+        yield self.verifyAllOrganizersForAttendee()
+
+        # Need to add fix summary information
+        if self.fix:
+            self.addSummaryBreak()
+            self.logResult("Fixed missing attendee events", self.fixAttendeesForOrganizerMissing)
+            self.logResult("Fixed mismatched attendee events", self.fixAttendeesForOrganizerMismatch)
+            self.logResult("Fixed missing organizer events", self.fixOrganizersForAttendeeMissing)
+            self.logResult("Fixed mismatched organizer events", self.fixOrganizersForAttendeeMismatch)
+            self.logResult("Fix failures", self.fixFailed)
+            self.logResult("Fixed Auto-Accepts", len(self.fixedAutoAccepts))
+            self.results["Auto-Accepts"] = self.fixedAutoAccepts
+
+            self.printAutoAccepts()
+
+        self.printSummary()
+
+
+    def buildResourceInfo(self, rows, onlyOrganizer=False, onlyAttendee=False):
         """
-        Fix bad CALENDARSERVER-OLD-CUA lines and write fixed data to store. Assumes iCalendar data lines unfolded.
+        For each resource, determine whether it is an organizer or attendee event, and also
+        cache the attendee partstats.
+
+        @param rows: set of DB query rows
+        @type rows: C{list}
+        @param onlyOrganizer: whether organizer information only is required
+        @type onlyOrganizer: C{bool}
+        @param onlyAttendee: whether attendee information only is required
+        @type onlyAttendee: C{bool}
         """
 
-        # Get store objects
-        homeID, calendarID = yield self.getAllResourceInfoForResourceID(resid)
-        home = yield self.txn.calendarHomeWithResourceID(homeID)
-        calendar = yield home.childWithID(calendarID)
-        calendarObj = yield calendar.objectResourceWithID(resid)
+        skipped = 0
+        inboxes = 0
+        for owner, resid, uid, calname, md5, organizer, created, modified in rows:
 
-        # Do raw data fix one line at a time
-        caltxt = self.fixBadOldCuaLines(caltxt)
+            # Skip owners not enabled for calendaring
+            if not self.testForCalendaringUUID(owner):
+                skipped += 1
+                continue
 
-        # Re-parse
-        try:
-            component = Component.fromString(caltxt)
-        except InvalidICalendarDataError:
-            returnValue(None)
+            # Skip inboxes
+            if calname == "inbox":
+                inboxes += 1
+                continue
 
-        # Write out fix, commit and get a new transaction
-        # Use _migrating to ignore possible overridden instance errors - we are either correcting or ignoring those
-        self.txn._migrating = True
-        component = yield calendarObj.setComponent(component)
-        yield self.txn.commit()
-        self.txn = self.store.newTransaction()
+            # If targeting a specific organizer, skip events belonging to others
+            if self.options["uuid"]:
+                if not organizer.startswith("urn:uuid:") or self.options["uuid"] != organizer[9:]:
+                    continue
 
-        returnValue(caltxt)
+            # Cache organizer/attendee states
+            if organizer.startswith("urn:uuid:") and owner == organizer[9:]:
+                if not onlyAttendee:
+                    self.organized.append((owner, resid, uid, md5, organizer, created, modified,))
+                    self.organized_byuid[uid] = (owner, resid, uid, md5, organizer, created, modified,)
+            else:
+                if not onlyOrganizer:
+                    self.attended.append((owner, resid, uid, md5, organizer, created, modified,))
+                    self.attended_byuid[uid].append((owner, resid, uid, md5, organizer, created, modified,))
 
+        return skipped, inboxes
 
-    def fixBadOldCuaLines(self, caltxt):
+
+    def testForCalendaringUUID(self, uuid):
         """
-        Fix bad CALENDARSERVER-OLD-CUA lines. Assumes iCalendar data lines unfolded.
+        Determine if the specified directory UUID is valid for calendaring. Keep a cache of
+        valid and invalid so we can do this quickly.
+
+        @param uuid: the directory UUID to test
+        @type uuid: C{str}
+
+        @return: C{True} if valid, C{False} if not
         """
 
-        # Do raw data fix one line at a time
-        lines = caltxt.splitlines()
-        for ctr, line in enumerate(lines):
-            startpos = line.find(";CALENDARSERVER-OLD-CUA=\"//")
-            if startpos != -1:
-                endpos = line.find("urn:uuid:")
-                if endpos != -1:
-                    endpos += len("urn:uuid:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\"")
-                    badparam = line[startpos + len(";CALENDARSERVER-OLD-CUA=\""):endpos]
-                    endbadparam = badparam.find(";")
-                    if endbadparam != -1:
-                        badparam = badparam[:endbadparam].replace("\\", "")
-                        if badparam.find("8443") != -1:
-                            badparam = "https:" + badparam
-                        else:
-                            badparam = "http:" + badparam
-                        if self.options["nobase64"]:
-                            badparam = "\"" + badparam + "\""
-                        else:
-                            badparam = "base64-%s" % (base64.b64encode(badparam),)
-                        badparam = ";CALENDARSERVER-OLD-CUA=" + badparam
-                        lines[ctr] = line[:startpos] + badparam + line[endpos:]
-        caltxt = "\r\n".join(lines) + "\r\n"
-        return caltxt
+        if uuid not in self.validForCalendaringUUIDs:
+            record = self.directoryService().recordWithGUID(uuid)
+            self.validForCalendaringUUIDs[uuid] = record is not None and record.enabledForCalendaring and record.thisServer()
+        return self.validForCalendaringUUIDs[uuid]
 
 
     @inlineCallbacks
@@ -1214,7 +1502,6 @@
         # Test organized events
         t = time.time()
         for ctr, organizerEvent in enumerate(self.organized):
-
             if self.options["verbose"] and divmod(ctr, organizer_div)[1] == 0:
                 self.output.write(("\r%d of %d (%d%%) Missing: %d  Mismatched: %s" % (
                     ctr + 1,
@@ -1277,7 +1564,7 @@
                         eachAttendeesOwnStatus[organizerAttendee] = self.buildAttendeeStates(calendar, self.start, self.end, attendee_only=organizerAttendee)
                         attendeeResIDs[(organizerAttendee, uid)] = attresid
                         attendeeCreatedModified[organizerAttendee] = (att_created, att_modified,)
-                        #print "Reloaded missing attendee data"
+                        #print("Reloaded missing attendee data")
 
                 # If an entry for the attendee exists, then check whether attendee status matches
                 if organizerAttendee in eachAttendeesOwnStatus:
@@ -1348,9 +1635,8 @@
             ))
 
         self.output.write("\n")
-        self.output.write("Events missing from Attendee's calendars (total=%d):\n" % (len(results_missing),))
+        self.logResult("Events missing from Attendee's calendars", len(results_missing), self.total)
         table.printTable(os=self.output)
-        self.addToSummary("Events missing from Attendee's calendars", len(results_missing), self.total)
         self.totalErrors += len(results_missing)
 
         # Print table of results
@@ -1374,9 +1660,8 @@
             ))
 
         self.output.write("\n")
-        self.output.write("Events mismatched between Organizer's and Attendee's calendars (total=%d):\n" % (len(results_mismatch),))
+        self.logResult("Events mismatched between Organizer's and Attendee's calendars", len(results_mismatch), self.total)
         table.printTable(os=self.output)
-        self.addToSummary("Events mismatched between Organizer's and Attendee's calendars", len(results_mismatch), self.total)
         self.totalErrors += len(results_mismatch)
 
 
@@ -1438,7 +1723,7 @@
                 self.buildResourceInfo(rows, onlyOrganizer=True)
 
                 #if uid in self.organized_byuid:
-                #    print "Reloaded missing organizer data: %s" % (uid,)
+                #    print("Reloaded missing organizer data: %s" % (uid,))
 
             if uid not in self.organized_byuid:
 
@@ -1452,7 +1737,7 @@
                 # If there is a miss we fix by removing the attendee data
                 if self.fix:
                     # This is where we attempt a fix
-                    fix_result = (yield self.fixByRemovingEvent(resid))
+                    fix_result = (yield self.removeEvent(resid))
                     if fix_result:
                         self.fixOrganizersForAttendeeMissing += 1
                     else:
@@ -1525,9 +1810,8 @@
             ))
 
         self.output.write("\n")
-        self.output.write("Attendee events mismatched in Organizer's calendar (total=%d):\n" % (len(mismatched),))
+        self.logResult("Attendee events mismatched in Organizer's calendar", len(mismatched), self.total)
         table.printTable(os=self.output)
-        self.addToSummary("Attendee events mismatched in Organizer's calendar", len(mismatched), self.total)
         self.totalErrors += len(mismatched)
 
 
@@ -1556,7 +1840,7 @@
             # Handle the case where the attendee is not actually in the organizer event at all by
             # removing the attendee event instead of re-inviting
             if itipmsg.resourceUID() is None:
-                yield self.fixByRemovingEvent(attresid)
+                yield self.removeEvent(attresid)
                 returnValue(True)
 
             # Convert iTip message into actual calendar data - just remove METHOD
@@ -1624,7 +1908,7 @@
             returnValue(True)
 
         except Exception, e:
-            print "Failed to fix resource: %d for attendee: %s\n%s" % (orgresid, attendee, e,)
+            print("Failed to fix resource: %d for attendee: %s\n%s" % (orgresid, attendee, e,))
             returnValue(False)
 
 
@@ -1647,66 +1931,6 @@
                 returnValue(None)
 
 
-    @inlineCallbacks
-    def fixByRemovingEvent(self, resid):
-        """
-        Remove the calendar resource specified by resid - this is a force remove - no implicit
-        scheduling is required so we use store apis directly.
-        """
-
-        try:
-            homeID, calendarID = yield self.getAllResourceInfoForResourceID(resid)
-            home = yield self.txn.calendarHomeWithResourceID(homeID)
-            calendar = yield home.childWithID(calendarID)
-            calendarObj = yield calendar.objectResourceWithID(resid)
-            objname = calendarObj.name()
-            yield calendar.removeObjectResource(calendarObj)
-            yield self.txn.commit()
-            self.txn = self.store.newTransaction()
-
-            self.results.setdefault("Fix remove", set()).add((home.name(), calendar.name(), objname,))
-
-            returnValue(True)
-        except Exception, e:
-            print "Failed to remove resource whilst fixing: %d\n%s" % (resid, e,)
-            returnValue(False)
-
-
-    def addToSummary(self, title, count, total=None):
-        if total is not None:
-            percent = safePercent(count, total),
-        else:
-            percent = ""
-        self.summary.append((title, count, percent))
-
-
-    def addSummaryBreak(self):
-        self.summary.append(None)
-
-
-    def printSummary(self):
-        # Print summary of results
-        table = tables.Table()
-        table.addHeader(("Item", "Count", "%"))
-        table.setDefaultColumnFormats(
-            (
-                tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.LEFT_JUSTIFY),
-                tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-                tables.Table.ColumnFormat("%.1f%%", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            )
-        )
-        for item in self.summary:
-            table.addRow(item)
-
-        if self.totalErrors is not None:
-            table.addRow(None)
-            table.addRow(("Total Errors", self.totalErrors, safePercent(self.totalErrors, self.total),))
-
-        self.output.write("\n")
-        self.output.write("Overall Summary:\n")
-        table.printTable(os=self.output)
-
-
     def printAutoAccepts(self):
         # Print summary of results
         table = tables.Table()
@@ -1725,71 +1949,11 @@
         table.printTable(os=self.output)
 
 
-    @inlineCallbacks
-    def getCalendar(self, resid, doFix=False):
-        co = schema.CALENDAR_OBJECT
-        kwds = {"ResourceID" : resid}
-        rows = (yield Select(
-            [co.ICALENDAR_TEXT],
-            From=co,
-            Where=(
-                co.RESOURCE_ID == Parameter("ResourceID")
-            ),
-        ).on(self.txn, **kwds))
-        try:
-            caldata = PyCalendar.parseText(rows[0][0]) if rows else None
-        except PyCalendarError:
-            caltxt = rows[0][0] if rows else None
-            if caltxt:
-                caltxt = caltxt.replace("\r\n ", "")
-                if caltxt.find("CALENDARSERVER-OLD-CUA=\"//") != -1:
-                    if doFix:
-                        caltxt = (yield self.fixBadOldCua(resid, caltxt))
-                        try:
-                            caldata = PyCalendar.parseText(caltxt) if rows else None
-                        except PyCalendarError:
-                            self.parseError = "No fix bad CALENDARSERVER-OLD-CUA"
-                            returnValue(None)
-                    else:
-                        self.parseError = "Bad CALENDARSERVER-OLD-CUA"
-                        returnValue(None)
-
-            self.parseError = "Failed to parse"
-            returnValue(None)
-
-        self.parseError = None
-        returnValue(caldata)
-
-
-    @inlineCallbacks
-    def getCalendarForOwnerByUID(self, owner, uid):
-        co = schema.CALENDAR_OBJECT
-        cb = schema.CALENDAR_BIND
-        ch = schema.CALENDAR_HOME
-
-        kwds = {"OWNER": owner, "UID": uid}
-        rows = (yield Select(
-            [co.ICALENDAR_TEXT, co.RESOURCE_ID, co.CREATED, co.MODIFIED, ],
-            From=ch.join(
-                cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID)).join(
-                co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID).And(
-                    cb.BIND_MODE == _BIND_MODE_OWN).And(
-                    cb.CALENDAR_RESOURCE_NAME != "inbox")),
-            Where=(ch.OWNER_UID == Parameter("OWNER")).And(co.ICALENDAR_UID == Parameter("UID")),
-        ).on(self.txn, **kwds))
-
-        try:
-            caldata = PyCalendar.parseText(rows[0][0]) if rows else None
-        except PyCalendarError:
-            returnValue((None, None, None, None,))
-
-        returnValue((caldata, rows[0][1], rows[0][2], rows[0][3],) if rows else (None, None, None, None,))
-
-
     def masterComponent(self, calendar):
         """
         Return the master iCal component in this calendar.
-        @return: the L{Component} for the master component,
+
+        @return: the L{PyCalendarComponent} for the master component,
             or C{None} if there isn't one.
         """
         for component in calendar.getComponents(definitions.cICalComponent_VEVENT):
@@ -1882,32 +2046,319 @@
             component.replaceProperty(Property("TRANSP", "TRANSPARENT" if addTransp else "OPAQUE"))
 
 
-    def directoryService(self):
-        """
-        Get an appropriate directory service for this L{CalVerifyService}'s
-        configuration, creating one first if necessary.
-        """
-        if self._directory is None:
-            self._directory = getDirectory(self.config) #directoryFromConfig(self.config)
-        return self._directory
 
+class DoubleBookingService(CalVerifyService):
+    """
+    Service which detects double-booked events.
+    """
 
-    def stopService(self):
+    def title(self):
+        return "Double Booking Service"
+
+
+    @inlineCallbacks
+    def doAction(self):
+
+        if self.options["fix"]:
+            self.output.write("\nFixing is not supported.\n")
+            returnValue(None)
+
+        self.output.write("\n---- Scanning calendar data ----\n")
+
+        self.tzid = PyCalendarTimezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
+        self.now = PyCalendarDateTime.getNowUTC()
+        self.start = PyCalendarDateTime.getToday()
+        self.start.setDateOnly(False)
+        self.start.setTimezone(self.tzid)
+        self.end = self.start.duplicate()
+        self.end.offsetYear(1)
+        self.fix = self.options["fix"]
+
+        if self.options["verbose"] and self.options["summary"]:
+            ot = time.time()
+
+        # Check loop over uuid
+        UUIDDetails = collections.namedtuple("UUIDDetails", ("uuid", "rname", "auto", "doubled",))
+        self.uuid_details = []
+        if len(self.options["uuid"]) != 36:
+            self.txn = self.store.newTransaction()
+            if self.options["uuid"]:
+                homes = yield self.getMatchingHomeUIDs(self.options["uuid"])
+            else:
+                homes = yield self.getAllHomeUIDs()
+            yield self.txn.commit()
+            self.txn = None
+            uuids = []
+            for uuid in sorted(homes):
+                record = self.directoryService().recordWithGUID(uuid)
+                if record is not None and record.recordType in (DirectoryService.recordType_locations, DirectoryService.recordType_resources):
+                    uuids.append(uuid)
+        else:
+            uuids = [self.options["uuid"], ]
+
+        count = 0
+        for uuid in uuids:
+            self.results = {}
+            self.summary = []
+            self.total = 0
+            count += 1
+
+            record = self.directoryService().recordWithGUID(uuid)
+            if record is None:
+                continue
+            if not record.thisServer() or not record.enabledForCalendaring:
+                continue
+
+            rname = record.fullName
+            auto = record.autoSchedule
+
+            if len(uuids) > 1 and not self.options["summary"]:
+                self.output.write("\n\n-----------------------------\n")
+
+            self.txn = self.store.newTransaction()
+
+            if self.options["verbose"]:
+                t = time.time()
+            rows = yield self.getTimeRangeInfoWithUUID(uuid, self.start)
+            descriptor = "getTimeRangeInfoWithUUID"
+
+            yield self.txn.commit()
+            self.txn = None
+
+            if self.options["verbose"]:
+                if not self.options["summary"]:
+                    self.output.write("%s time: %.1fs\n" % (descriptor, time.time() - t,))
+                else:
+                    self.output.write("%s (%d/%d)" % (uuid, count, len(uuids),))
+                    self.output.flush()
+
+            self.total = len(rows)
+            if not self.options["summary"]:
+                self.logResult("UUID to process", uuid)
+                self.logResult("Record name", rname)
+                self.logResult("Auto-schedule", "True" if auto else "False")
+                self.addSummaryBreak()
+                self.logResult("Number of events to process", self.total)
+
+            if rows:
+                if not self.options["summary"]:
+                    self.addSummaryBreak()
+                doubled = yield self.doubleBookCheck(rows, uuid, self.start)
+            else:
+                doubled = False
+
+            self.uuid_details.append(UUIDDetails(uuid, rname, auto, doubled))
+
+            if not self.options["summary"]:
+                self.printSummary()
+            else:
+                self.output.write(" - %s\n" % ("Double-booked" if doubled else "OK",))
+                self.output.flush()
+
+        if self.options["summary"]:
+            table = tables.Table()
+            table.addHeader(("GUID", "Name", "Auto-Schedule", "Double-Booked",))
+            doubled = 0
+            for item in sorted(self.uuid_details):
+                if not item.doubled:
+                    continue
+                table.addRow((
+                    item.uuid,
+                    item.rname,
+                    item.auto,
+                    item.doubled,
+                ))
+                doubled += 1
+            table.addFooter(("Total", "", "", "%d of %d" % (doubled, len(self.uuid_details),),))
+            self.output.write("\n")
+            table.printTable(os=self.output)
+
+            if self.options["verbose"]:
+                self.output.write("%s time: %.1fs\n" % ("Summary", time.time() - ot,))
+
+
+    @inlineCallbacks
+    def getTimeRangeInfoWithUUID(self, uuid, start):
+        co = schema.CALENDAR_OBJECT
+        cb = schema.CALENDAR_BIND
+        ch = schema.CALENDAR_HOME
+        tr = schema.TIME_RANGE
+        kwds = {
+            "uuid": uuid,
+            "Start" : pyCalendarTodatetime(start),
+        }
+        rows = (yield Select(
+            [co.RESOURCE_ID, ],
+            From=ch.join(
+                cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID)).join(
+                co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID).And(
+                    cb.BIND_MODE == _BIND_MODE_OWN).And(
+                    cb.CALENDAR_RESOURCE_NAME != "inbox").And(
+                    co.ORGANIZER != "")).join(
+                tr, type="left", on=(co.RESOURCE_ID == tr.CALENDAR_OBJECT_RESOURCE_ID)),
+            Where=(ch.OWNER_UID == Parameter("uuid")).And((tr.START_DATE >= Parameter("Start")).Or(co.RECURRANCE_MAX <= Parameter("Start"))),
+            Distinct=True,
+        ).on(self.txn, **kwds))
+        returnValue(tuple(rows))
+
+
+    @inlineCallbacks
+    def doubleBookCheck(self, rows, uuid, start):
         """
-        Stop the service.  Nothing to do; everything should be finished by this
-        time.
+        Check each calendar resource by expanding instances within the next year, and looking for
+        any that overlap with status not CANCELLED and PARTSTAT ACCEPTED.
         """
-        # TODO: stopping this service mid-export should really stop the export
-        # loop, but this is not implemented because nothing will actually do it
-        # except hitting ^C (which also calls reactor.stop(), so that will exit
-        # anyway).
 
+        if not self.options["summary"]:
+            self.output.write("\n---- Checking instances for double-booking ----\n")
+        self.txn = self.store.newTransaction()
 
+        if self.options["verbose"]:
+            t = time.time()
 
+        InstanceDetails = collections.namedtuple("InstanceDetails", ("resid", "uid", "start", "end", "organizer", "summary",))
+
+        end = start.duplicate()
+        end.offsetDay(int(self.options["days"]))
+        count = 0
+        total = len(rows)
+        total_instances = 0
+        booked_instances = 0
+        details = []
+        rjust = 10
+        tzid = None
+        hasFloating = False
+        for resid in rows:
+            resid = resid[0]
+            caldata = yield self.getCalendar(resid, self.fix)
+            if caldata is None:
+                if self.parseError:
+                    returnValue((False, self.parseError))
+                else:
+                    returnValue((True, "Nothing to scan"))
+
+            cal = Component(None, pycalendar=caldata)
+            cal = PerUserDataFilter(uuid).filter(cal)
+            uid = cal.resourceUID()
+            instances = cal.expandTimeRanges(end, start, ignoreInvalidInstances=False)
+            count += 1
+
+            for instance in instances.instances.values():
+                total_instances += 1
+
+                # See if it is CANCELLED or TRANSPARENT
+                if instance.component.propertyValue("STATUS") == "CANCELLED":
+                    continue
+                if instance.component.propertyValue("TRANSP") == "TRANSPARENT":
+                    continue
+                dtstart = instance.component.propertyValue("DTSTART")
+                if tzid is None and dtstart.getTimezoneID():
+                    tzid = PyCalendarTimezone(tzid=dtstart.getTimezoneID())
+                hasFloating |= dtstart.isDateOnly() or dtstart.floating()
+
+                details.append(InstanceDetails(resid, uid, instance.start, instance.end, instance.component.getOrganizer(), instance.component.propertyValue("SUMMARY")))
+                booked_instances += 1
+
+            if self.options["verbose"] and not self.options["summary"]:
+                if count == 1:
+                    self.output.write("Instances".rjust(rjust) + "Current".rjust(rjust) + "Total".rjust(rjust) + "Complete".rjust(rjust) + "\n")
+                if divmod(count, 100)[1] == 0:
+                    self.output.write((
+                        "\r" +
+                        ("%s" % total_instances).rjust(rjust) +
+                        ("%s" % count).rjust(rjust) +
+                        ("%s" % total).rjust(rjust) +
+                        ("%d%%" % safePercent(count, total)).rjust(rjust)
+                    ).ljust(80))
+                    self.output.flush()
+
+            # To avoid holding locks on all the rows scanned, commit every 100 resources
+            if divmod(count, 100)[1] == 0:
+                yield self.txn.commit()
+                self.txn = self.store.newTransaction()
+
+        yield self.txn.commit()
+        self.txn = None
+        if self.options["verbose"] and not self.options["summary"]:
+            self.output.write((
+                "\r" +
+                ("%s" % total_instances).rjust(rjust) +
+                ("%s" % count).rjust(rjust) +
+                ("%s" % total).rjust(rjust) +
+                ("%d%%" % safePercent(count, total)).rjust(rjust)
+            ).ljust(80) + "\n")
+
+        if not self.options["summary"]:
+            self.logResult("Number of instances in time-range", total_instances)
+            self.logResult("Number of booked instances", booked_instances)
+
+        # Adjust floating and sort
+        if hasFloating and tzid is not None:
+            utc = PyCalendarTimezone(utc=True)
+            for item in details:
+                if item.start.floating():
+                    item.start.setTimezone(tzid)
+                    item.start.adjustTimezone(utc)
+                if item.end.floating():
+                    item.end.setTimezone(tzid)
+                    item.end.adjustTimezone(utc)
+        details.sort(key=lambda x: x.start)
+
+        # Now look for double-bookings
+        DoubleBookedDetails = collections.namedtuple("DoubleBookedDetails", ("resid1", "uid1", "resid2", "uid2", "start",))
+        double_booked = []
+        current = details[0] if details else None
+        for next in details[1:]:
+            if current.end > next.start and current.resid != next.resid and not (current.organizer == next.organizer and current.summary == next.summary):
+                dt = next.start.duplicate()
+                dt.adjustTimezone(self.tzid)
+                double_booked.append(DoubleBookedDetails(current.resid, current.uid, next.resid, next.uid, dt,))
+            current = next
+
+        # Print table of results
+        if double_booked and not self.options["summary"]:
+            table = tables.Table()
+            table.addHeader(("RID #1", "UID #1", "RID #2", "UID #2", "Start",))
+            previous1 = None
+            previous2 = None
+            unique_events = 0
+            for item in sorted(double_booked):
+                if previous1 != item.resid1:
+                    unique_events += 1
+                resid1 = item.resid1 if previous1 != item.resid1 else "."
+                uid1 = item.uid1 if previous1 != item.resid1 else "."
+                resid2 = item.resid2 if previous2 != item.resid2 else "."
+                uid2 = item.uid2 if previous2 != item.resid2 else "."
+                table.addRow((
+                    resid1,
+                    uid1,
+                    resid2,
+                    uid2,
+                    item.start,
+                ))
+                previous1 = item.resid1
+                previous2 = item.resid2
+
+            self.output.write("\n")
+            self.logResult("Number of double-bookings", len(double_booked))
+            self.logResult("Number of unique double-bookings", unique_events)
+            table.printTable(os=self.output)
+
+        self.results["Double-bookings"] = double_booked
+
+        if self.options["verbose"] and not self.options["summary"]:
+            diff_time = time.time() - t
+            self.output.write("Time: %.2f s  Average: %.1f ms/resource\n" % (
+                diff_time,
+                safePercent(diff_time, total, 1000.0),
+            ))
+
+        returnValue(len(double_booked) != 0)
+
+
+
 def main(argv=sys.argv, stderr=sys.stderr, reactor=None):
-    """
-    Do the export.
-    """
+
     if reactor is None:
         from twisted.internet import reactor
     options = CalVerifyOptions()
@@ -1926,9 +2377,18 @@
     def makeService(store):
         from twistedcaldav.config import config
         config.TransactionTimeoutSeconds = 0
-        return CalVerifyService(store, options, output, reactor, config)
+        if options["nuke"]:
+            return NukeService(store, options, output, reactor, config)
+        elif options["missing"]:
+            return OrphansService(store, options, output, reactor, config)
+        elif options["ical"] or options["badcua"]:
+            return BadDataService(store, options, output, reactor, config)
+        elif options["mismatch"]:
+            return SchedulingMismatchService(store, options, output, reactor, config)
+        elif options["double"]:
+            return DoubleBookingService(store, options, output, reactor, config)
 
-    utilityMain(options['config'], makeService, reactor, verbose=options['debug'])
+    utilityMain(options['config'], makeService, reactor)
 
 if __name__ == '__main__':
     main()

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/calverify_diff.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/calverify_diff.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/calverify_diff.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import getopt
 import sys
@@ -77,16 +78,16 @@
 
 def diff(results1, results2):
     
-    print "\n\nEvents missing from Attendee's calendars"
+    print("\n\nEvents missing from Attendee's calendars")
     diffSets(results1["table1"], results2["table1"])
     
-    print "\n\nEvents mismatched between Organizer's and Attendee's calendars"
+    print("\n\nEvents mismatched between Organizer's and Attendee's calendars")
     diffSets(results1["table2"], results2["table2"])
     
-    print "\n\nAttendee events missing in Organizer's calendar"
+    print("\n\nAttendee events missing in Organizer's calendar")
     diffSets(results1["table3"], results2["table3"])
     
-    print "\n\nAttendee events mismatched in Organizer's calendar"
+    print("\n\nAttendee events mismatched in Organizer's calendar")
     diffSets(results1["table4"], results2["table4"])
 
 def diffSets(results1, results2):
@@ -95,20 +96,20 @@
     s2 = set(results2)
     
     d = s1 - s2
-    print "\nIn first, not in second: (%d)" % (len(d),)
+    print("\nIn first, not in second: (%d)" % (len(d),))
     for i in sorted(d):
-        print i
+        print(i)
     
     d = s2 - s1
-    print "\nIn second, not in first: (%d)" % (len(d),)
+    print("\nIn second, not in first: (%d)" % (len(d),))
     for i in sorted(d):
-        print i
+        print(i)
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: calverify_diff [options] FILE1 FILE2
+    print("""Usage: calverify_diff [options] FILE1 FILE2
 Options:
     -h          Print this help and exit
 
@@ -119,7 +120,7 @@
 Description:
     This utility will analyze the output of two calverify runs
     and show what is different between the two.
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)
@@ -143,10 +144,10 @@
         fname1 = args[0]
         fname2 = args[1]
 
-    print "*** CalVerify diff from %s to %s" % (
+    print("*** CalVerify diff from %s to %s" % (
         os.path.basename(fname1),
         os.path.basename(fname2),
-    )
+    ))
     results1 = analyze(fname1)
     results2 = analyze(fname2)
     diff(results1, results2)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/changeip_calendar.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/changeip_calendar.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/changeip_calendar.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -9,7 +9,7 @@
 # Software License Agreement accompanying the package this file is a
 # part of.  You may not port this file to another platform without
 # Apple's written consent.
-
+from __future__ import print_function
 from __future__ import with_statement
 
 import os
@@ -21,15 +21,15 @@
 
 def usage():
     name = os.path.basename(sys.argv[0])
-    print "Usage: %s [-hv] old-ip new-ip [old-hostname new-hostname]" % (name,)
-    print "  Options:"
-    print "    -h           - print this message and exit"
-    print "    -v           - print additional information when running"
-    print "  Arguments:"
-    print "    old-ip       - current IPv4 address of the server"
-    print "    new-ip       - new IPv4 address of the server"
-    print "    old-hostname - current FQDN for the server"
-    print "    new-hostname - new FQDN for the server"
+    print("Usage: %s [-hv] old-ip new-ip [old-hostname new-hostname]" % (name,))
+    print("  Options:")
+    print("    -h           - print this message and exit")
+    print("    -v           - print additional information when running")
+    print("  Arguments:")
+    print("    old-ip       - current IPv4 address of the server")
+    print("    new-ip       - new IPv4 address of the server")
+    print("    old-hostname - current FQDN for the server")
+    print("    new-hostname - new FQDN for the server")
 
 
 def main():
@@ -38,7 +38,7 @@
 
     # Since the serveradmin command must be run as root, so must this script
     if os.getuid() != 0:
-        print "%s must be run as root" % (name,)
+        print("%s must be run as root" % (name,))
         sys.exit(1)
 
     try:
@@ -74,15 +74,15 @@
         oldHostname = newHostname = None
 
     if verbose:
-        print "Calendar Server: updating %s" % (configFile,)
+        print("Calendar Server: updating %s" % (configFile,))
 
     try:
         plist = readPlist(configFile)
     except IOError:
-        print "Error: could not open %s" % (configFile,)
+        print("Error: could not open %s" % (configFile,))
         sys.exit(1)
     except Exception, e:
-        print "Error: could not parse %s" % (configFile,)
+        print("Error: could not parse %s" % (configFile,))
         raise e
 
     writePlist(plist, "%s.changeip.bak" % (configFile,))
@@ -91,7 +91,7 @@
     writePlist(plist, configFile)
 
     if verbose:
-        print "Calendar Server: done"
+        print("Calendar Server: done")
 
 def updatePlist(plist, oldIP, newIP, oldHostname, newHostname, verbose=False):
 
@@ -109,7 +109,7 @@
         if oldHostname and newHostname:
             newValue = newValue.replace(oldHostname, newHostname)
         if verbose and value != newValue:
-            print "Changed %s -> %s" % (value, newValue)
+            print("Changed %s -> %s" % (value, newValue))
         return newValue
 
     for keyPath in keys:

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/cmdline.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/cmdline.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/cmdline.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -30,7 +30,7 @@
 
 # TODO: direct unit tests for these functions.
 
-def utilityMain(configFileName, serviceClass, reactor=None, serviceMaker=CalDAVServiceMaker, verbose=False):
+def utilityMain(configFileName, serviceClass, reactor=None, serviceMaker=CalDAVServiceMaker, patchConfig=None, onShutdown=None, verbose=False):
     """
     Shared main-point for utilities.
 
@@ -52,6 +52,11 @@
         provides L{ICalendarStore} and/or L{IAddressbookStore} and returns an
         L{IService}.
 
+    @param patchConfig: a 1-argument callable which takes a config object
+        and makes and changes necessary for the tool.
+
+    @param onShutdown: a 0-argument callable which will run on shutdown.
+
     @param reactor: if specified, the L{IReactorTime} / L{IReactorThreads} /
         L{IReactorTCP} (etc) provider to use.  If C{None}, the default reactor
         will be imported and used.
@@ -66,6 +71,8 @@
         from twisted.internet import reactor
     try:
         config = loadConfig(configFileName)
+        if patchConfig is not None:
+            patchConfig(config)
 
         # If we don't have permission to access the DataRoot directory, we
         # can't proceed.  If this fails it should raise OSError which we
@@ -83,6 +90,8 @@
 
         reactor.addSystemEventTrigger("during", "startup", service.startService)
         reactor.addSystemEventTrigger("before", "shutdown", service.stopService)
+        if onShutdown is not None:
+            reactor.addSystemEventTrigger("before", "shutdown", onShutdown)
 
     except (ConfigurationError, OSError), e:
         sys.stderr.write("Error: %s\n" % (e,))

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/config.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/config.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/config.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 This tool reads the Calendar Server configuration file and emits the
@@ -31,16 +32,16 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] config_key" % (name,)
-    print ""
-    print "Print the value of the given config key."
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -f --config: Specify caldavd.plist configuration path"
+    print("usage: %s [options] config_key" % (name,))
+    print("")
+    print("Print the value of the given config key.")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -f --config: Specify caldavd.plist configuration path")
 
     if e:
         sys.exit(64)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dbinspect.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dbinspect.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dbinspect.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 This tool allows data in the database to be directly inspected using a set
@@ -49,8 +50,8 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
     try:
         DBInspectOptions().opt_help()
     except SystemExit:
@@ -152,8 +153,8 @@
                 count,
             ))
 
-        print "\n"
-        print "Database Tables (total=%d):\n" % (len(results),)
+        print("\n")
+        print("Database Tables (total=%d):\n" % (len(results),))
         table.printTable()
 
 
@@ -189,8 +190,8 @@
                 shortname,
             ))
 
-        print "\n"
-        print "Calendar Homes (total=%d, missing=%d):\n" % (len(uids), missing,)
+        print("\n")
+        print("Calendar Homes (total=%d, missing=%d):\n" % (len(uids), missing,))
         table.printTable()
 
 
@@ -245,8 +246,8 @@
             "%.2f" % ((1.0 * totals[2]) / totals[0] if totals[0] else 0,),
         ))
 
-        print "\n"
-        print "Calendars with resource count (total=%d):\n" % (len(results),)
+        print("\n")
+        print("Calendars with resource count (total=%d):\n" % (len(results),))
         table.printTable()
 
 
@@ -292,8 +293,8 @@
                 count
             ))
 
-        print "\n"
-        print "Calendars with resource count (total=%d):\n" % (len(uids),)
+        print("\n")
+        print("Calendars with resource count (total=%d):\n" % (len(uids),))
         table.printTable()
 
 
@@ -346,8 +347,8 @@
             totals[1] += count
         table.addFooter(("Total", "", totals[0], "", totals[1]))
 
-        print "\n"
-        print "Calendars with resource count (total=%d):\n" % (len(uids),)
+        print("\n")
+        print("Calendars with resource count (total=%d):\n" % (len(uids),))
         table.printTable()
 
 
@@ -397,8 +398,8 @@
                 caluid
             ))
 
-        print "\n"
-        print "Calendar events (total=%d):\n" % (len(uids),)
+        print("\n")
+        print("Calendar events (total=%d):\n" % (len(uids),))
         table.printTable()
 
 
@@ -435,7 +436,7 @@
         try:
             int(rid)
         except ValueError:
-            print 'Resource ID must be an integer'
+            print('Resource ID must be an integer')
             returnValue(None)
         uids = yield self.getEvents(txn, rid)
 
@@ -450,8 +451,8 @@
                 rid,
             ))
 
-        print "\n"
-        print "Calendar events (total=%d):\n" % (len(uids),)
+        print("\n")
+        print("Calendar events (total=%d):\n" % (len(uids),))
         table.printTable()
 
 
@@ -492,9 +493,9 @@
         table.addRow(("Resource ID:", resource_id))
         table.addRow(("Created", created))
         table.addRow(("Modified", modified))
-        print "\n"
+        print("\n")
         table.printTable()
-        print data
+        print(data)
 
 
     @inlineCallbacks
@@ -533,13 +534,13 @@
         try:
             int(rid)
         except ValueError:
-            print 'Resource ID must be an integer'
+            print('Resource ID must be an integer')
             returnValue(None)
         result = yield self.getData(txn, rid)
         if result:
             self.printEventDetails(txn, result[0])
         else:
-            print "Could not find resource"
+            print("Could not find resource")
 
 
     def getData(self, txn, rid):
@@ -561,7 +562,7 @@
             for result in rows:
                 self.printEventDetails(txn, result)
         else:
-            print "Could not find icalendar data"
+            print("Could not find icalendar data")
 
 
     def getData(self, txn, uid):
@@ -583,7 +584,7 @@
             for result in rows:
                 self.printEventDetails(txn, result)
         else:
-            print "Could not find icalendar data"
+            print("Could not find icalendar data")
 
 
     def getData(self, txn, name):
@@ -606,7 +607,7 @@
             for result in rows:
                 self.printEventDetails(txn, result)
         else:
-            print "Could not find icalendar data"
+            print("Could not find icalendar data")
 
 
     def getData(self, txn, uid):
@@ -630,7 +631,7 @@
             for result in rows:
                 self.printEventDetails(txn, result)
         else:
-            print "Could not find icalendar data"
+            print("Could not find icalendar data")
 
 
     def getData(self, txn, uid, name):
@@ -650,7 +651,7 @@
         path = raw_input("Path: ")
         pathbits = path.split("/")
         if len(pathbits) != 6:
-            print "Not a valid calendar object resource path"
+            print("Not a valid calendar object resource path")
             returnValue(None)
         homeName = pathbits[3]
         calendarName = pathbits[4]
@@ -660,7 +661,7 @@
             for result in rows:
                 self.printEventDetails(txn, result)
         else:
-            print "Could not find icalendar data"
+            print("Could not find icalendar data")
 
 
     def getData(self, txn, homeName, calendarName, resourceName):
@@ -692,7 +693,7 @@
             for result in rows:
                 self.printEventDetails(txn, result)
         else:
-            print "Could not find icalendar data"
+            print("Could not find icalendar data")
 
 
     def getData(self, txn, text):
@@ -719,18 +720,18 @@
         try:
             start = PyCalendarDateTime.parseText(start)
         except ValueError:
-            print "Invalid start value"
+            print("Invalid start value")
             returnValue(None)
         try:
             end = PyCalendarDateTime.parseText(end)
         except ValueError:
-            print "Invalid end value"
+            print("Invalid end value")
             returnValue(None)
         timerange = caldavxml.TimeRange(start=start.getText(), end=end.getText())
 
         home = yield txn.calendarHomeWithUID(uid)
         if home is None:
-            print "Could not find calendar home"
+            print("Could not find calendar home")
             returnValue(None)
 
         yield self.eventsForEachCalendar(home, uid, timerange)
@@ -777,9 +778,9 @@
             table.addRow(("Resource ID:", event._resourceID))
             table.addRow(("Created", event.created()))
             table.addRow(("Modified", event.modified()))
-            print "\n"
+            print("\n")
             table.printTable()
-            print ical_data.getTextWithTimezones(includeTimezones=False)
+            print(ical_data.getTextWithTimezones(includeTimezones=False))
 
 
 
@@ -791,7 +792,7 @@
     def doIt(self, txn):
 
         if raw_input("Do you really want to remove all data [y/n]: ")[0].lower() != 'y':
-            print "No data removed"
+            print("No data removed")
             returnValue(None)
 
         wipeout = (
@@ -827,21 +828,21 @@
 
         for tableschema in wipeout:
             yield self.removeTableData(txn, tableschema)
-            print "Removed rows in table %s" % (tableschema,)
+            print("Removed rows in table %s" % (tableschema,))
 
         if calendaruserproxy.ProxyDBService is not None:
             calendaruserproxy.ProxyDBService.clean() #@UndefinedVariable
-            print "Removed all proxies"
+            print("Removed all proxies")
         else:
-            print "No proxy database to clean."
+            print("No proxy database to clean.")
 
         fp = FilePath(config.AttachmentsRoot)
         if fp.exists():
             for child in fp.children():
                 child.remove()
-            print "Removed attachments."
+            print("Removed attachments.")
         else:
-            print "No attachments path to delete."
+            print("No attachments path to delete.")
 
 
     @inlineCallbacks
@@ -904,7 +905,7 @@
         try:
             yield self.runCommandByName(self.commands[position])
         except IndexError:
-            print "Position %d not available" % (position,)
+            print("Position %d not available" % (position,))
             returnValue(None)
 
 
@@ -913,7 +914,7 @@
         try:
             yield self.runCommand(self.commandMap[name])
         except IndexError:
-            print "Unknown command: '%s'" % (name,)
+            print("Unknown command: '%s'" % (name,))
 
 
     @inlineCallbacks
@@ -925,18 +926,18 @@
             yield txn.commit()
         except Exception, e:
             traceback.print_exc()
-            print "Command '%s' failed because of: %s" % (cmd.name(), e,)
+            print("Command '%s' failed because of: %s" % (cmd.name(), e,))
             yield txn.abort()
 
 
     def printCommands(self):
 
-        print "\n<---- Commands ---->"
+        print("\n<---- Commands ---->")
         for ctr, name in enumerate(self.commands):
-            print "%d. %s" % (ctr + 1, name,)
+            print("%d. %s" % (ctr + 1, name,))
         if self.options["purging"]:
-            print "P. Purge\n"
-        print "Q. Quit\n"
+            print("P. Purge\n")
+        print("Q. Quit\n")
 
 
     @inlineCallbacks
@@ -956,7 +957,7 @@
                 try:
                     position = int(cmd)
                 except ValueError:
-                    print "Invalid command. Try again.\n"
+                    print("Invalid command. Try again.\n")
                     continue
 
                 yield self.runCommandByPosition(position - 1)
@@ -975,7 +976,7 @@
             try:
                 calendaruserproxy.ProxyDBService = proxydbClass(**config.ProxyDBService.params)
             except IOError:
-                print "Could not start proxydb service"
+                print("Could not start proxydb service")
         return self._directory
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dkimtool.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dkimtool.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dkimtool.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -41,7 +41,7 @@
     if options["key"]:
         open(options["key"], "w").write(output)
     else:
-        print output
+        print(output)
         lineBreak = True
 
     output = key.publickey().exportKey()
@@ -50,7 +50,7 @@
     else:
         if lineBreak:
             print
-        print output
+        print(output)
         lineBreak = True
 
     if options["txt"]:
@@ -58,7 +58,7 @@
         txt = "v=DKIM1; p=%s" % (output,)
         if lineBreak:
             print
-        print txt
+        print(txt)
 
 
 
@@ -105,7 +105,7 @@
 
     s = StringIO()
     _writeRequest(dkim, s)
-    print s.getvalue()
+    print(s.getvalue())
 
 
 
@@ -131,9 +131,9 @@
     try:
         yield dkim.verify()
     except DKIMVerificationError, e:
-        print "Verification Failed: %s" % (e,)
+        print("Verification Failed: %s" % (e,))
     else:
-        print "Verification Succeeded"
+        print("Verification Succeeded")
 
 
 
@@ -192,8 +192,8 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
     try:
         DKIMToolOptions().opt_help()
     except SystemExit:
@@ -282,7 +282,7 @@
     try:
         yield fn(options)
     except Exception, e:
-        print e
+        print(e)
     finally:
         reactor.stop()
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/doublequotefix.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/doublequotefix.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/doublequotefix.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import datetime
 import getopt
@@ -32,21 +33,21 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options]" % (name,)
-    print ""
-    print "Fix double-quote/escape bugs in iCalendar data."
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -p <path>: path to calendar server document root [icalserver default]"
-    print "  -u <path>: path to file containing uris to process [uris.txt]"
-    print "  --fix: Apply fixes, otherwise only check for problems"
-    print ""
-    print "uris: list of uris to process"
+    print("usage: %s [options]" % (name,))
+    print("")
+    print("Fix double-quote/escape bugs in iCalendar data.")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -p <path>: path to calendar server document root [icalserver default]")
+    print("  -u <path>: path to file containing uris to process [uris.txt]")
+    print("  --fix: Apply fixes, otherwise only check for problems")
+    print("")
+    print("uris: list of uris to process")
 
     if e:
         sys.exit(64)
@@ -76,7 +77,7 @@
     # Verify we have a valid path
     pathBits = uri.strip("/").rstrip("/").split("/")
     if len(pathBits) != 4 or pathBits[0] != "calendars" or pathBits[1] != "__uids__":
-        print "Invalid uri (ignoring): %s" % (uri,)
+        print("Invalid uri (ignoring): %s" % (uri,))
         totalErrors += 1
         return
 
@@ -92,7 +93,7 @@
     )
     
     if not os.path.exists(calendarPath):
-        print "Calendar path does not exist: %s" % (calendarPath,)
+        print("Calendar path does not exist: %s" % (calendarPath,))
         totalErrors += 1
         return
 
@@ -109,7 +110,7 @@
             f = open(icsPath)
             icsData = f.read()
         except Exception, e:
-            print "Failed to read file %s due to %s" % (icsPath, str(e),)
+            print("Failed to read file %s due to %s" % (icsPath, str(e),))
             totalErrors += 1
             continue
         finally:
@@ -131,7 +132,7 @@
                     f = open(icsPath, "w")
                     f.write(icsData)
                 except Exception, e:
-                    print "Failed to write file %s due to %s" % (icsPath, str(e),)
+                    print("Failed to write file %s due to %s" % (icsPath, str(e),))
                     totalErrors += 1
                     continue
                 finally:
@@ -140,9 +141,9 @@
                 # Change ETag on written resource
                 updateEtag(icsPath, icsData)
                 didFix = True
-                print "Problem fixed in: <BasePath>%s" % (icsPath[basePathLength:],)
+                print("Problem fixed in: <BasePath>%s" % (icsPath[basePathLength:],))
             else:
-                print "Problem found in: <BasePath>%s" % (icsPath[basePathLength:],)
+                print("Problem found in: <BasePath>%s" % (icsPath[basePathLength:],))
             totalProblems += 1
      
     # Change CTag on calendar collection if any resource was written
@@ -182,24 +183,24 @@
     for line in f:
         pos = line.find("/calendars/")
         if pos == -1:
-            print "Ignored log line: %s" % (line,)
+            print("Ignored log line: %s" % (line,))
             continue
         uris.add(line[pos:].split()[0])
     uris = list(uris)
     uris.sort()
     f.close()
 
-    print "Base Path is: %s" % (basePath,)
-    print "Number of unique URIs to fix: %d" % (len(uris),)
-    print ""
+    print("Base Path is: %s" % (basePath,))
+    print("Number of unique URIs to fix: %d" % (len(uris),))
+    print("")
     for uri in uris:
         scanURI(uri, basePath, doFix)
 
-    print ""
-    print "---------------------"
-    print "Total Problems %s: %d of %d" % ("Fixed" if doFix else "Found", totalProblems, totalScanned,)
+    print("")
+    print("---------------------")
+    print("Total Problems %s: %d of %d" % ("Fixed" if doFix else "Found", totalProblems, totalScanned,))
     if totalErrors:
-        print "Total Errors: %s" % (totalErrors,)
+        print("Total Errors: %s" % (totalErrors,))
 
 if __name__ == '__main__':
     

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/export.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/export.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/export.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -33,6 +33,8 @@
 per-user data such as alarms.
 """
 
+from __future__ import print_function
+
 import os
 import sys
 import itertools
@@ -52,8 +54,8 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
     try:
         ExportOptions().opt_help()
     except SystemExit:

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/fixcalendardata.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/fixcalendardata.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/fixcalendardata.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import re
 import datetime
@@ -38,24 +39,24 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options]" % (name,)
-    print ""
-    print "Fix double-quote/escape bugs in iCalendar data."
-    print "Fix incorrect use of TZID in iCalendar data."
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -f --config: Specify caldavd.plist configuration path"
-    print "  -o <path>: path to file for scan results [problems.txt]"
-    print "  -v: print each calendar home scanned"
-    print "  --scan: Scan for problems"
-    print "  --fix: Apply fixes"
-    print ""
-    print "One of --scan or --fix must be specified. Both may be specified"
+    print("usage: %s [options]" % (name,))
+    print("")
+    print("Fix double-quote/escape bugs in iCalendar data.")
+    print("Fix incorrect use of TZID in iCalendar data.")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -f --config: Specify caldavd.plist configuration path")
+    print("  -o <path>: path to file for scan results [problems.txt]")
+    print("  -v: print each calendar home scanned")
+    print("  --scan: Scan for problems")
+    print("  --fix: Apply fixes")
+    print("")
+    print("One of --scan or --fix must be specified. Both may be specified")
 
     if e:
         sys.exit(64)
@@ -101,7 +102,7 @@
 
 def scanCalendarHome(basePath, calendarHome, scanFile, doFix):
     if verbose:
-        print "Scanning: %s" % (calendarHome,)
+        print("Scanning: %s" % (calendarHome,))
     
     for item in os.listdir(calendarHome):
         calendarPath = os.path.join(calendarHome, item)
@@ -116,7 +117,7 @@
     global totalScanned
 
     if not os.path.exists(calendarPath):
-        print "Calendar path does not exist: %s" % (calendarPath,)
+        print("Calendar path does not exist: %s" % (calendarPath,))
         totalErrors += 1
         return
 
@@ -134,7 +135,7 @@
             f = open(icsPath)
             icsData = f.read()
         except Exception, e:
-            print "Failed to read file %s due to %s" % (icsPath, str(e),)
+            print("Failed to read file %s due to %s" % (icsPath, str(e),))
             totalErrors += 1
             continue
         finally:
@@ -158,9 +159,9 @@
             if doFix:
                 if fixPath(icsPath, icsData, fixQuotes, fixTZIDs, fixMultiVALARMs):
                     didFix = True
-                    print "Problems %s fixed in: <BasePath>%s" % (",".join(problems), icsPath[basePathLength:],)
+                    print("Problems %s fixed in: <BasePath>%s" % (",".join(problems), icsPath[basePathLength:],))
             else:
-                print "Problem %s found in: <BasePath>%s" % (",".join(problems), icsPath[basePathLength:],)
+                print("Problem %s found in: <BasePath>%s" % (",".join(problems), icsPath[basePathLength:],))
                 scanFile.write(icsPath + "\n")
             totalProblems += 1
      
@@ -220,7 +221,7 @@
         f = open(scanPath)
         lines = [line[:-1] for line in f]
     except Exception, e:
-        print "Failed to read file %s due to %s" % (scanPath, str(e),)
+        print("Failed to read file %s due to %s" % (scanPath, str(e),))
         totalErrors += 1
         return
     finally:
@@ -241,7 +242,7 @@
             icsPath = os.path.join(calendarPath, icsName)
             if fixPath(icsPath):
                 didFix = True
-                print "Problem fixed in: <BasePath>%s" % (icsPath[basePathLength:],)
+                print("Problem fixed in: <BasePath>%s" % (icsPath[basePathLength:],))
                 totalProblems += 1
          
         # Change CTag on calendar collection if any resource was written
@@ -260,7 +261,7 @@
             f = open(icsPath)
             icsData = f.read()
         except Exception, e:
-            print "Failed to read file %s due to %s" % (icsPath, str(e),)
+            print("Failed to read file %s due to %s" % (icsPath, str(e),))
             totalErrors += 1
             return False
         finally:
@@ -302,7 +303,7 @@
         f = open(icsPath, "w")
         f.write(icsData)
     except Exception, e:
-        print "Failed to write file %s due to %s" % (icsPath, str(e),)
+        print("Failed to write file %s due to %s" % (icsPath, str(e),))
         totalErrors += 1
         return False
     finally:
@@ -348,29 +349,29 @@
     basePath = parsePlist(plistPath)
 
     start = time.time()
-    print "Base Path is: %s" % (basePath,)
+    print("Base Path is: %s" % (basePath,))
     if doScan:
         if doFix:
-            print "Scanning data store and fixing"
+            print("Scanning data store and fixing")
             scanFile = None
         else:
-            print "Scanning data store and writing results to '%s'" % (scanPath,)
+            print("Scanning data store and writing results to '%s'" % (scanPath,))
             try:
                 scanFile = open(scanPath, "w")
             except Exception, e:
-                print "Failed to open file for writing %s due to %s" % (scanPath, str(e),)
+                print("Failed to open file for writing %s due to %s" % (scanPath, str(e),))
         scanData(basePath, scanFile, doFix)
     elif doFix:
-        print "Fixing data using results from '%s'" % (scanPath,)
+        print("Fixing data using results from '%s'" % (scanPath,))
         fixData(basePath, scanPath)
     difftime = time.time() - start
 
-    print ""
-    print "---------------------"
-    print "Total Problems %s: %d of %d" % ("Fixed" if doFix else "Found", totalProblems, totalScanned,)
+    print("")
+    print("---------------------")
+    print("Total Problems %s: %d of %d" % ("Fixed" if doFix else "Found", totalProblems, totalScanned,))
     if totalErrors:
-        print "Total Errors: %s" % (totalErrors,)
-    print "Time taken (secs): %.1f" % (difftime,)
+        print("Total Errors: %s" % (totalErrors,))
+    print("Time taken (secs): %.1f" % (difftime,))
 
 if __name__ == '__main__':
     

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/gateway.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/gateway.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/gateway.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from getopt import getopt, GetoptError
 import os
@@ -40,15 +41,15 @@
 def usage(e=None):
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options]" % (name,)
-    print ""
-    print "  TODO: describe usage"
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -e --error: send stderr to stdout"
-    print "  -f --config <path>: Specify caldavd.plist configuration path"
-    print ""
+    print("usage: %s [options]" % (name,))
+    print("")
+    print("  TODO: describe usage")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -e --error: send stderr to stdout")
+    print("  -f --config <path>: Specify caldavd.plist configuration path")
+    print("")
 
     if e:
         sys.exit(64)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/icalsplit.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/icalsplit.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/icalsplit.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import os
 import sys
@@ -53,7 +54,7 @@
         uid = subcalendar.resourceUID()
         subFileName = os.path.join(outputDirectory, uid + ".ics")
 
-        print "Writing %s" % (subFileName,)
+        print("Writing %s" % (subFileName,))
 
         subcalendar_file = file(subFileName, "w")
         try:
@@ -64,19 +65,19 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] input_file output_directory" % (name,)
-    print ""
-    print "  Splits up monolithic iCalendar data into separate files for each"
-    print "  subcomponent so as to comply with CalDAV requirements for"
-    print "  individual resources."
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print ""
+    print("usage: %s [options] input_file output_directory" % (name,))
+    print("")
+    print("  Splits up monolithic iCalendar data into separate files for each")
+    print("  subcomponent so as to comply with CalDAV requirements for")
+    print("  individual resources.")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("")
 
     if e:
         sys.exit(64)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/loadaugmentdb.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/loadaugmentdb.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/loadaugmentdb.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from calendarserver.tools.managetimezones import StandardIOObserver
 from calendarserver.tools.util import loadConfig, getDirectory, \
@@ -43,20 +44,20 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options]" % (name,)
-    print ""
-    print "Populate an sqlite or PostgreSQL augments database with values"
-    print "from an XML augments file."
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -f --config: Specify caldavd.plist configuration path"
-    print "  -x --xmlfile: Specify xml augments file path"
-    print "  -r --remove: Remove all entries from the database"
+    print("usage: %s [options]" % (name,))
+    print("")
+    print("Populate an sqlite or PostgreSQL augments database with values")
+    print("from an XML augments file.")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -f --config: Specify caldavd.plist configuration path")
+    print("  -x --xmlfile: Specify xml augments file path")
+    print("  -r --remove: Remove all entries from the database")
 
     if e:
         sys.exit(64)
@@ -160,10 +161,10 @@
             yield augment.AugmentService.removeAugmentRecords(remove_uids)
             removed = len(remove_uids)
 
-        print "Changes:"
-        print "  Added: %d" % (added,)
-        print "  Changed: %d" % (updated,)
-        print "  Removed: %d" % (removed,)
+        print("Changes:")
+        print("  Added: %d" % (added,))
+        print("  Changed: %d" % (updated,))
+        print("  Removed: %d" % (removed,))
     finally:
         #
         # Stop the reactor

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/managepostgres.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/managepostgres.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/managepostgres.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from optparse import OptionParser
 import os
@@ -22,11 +23,11 @@
 import time
 
 def error(s):
-    print s
+    print(s)
     sys.exit(1)
 
 def cmd(s):
-    print s
+    print(s)
     subprocess.call(s, shell=True)
 
 def doInit(basedir):

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/managetimezones.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/managetimezones.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/managetimezones.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from pycalendar.calendar import PyCalendar
 from pycalendar.datetime import PyCalendarDateTime
@@ -65,20 +66,20 @@
     Refresh data from IANA.
     """
 
-    print "Downloading latest data from IANA"
+    print("Downloading latest data from IANA")
     if tzvers:
         path = "http://www.iana.org/time-zones/repository/releases/tzdata%s.tar.gz" % (tzvers,)
     else:
         path = "http://www.iana.org/time-zones/repository/tzdata-latest.tar.gz"
         tzvers = "Latest (%s)" % (PyCalendarDateTime.getToday().getText(),)
     data = urllib.urlretrieve(path)
-    print "Extract data at: %s" % (data[0])
+    print("Extract data at: %s" % (data[0]))
     rootdir = tempfile.mkdtemp()
     zonedir = os.path.join(rootdir, "tzdata")
     os.mkdir(zonedir)
     with tarfile.open(data[0], "r:gz") as t:
         t.extractall(zonedir)
-    print "Converting data at: %s" % (zonedir,)
+    print("Converting data at: %s" % (zonedir,))
     startYear = 1800
     endYear = PyCalendarDateTime.getToday().getYear() + 10
     PyCalendar.sProdID = "-//calendarserver.org//Zonal//EN"
@@ -88,22 +89,22 @@
         parser.parse(os.path.join(zonedir, file))
 
     parser.generateZoneinfoFiles(os.path.join(rootdir, "zoneinfo"), startYear, endYear, filterzones=())
-    print "Copy new zoneinfo to destination: %s" % (tzpath,)
+    print("Copy new zoneinfo to destination: %s" % (tzpath,))
     z = FilePath(os.path.join(rootdir, "zoneinfo"))
     tz = FilePath(tzpath)
     z.copyTo(tz)
-    print "Updating XML file at: %s" % (xmlfile,)
+    print("Updating XML file at: %s" % (xmlfile,))
     tzdb.readDatabase()
     tzdb.updateDatabase()
-    print "Current total: %d" % (len(tzdb.timezones),)
-    print "Total Changed: %d" % (tzdb.changeCount,)
+    print("Current total: %d" % (len(tzdb.timezones),))
+    print("Total Changed: %d" % (tzdb.changeCount,))
     if tzdb.changeCount:
-        print "Changed:"
+        print("Changed:")
         for k in sorted(tzdb.changed):
-            print "  %s" % (k,)
+            print("  %s" % (k,))
 
     versfile = os.path.join(os.path.dirname(xmlfile), "version.txt")
-    print "Updating version file at: %s" % (versfile,)
+    print("Updating version file at: %s" % (versfile,))
     with open(versfile, "w") as f:
         f.write("Olson data source: %s\n" % (tzvers,))
 
@@ -114,9 +115,9 @@
     Create new xml file.
     """
 
-    print "Creating new XML file at: %s" % (xmlfile,)
+    print("Creating new XML file at: %s" % (xmlfile,))
     tzdb.createNewDatabase()
-    print "Current total: %d" % (len(tzdb.timezones),)
+    print("Current total: %d" % (len(tzdb.timezones),))
 
 
 
@@ -125,15 +126,15 @@
     Update xml file.
     """
 
-    print "Updating XML file at: %s" % (xmlfile,)
+    print("Updating XML file at: %s" % (xmlfile,))
     tzdb.readDatabase()
     tzdb.updateDatabase()
-    print "Current total: %d" % (len(tzdb.timezones),)
-    print "Total Changed: %d" % (tzdb.changeCount,)
+    print("Current total: %d" % (len(tzdb.timezones),))
+    print("Total Changed: %d" % (tzdb.changeCount,))
     if tzdb.changeCount:
-        print "Changed:"
+        print("Changed:")
         for k in sorted(tzdb.changed):
-            print "  %s" % (k,)
+            print("  %s" % (k,))
 
 
 
@@ -142,12 +143,12 @@
     List current timezones from xml file.
     """
 
-    print "Listing XML file at: %s" % (xmlfile,)
+    print("Listing XML file at: %s" % (xmlfile,))
     tzdb.readDatabase()
-    print "Current timestamp: %s" % (tzdb.dtstamp,)
-    print "Timezones:"
+    print("Current timestamp: %s" % (tzdb.dtstamp,))
+    print("Timezones:")
     for k in sorted(tzdb.timezones.keys()):
-        print "  %s" % (k,)
+        print("  %s" % (k,))
 
 
 
@@ -156,16 +157,16 @@
     Check for local timezone changes.
     """
 
-    print "Changes from XML file at: %s" % (xmlfile,)
+    print("Changes from XML file at: %s" % (xmlfile,))
     tzdb.readDatabase()
-    print "Check timestamp: %s" % (changed,)
-    print "Current timestamp: %s" % (tzdb.dtstamp,)
+    print("Check timestamp: %s" % (changed,))
+    print("Current timestamp: %s" % (tzdb.dtstamp,))
     results = [k for k, v in tzdb.timezones.items() if v.dtstamp > changed]
-    print "Total Changed: %d" % (len(results),)
+    print("Total Changed: %d" % (len(results),))
     if results:
-        print "Changed:"
+        print("Changed:")
         for k in sorted(results):
-            print "  %s" % (k,)
+            print("  %s" % (k,))
 
 
 
@@ -174,11 +175,11 @@
 
     try:
         new, changed = yield tzdb.syncWithServer()
-        print "New:           %d" % (new,)
-        print "Changed:       %d" % (changed,)
-        print "Current total: %d" % (len(tzdb.timezones),)
+        print("New:           %d" % (new,))
+        print("Changed:       %d" % (changed,))
+        print("Current total: %d" % (len(tzdb.timezones),))
     except Exception, e:
-        print "Could not sync with server: %s" % (str(e),)
+        print("Could not sync with server: %s" % (str(e),))
     finally:
         reactor.stop()
 
@@ -192,7 +193,7 @@
     except:
         pass
     if action == "cache":
-        print "Caching from secondary server: %s" % (url,)
+        print("Caching from secondary server: %s" % (url,))
 
         observer = StandardIOObserver()
         observer.start()
@@ -205,10 +206,10 @@
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
-        print
+        print(error_msg)
+        print("")
 
-    print """Usage: managetimezones [options]
+    print("""Usage: managetimezones [options]
 Options:
     -h            Print this help and exit
     -f            XML file path
@@ -232,7 +233,7 @@
     This utility will create, update or list an XML timezone database
     summary file, or refresh iCalendar timezone from IANA (Olson).
 
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/migrate.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/migrate.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/migrate.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 This tool migrates existing calendar data from any previous calendar server
@@ -36,17 +37,17 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options]" % (name,)
-    print ""
-    print "Migrate calendar data to current version"
-    print __doc__
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -f --config: Specify caldavd.plist configuration path"
+    print("usage: %s [options]" % (name,))
+    print("")
+    print("Migrate calendar data to current version")
+    print(__doc__)
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -f --config: Specify caldavd.plist configuration path")
 
     if e:
         sys.exit(64)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/migrate_verify.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/migrate_verify.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/migrate_verify.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
+
 from txdav.common.datastore.sql_tables import schema, _BIND_MODE_OWN
 from twext.enterprise.dal.syntax import Select, Parameter
 
@@ -38,8 +40,8 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
     try:
         MigrateVerifyOptions().opt_help()
     except SystemExit:

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/notifications.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/notifications.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/notifications.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from calendarserver.tools.util import loadConfig
 from datetime import datetime
@@ -42,26 +43,26 @@
 
 def usage(e=None):
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] username" % (name,)
-    print ""
-    print " Monitor push notification events from calendar server"
-    print ""
-    print "options:"
-    print "  -a --admin <username>: Specify an administrator username"
-    print "  -f --config <path>: Specify caldavd.plist configuration path"
-    print "  -h --help: print this help and exit"
-    print "  -H --host <hostname>: calendar server host name"
-    print "  -n --node <pubsub node>: pubsub node to subscribe to *"
-    print "  -p --port <port number>: calendar server port number"
-    print "  -s --ssl: use https (default is http)"
-    print "  -v --verbose: print additional information including XMPP traffic"
-    print ""
-    print " * The --node option is only required for calendar servers that"
-    print "   don't advertise the push-transports DAV property (such as a Snow"
-    print "   Leopard server).  In this case, --host should specify the name"
-    print "   of the XMPP server and --port should specify the port XMPP is"
-    print "   is listening on."
-    print ""
+    print("usage: %s [options] username" % (name,))
+    print("")
+    print(" Monitor push notification events from calendar server")
+    print("")
+    print("options:")
+    print("  -a --admin <username>: Specify an administrator username")
+    print("  -f --config <path>: Specify caldavd.plist configuration path")
+    print("  -h --help: print this help and exit")
+    print("  -H --host <hostname>: calendar server host name")
+    print("  -n --node <pubsub node>: pubsub node to subscribe to *")
+    print("  -p --port <port number>: calendar server port number")
+    print("  -s --ssl: use https (default is http)")
+    print("  -v --verbose: print additional information including XMPP traffic")
+    print("")
+    print(" * The --node option is only required for calendar servers that")
+    print("   don't advertise the push-transports DAV property (such as a Snow")
+    print("   Leopard server).  In this case, --host should specify the name")
+    print("   of the XMPP server and --port should specify the port XMPP is")
+    print("   is listening on.")
+    print("")
 
     if e:
         sys.stderr.write("%s\n" % (e,))
@@ -125,7 +126,7 @@
         try:
             loadConfig(configFileName)
         except ConfigurationError, e:
-            print "Error in configuration: %s" % (e,)
+            print("Error in configuration: %s" % (e,))
             sys.exit(1)
 
         useSSL = config.EnableSSL
@@ -168,7 +169,7 @@
         self.verbose = verbose
 
         if self.verbose:
-            print "JID:", self.jid, "Pubsub service:", self.service
+            print("JID:", self.jid, "Pubsub service:", self.service)
 
         self.presenceSeconds = 60
         self.presenceCall = None
@@ -193,7 +194,7 @@
 
     @inlineCallbacks
     def sigint_handler(self, num, frame):
-        print " Shutting down..."
+        print(" Shutting down...")
         yield self.unsubscribeAll()
         reactor.stop()
 
@@ -206,7 +207,7 @@
     def connected(self, xmlStream):
         self.xmlStream = xmlStream
         if self.verbose:
-            print "XMPP connection successful"
+            print("XMPP connection successful")
             xmlStream.rawDataInFn = self.rawDataIn
             xmlStream.rawDataOutFn = self.rawDataOut
         xmlStream.addObserver("/message/event/items",
@@ -218,25 +219,25 @@
             self.presenceCall.cancel()
             self.presenceCall = None
         if self.verbose:
-            print "XMPP disconnected"
+            print("XMPP disconnected")
 
     def initFailed(self, failure):
         self.xmlStream = None
-        print "XMPP connection failure: %s" % (failure,)
+        print("XMPP connection failure: %s" % (failure,))
         reactor.stop()
 
     @inlineCallbacks
     def authenticated(self, xmlStream):
         if self.verbose:
-            print "XMPP authentication successful"
+            print("XMPP authentication successful")
         self.sendPresence()
         for node, (url, name, kind) in self.nodes.iteritems():
             yield self.subscribe(node, name, kind)
 
-        print "Awaiting notifications (hit Control-C to end)"
+        print("Awaiting notifications (hit Control-C to end)")
 
     def authFailed(self, e):
-        print "XMPP authentication failed"
+        print("XMPP authentication failed")
         reactor.stop()
 
     def sendPresence(self):
@@ -254,10 +255,10 @@
                 node = str(node)
                 url, name, kind = self.nodes.get(node, ("Not subscribed", "Unknown", "Unknown"))
                 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-                print '%s | Notification for "%s" (%s)' % (timestamp, name, kind)
+                print('%s | Notification for "%s" (%s)' % (timestamp, name, kind))
                 if self.verbose:
-                    print " node = %s" % (node,)
-                    print " url = %s" % (url,)
+                    print(" node = %s" % (node,))
+                    print(" url = %s" % (url,))
 
 
     @inlineCallbacks
@@ -267,14 +268,14 @@
         subElement = pubsubElement.addElement("subscribe")
         subElement["node"] = node
         subElement["jid"] = self.jid
-        print 'Subscribing to "%s" (%s)' % (name, kind)
+        print('Subscribing to "%s" (%s)' % (name, kind))
         if self.verbose:
-            print node
+            print(node)
         try:
             yield iq.send(to=self.service)
-            print "OK"
+            print("OK")
         except Exception, e:
-            print "Subscription failure: %s %s" % (node, e)
+            print("Subscription failure: %s %s" % (node, e))
 
     @inlineCallbacks
     def unsubscribe(self, node, name, kind):
@@ -283,14 +284,14 @@
         subElement = pubsubElement.addElement("unsubscribe")
         subElement["node"] = node
         subElement["jid"] = self.jid
-        print 'Unsubscribing from "%s" (%s)' % (name, kind)
+        print('Unsubscribing from "%s" (%s)' % (name, kind))
         if self.verbose:
-            print node
+            print(node)
         try:
             yield iq.send(to=self.service)
-            print "OK"
+            print("OK")
         except Exception, e:
-            print "Unsubscription failure: %s %s" % (node, e)
+            print("Unsubscription failure: %s %s" % (node, e))
 
 
     @inlineCallbacks
@@ -299,18 +300,18 @@
         iq = IQ(self.xmlStream)
         pubsubElement = iq.addElement("pubsub", defaultUri=self.pubsubNS)
         pubsubElement.addElement("subscriptions")
-        print "Requesting list of subscriptions"
+        print("Requesting list of subscriptions")
         try:
             yield iq.send(to=self.service)
         except Exception, e:
-            print "Subscription list failure: %s" % (e,)
+            print("Subscription list failure: %s" % (e,))
 
 
     def rawDataIn(self, buf):
-        print "RECV: %s" % unicode(buf, 'utf-8').encode('ascii', 'replace')
+        print("RECV: %s" % unicode(buf, 'utf-8').encode('ascii', 'replace'))
 
     def rawDataOut(self, buf):
-        print "SEND: %s" % unicode(buf, 'utf-8').encode('ascii', 'replace')
+        print("SEND: %s" % unicode(buf, 'utf-8').encode('ascii', 'replace'))
 
 
 class PropfindRequestor(AuthorizedHTTPGetter):
@@ -345,14 +346,14 @@
                 principal = "/principals/users/%s/" % (self.username,)
                 name, homes = (yield self.getPrincipalDetails(principal))
                 if self.verbose:
-                    print name, homes
+                    print(name, homes)
                 for home in homes:
                     paths.add(home)
                 for principal in (yield self.getProxyFor()):
                     name, homes = (yield self.getPrincipalDetails(principal,
                         includeCardDAV=False))
                     if self.verbose:
-                        print name, homes
+                        print(name, homes)
                     for home in homes:
                         if home.startswith("/"):
                             # Only support homes on the same server for now.
@@ -371,11 +372,11 @@
             if subscribeNodes:
                 self.startMonitoring(host, port, subscribeNodes)
             else:
-                print "No nodes to monitor"
+                print("No nodes to monitor")
                 reactor.stop()
 
         except Exception, e:
-            print "Error:", e
+            print("Error:", e)
             reactor.stop()
 
     @inlineCallbacks
@@ -434,12 +435,12 @@
                                         name = displayName
 
             except Exception, e:
-                print "Unable to parse principal details", e
-                print responseBody
+                print("Unable to parse principal details", e)
+                print(responseBody)
                 raise
 
         except Exception, e:
-            print "Unable to look up principal details", e
+            print("Unable to look up principal details", e)
             raise
 
         returnValue( (name, homes) )
@@ -489,12 +490,12 @@
                                                 proxies.add(href)
 
             except Exception, e:
-                print "Unable to parse proxy information", e
-                print responseBody
+                print("Unable to parse proxy information", e)
+                print(responseBody)
                 raise
 
         except Exception, e:
-            print "Unable to look up who %s is a proxy for" % (self.username,)
+            print("Unable to look up who %s is a proxy for" % (self.username,))
             raise
 
         returnValue(proxies)
@@ -561,7 +562,7 @@
                                 pushTransports = prop.find("{http://calendarserver.org/ns/}push-transports")
                                 if pushTransports is not None:
                                     if self.verbose:
-                                        print "push-transports:\n\n", ElementTree.tostring(pushTransports)
+                                        print("push-transports:\n\n", ElementTree.tostring(pushTransports))
                                     for transport in pushTransports.findall("{http://calendarserver.org/ns/}transport"):
                                         if transport.attrib["type"] == "XMPP":
                                             xmppServer = transport.find("{http://calendarserver.org/ns/}xmpp-server")
@@ -579,12 +580,12 @@
                         nodes[key] = (href.text, name, kind)
 
             except Exception, e:
-                print "Unable to parse push information", e
-                print responseBody
+                print("Unable to parse push information", e)
+                print(responseBody)
                 raise
 
         except Exception, e:
-            print "Unable to look up push information for %s" % (self.username,)
+            print("Unable to look up push information for %s" % (self.username,))
             raise
 
         if host is None:

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/obliterate.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/obliterate.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/obliterate.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 This tool scans wipes out user data without using slow store object apis
@@ -43,8 +44,8 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
     try:
         ObliterateOptions().opt_help()
     except SystemExit:

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/principals.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/principals.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -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
 import os
@@ -49,49 +50,49 @@
 def usage(e=None):
     if e:
         if isinstance(e, UnknownRecordTypeError):
-            print "Valid record types:"
+            print("Valid record types:")
             for recordType in config.directory.recordTypes():
-                print "    %s" % (recordType,)
+                print("    %s" % (recordType,))
 
-        print e
-        print ""
+        print(e)
+        print("")
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] action_flags principal [principal ...]" % (name,)
-    print "       %s [options] --list-principal-types" % (name,)
-    print "       %s [options] --list-principals type" % (name,)
-    print ""
-    print "  Performs the given actions against the giving principals."
-    print ""
-    print "  Principals are identified by one of the following:"
-    print "    Type and shortname (eg.: users:wsanchez)"
-    #print "    A principal path (eg.: /principals/users/wsanchez/)"
-    print "    A GUID (eg.: E415DBA7-40B5-49F5-A7CC-ACC81E4DEC79)"
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -f --config <path>: Specify caldavd.plist configuration path"
-    print "  -v --verbose: print debugging information"
-    print ""
-    print "actions:"
-    print "  --search <search-string>: search for matching principals"
-    print "  --list-principal-types: list all of the known principal types"
-    print "  --list-principals type: list all principals of the given type"
-    print "  --read-property=property: read DAV property (eg.: {DAV:}group-member-set)"
-    print "  --list-read-proxies: list proxies with read-only access"
-    print "  --list-write-proxies: list proxies with read-write access"
-    print "  --list-proxies: list all proxies"
-    print "  --add-read-proxy=principal: add a read-only proxy"
-    print "  --add-write-proxy=principal: add a read-write proxy"
-    print "  --remove-proxy=principal: remove a proxy"
-    print "  --set-auto-schedule={true|false}: set auto-accept state"
-    print "  --get-auto-schedule: read auto-schedule state"
-    print "  --set-auto-schedule-mode={default|none|accept-always|decline-always|accept-if-free|decline-if-busy|automatic}: set auto-schedule mode"
-    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 "  --remove: remove a principal"
+    print("usage: %s [options] action_flags principal [principal ...]" % (name,))
+    print("       %s [options] --list-principal-types" % (name,))
+    print("       %s [options] --list-principals type" % (name,))
+    print("")
+    print("  Performs the given actions against the giving principals.")
+    print("")
+    print("  Principals are identified by one of the following:")
+    print("    Type and shortname (eg.: users:wsanchez)")
+    #print("    A principal path (eg.: /principals/users/wsanchez/)")
+    print("    A GUID (eg.: E415DBA7-40B5-49F5-A7CC-ACC81E4DEC79)")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -f --config <path>: Specify caldavd.plist configuration path")
+    print("  -v --verbose: print debugging information")
+    print("")
+    print("actions:")
+    print("  --search <search-string>: search for matching principals")
+    print("  --list-principal-types: list all of the known principal types")
+    print("  --list-principals type: list all principals of the given type")
+    print("  --read-property=property: read DAV property (eg.: {DAV:}group-member-set)")
+    print("  --list-read-proxies: list proxies with read-only access")
+    print("  --list-write-proxies: list proxies with read-write access")
+    print("  --list-proxies: list all proxies")
+    print("  --add-read-proxy=principal: add a read-only proxy")
+    print("  --add-write-proxy=principal: add a read-write proxy")
+    print("  --remove-proxy=principal: remove a proxy")
+    print("  --set-auto-schedule={true|false}: set auto-accept state")
+    print("  --get-auto-schedule: read auto-schedule state")
+    print("  --set-auto-schedule-mode={default|none|accept-always|decline-always|accept-if-free|decline-if-busy|automatic}: set auto-schedule mode")
+    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("  --remove: remove a principal")
 
     if e:
         sys.exit(64)
@@ -298,7 +299,7 @@
             usage("Too many arguments")
 
         for recordType in config.directory.recordTypes():
-            print recordType
+            print(recordType)
 
         return
 
@@ -307,13 +308,13 @@
         try:
             addType = matchStrings(addType, ["locations", "resources"])
         except ValueError, e:
-            print e
+            print(e)
             return
 
         try:
             fullName, shortName, guid = parseCreationArgs(args)
         except ValueError, e:
-            print e
+            print(e)
             return
 
         if shortName is not None:
@@ -329,7 +330,7 @@
             listPrincipals = matchStrings(listPrincipals, ["users", "groups",
                 "locations", "resources"])
         except ValueError, e:
-            print e
+            print(e)
             return
 
         if args:
@@ -340,7 +341,7 @@
             if records:
                 printRecordList(records)
             else:
-                print "No records of type %s" % (listPrincipals,)
+                print("No records of type %s" % (listPrincipals,))
         except UnknownRecordTypeError, e:
             usage(e)
 
@@ -390,7 +391,7 @@
             # Performs requested actions
             for action in actions:
                 (yield action[0](principal, *action[1:]))
-                print ""
+                print("")
 
     finally:
         #
@@ -409,25 +410,25 @@
         records = list((yield config.directory.recordsMatchingTokens(searchTerm.strip().split())))
         if records:
             records.sort(key=operator.attrgetter('fullName'))
-            print "%d matches found:" % (len(records),)
+            print("%d matches found:" % (len(records),))
             for record in records:
-                print "\n%s (%s)" % (record.fullName,
+                print("\n%s (%s)" % (record.fullName,
                     { "users"     : "User",
                       "groups"    : "Group",
                       "locations" : "Place",
                       "resources" : "Resource",
                     }.get(record.recordType),
-                )
-                print "   GUID: %s" % (record.guid,)
-                print "   Record name(s): %s" % (", ".join(record.shortNames),)
+                ))
+                print("   GUID: %s" % (record.guid,))
+                print("   Record name(s): %s" % (", ".join(record.shortNames),))
                 if record.authIDs:
-                    print "   Auth ID(s): %s" % (", ".join(record.authIDs),)
+                    print("   Auth ID(s): %s" % (", ".join(record.authIDs),))
                 if record.emailAddresses:
-                    print "   Email(s): %s" % (", ".join(record.emailAddresses),)
+                    print("   Email(s): %s" % (", ".join(record.emailAddresses),))
         else:
-            print "No matches found"
+            print("No matches found")
 
-        print ""
+        print("")
 
     finally:
         #
@@ -441,9 +442,9 @@
         try:
             yield updateRecord(True, config.directory, addType, guid=guid,
                 shortNames=shortNames, fullName=fullName)
-            print "Added '%s'" % (fullName,)
+            print("Added '%s'" % (fullName,))
         except DirectoryError, e:
-            print e
+            print(e)
 
     finally:
         #
@@ -523,32 +524,32 @@
     guid = record.guid
 
     config.directory.destroyRecord(record.recordType, guid=guid)
-    print "Removed '%s' %s %s" % (fullName, shortName, guid)
+    print("Removed '%s' %s %s" % (fullName, shortName, guid))
 
 
 @inlineCallbacks
 def action_readProperty(resource, qname):
     property = (yield resource.readProperty(qname, None))
-    print "%r on %s:" % (encodeXMLName(*qname), resource)
-    print ""
-    print property.toxml()
+    print("%r on %s:" % (encodeXMLName(*qname), resource))
+    print("")
+    print(property.toxml())
 
 @inlineCallbacks
 def action_listProxies(principal, *proxyTypes):
     for proxyType in proxyTypes:
         subPrincipal = proxySubprincipal(principal, proxyType)
         if subPrincipal is None:
-            print "No %s proxies for %s" % (proxyType,
-                prettyPrincipal(principal))
+            print("No %s proxies for %s" % (proxyType,
+                prettyPrincipal(principal)))
             continue
 
         membersProperty = (yield subPrincipal.readProperty(davxml.GroupMemberSet, None))
 
         if membersProperty.children:
-            print "%s proxies for %s:" % (
+            print("%s proxies for %s:" % (
                 {"read": "Read-only", "write": "Read/write"}[proxyType],
                 prettyPrincipal(principal)
-            )
+            ))
             records = []
             for member in membersProperty.children:
                 proxyPrincipal = principalForPrincipalID(str(member),
@@ -558,15 +559,15 @@
             printRecordList(records)
             print
         else:
-            print "No %s proxies for %s" % (proxyType,
-                prettyPrincipal(principal))
+            print("No %s proxies for %s" % (proxyType,
+                prettyPrincipal(principal)))
 
 @inlineCallbacks
 def action_addProxy(principal, proxyType, *proxyIDs):
     for proxyID in proxyIDs:
         proxyPrincipal = principalForPrincipalID(proxyID)
         if proxyPrincipal is None:
-            print "Invalid principal ID: %s" % (proxyID,)
+            print("Invalid principal ID: %s" % (proxyID,))
         else:
             (yield action_addProxyPrincipal(principal, proxyType, proxyPrincipal))
 
@@ -574,13 +575,13 @@
 def action_addProxyPrincipal(principal, proxyType, proxyPrincipal):
     try:
         (yield addProxy(principal, proxyType, proxyPrincipal))
-        print "Added %s as a %s proxy for %s" % (
+        print("Added %s as a %s proxy for %s" % (
             prettyPrincipal(proxyPrincipal), proxyType,
-            prettyPrincipal(principal))
+            prettyPrincipal(principal)))
     except ProxyError, e:
-        print "Error:", e
+        print("Error:", e)
     except ProxyWarning, e:
-        print e
+        print(e)
 
 @inlineCallbacks
 def addProxy(principal, proxyType, proxyPrincipal):
@@ -671,7 +672,7 @@
     for proxyID in proxyIDs:
         proxyPrincipal = principalForPrincipalID(proxyID)
         if proxyPrincipal is None:
-            print "Invalid principal ID: %s" % (proxyID,)
+            print("Invalid principal ID: %s" % (proxyID,))
         else:
             (yield action_removeProxyPrincipal(principal, proxyPrincipal, **kwargs))
 
@@ -680,13 +681,13 @@
     try:
         removed = (yield removeProxy(principal, proxyPrincipal, **kwargs))
         if removed:
-            print "Removed %s as a proxy for %s" % (
+            print("Removed %s as a proxy for %s" % (
                 prettyPrincipal(proxyPrincipal),
-                prettyPrincipal(principal))
+                prettyPrincipal(principal)))
     except ProxyError, e:
-        print "Error:", e
+        print("Error:", e)
     except ProxyWarning, e:
-        print e
+        print(e)
 
 
 @inlineCallbacks
@@ -725,16 +726,16 @@
 @inlineCallbacks
 def action_setAutoSchedule(principal, autoSchedule):
     if principal.record.recordType == "groups":
-        print "Enabling auto-schedule for %s is not allowed." % (principal,)
+        print("Enabling auto-schedule for %s is not allowed." % (principal,))
 
     elif principal.record.recordType == "users" and not config.Scheduling.Options.AutoSchedule.AllowUsers:
-        print "Enabling auto-schedule for %s is not allowed." % (principal,)
+        print("Enabling auto-schedule for %s is not allowed." % (principal,))
 
     else:
-        print "Setting auto-schedule to %s for %s" % (
+        print("Setting auto-schedule to %s for %s" % (
             { True: "true", False: "false" }[autoSchedule],
             prettyPrincipal(principal),
-        )
+        ))
 
         (yield updateRecord(False, config.directory,
             principal.record.recordType,
@@ -747,24 +748,24 @@
 
 def action_getAutoSchedule(principal):
     autoSchedule = principal.getAutoSchedule()
-    print "Auto-schedule for %s is %s" % (
+    print("Auto-schedule for %s is %s" % (
         prettyPrincipal(principal),
         { True: "true", False: "false" }[autoSchedule],
-    )
+    ))
 
 @inlineCallbacks
 def action_setAutoScheduleMode(principal, autoScheduleMode):
     if principal.record.recordType == "groups":
-        print "Setting auto-schedule mode for %s is not allowed." % (principal,)
+        print("Setting auto-schedule mode for %s is not allowed." % (principal,))
 
     elif principal.record.recordType == "users" and not config.Scheduling.Options.AutoSchedule.AllowUsers:
-        print "Setting auto-schedule mode for %s is not allowed." % (principal,)
+        print("Setting auto-schedule mode for %s is not allowed." % (principal,))
 
     else:
-        print "Setting auto-schedule mode to %s for %s" % (
+        print("Setting auto-schedule mode to %s for %s" % (
             autoScheduleMode,
             prettyPrincipal(principal),
-        )
+        ))
 
         (yield updateRecord(False, config.directory,
             principal.record.recordType,
@@ -779,28 +780,28 @@
     autoScheduleMode = principal.getAutoScheduleMode()
     if not autoScheduleMode:
         autoScheduleMode = "automatic"
-    print "Auto-schedule mode for %s is %s" % (
+    print("Auto-schedule mode for %s is %s" % (
         prettyPrincipal(principal),
         autoScheduleMode,
-    )
+    ))
 
 @inlineCallbacks
 def action_setAutoAcceptGroup(principal, autoAcceptGroup):
     if principal.record.recordType == "groups":
-        print "Setting auto-accept-group for %s is not allowed." % (principal,)
+        print("Setting auto-accept-group for %s is not allowed." % (principal,))
 
     elif principal.record.recordType == "users" and not config.Scheduling.Options.AutoSchedule.AllowUsers:
-        print "Setting auto-accept-group for %s is not allowed." % (principal,)
+        print("Setting auto-accept-group for %s is not allowed." % (principal,))
 
     else:
         groupPrincipal = principalForPrincipalID(autoAcceptGroup)
         if groupPrincipal is None or groupPrincipal.record.recordType != "groups":
-            print "Invalid principal ID: %s" % (autoAcceptGroup,)
+            print("Invalid principal ID: %s" % (autoAcceptGroup,))
         else:
-            print "Setting auto-accept-group to %s for %s" % (
+            print("Setting auto-accept-group to %s for %s" % (
                 prettyPrincipal(groupPrincipal),
                 prettyPrincipal(principal),
-            )
+            ))
 
             (yield updateRecord(False, config.directory,
                 principal.record.recordType,
@@ -818,14 +819,14 @@
         if record is not None:
             groupPrincipal = config.directory.principalCollection.principalForUID(record.uid)
             if groupPrincipal is not None:
-                print "Auto-accept-group for %s is %s" % (
+                print("Auto-accept-group for %s is %s" % (
                     prettyPrincipal(principal),
                     prettyPrincipal(groupPrincipal),
-                )
+                ))
                 return
-        print "Invalid auto-accept-group assigned: %s" % (autoAcceptGroup,)
+        print("Invalid auto-accept-group assigned: %s" % (autoAcceptGroup,))
     else:
-        print "No auto-accept-group assigned to %s" % (prettyPrincipal(principal),)
+        print("No auto-accept-group assigned to %s" % (prettyPrincipal(principal),))
 
 
 def abort(msg, status=1):
@@ -894,10 +895,10 @@
         for record in records]
     results.sort()
     format = "%-22s %-17s %s"
-    print format % ("Full name", "Record name", "UUID")
-    print format % ("---------", "-----------", "----")
+    print(format % ("Full name", "Record name", "UUID"))
+    print(format % ("---------", "-----------", "----"))
     for fullName, shortName, guid in results:
-        print format % (fullName, shortName, guid)
+        print(format % (fullName, shortName, guid))
 
 def prettyPrincipal(principal):
     record = principal.record

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/purge.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/purge.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/purge.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from calendarserver.tap.util import FakeRequest
 from calendarserver.tap.util import getRootResource
@@ -107,19 +108,19 @@
     def usage(cls, e=None):
 
         name = os.path.basename(sys.argv[0])
-        print "usage: %s [options]" % (name,)
-        print ""
-        print "  Remove old events from the calendar server"
-        print ""
-        print "options:"
-        print "  -h --help: print this help and exit"
-        print "  -f --config <path>: Specify caldavd.plist configuration path"
-        print "  -d --days <number>: specify how many days in the past to retain (default=%d)" % (DEFAULT_RETAIN_DAYS,)
-        #print "  -b --batch <number>: number of events to remove in each transaction (default=%d)" % (DEFAULT_BATCH_SIZE,)
-        print "  -n --dry-run: calculate how many events to purge, but do not purge data"
-        print "  -v --verbose: print progress information"
-        print "  -D --debug: debug logging"
-        print ""
+        print("usage: %s [options]" % (name,))
+        print("")
+        print("  Remove old events from the calendar server")
+        print("")
+        print("options:")
+        print("  -h --help: print this help and exit")
+        print("  -f --config <path>: Specify caldavd.plist configuration path")
+        print("  -d --days <number>: specify how many days in the past to retain (default=%d)" % (DEFAULT_RETAIN_DAYS,))
+        #print("  -b --batch <number>: number of events to remove in each transaction (default=%d)" % (DEFAULT_BATCH_SIZE,))
+        print("  -n --dry-run: calculate how many events to purge, but do not purge data")
+        print("  -v --verbose: print progress information")
+        print("  -D --debug: debug logging")
+        print("")
 
         if e:
             sys.stderr.write("%s\n" % (e,))
@@ -164,14 +165,14 @@
                 try:
                     days = int(arg)
                 except ValueError, e:
-                    print "Invalid value for --days: %s" % (arg,)
+                    print("Invalid value for --days: %s" % (arg,))
                     cls.usage(e)
 
             elif opt in ("-b", "--batch"):
                 try:
                     batchSize = int(arg)
                 except ValueError, e:
-                    print "Invalid value for --batch: %s" % (arg,)
+                    print("Invalid value for --batch: %s" % (arg,))
                     cls.usage(e)
 
             elif opt in ("-v", "--verbose"):
@@ -228,21 +229,21 @@
 
         if self.dryrun:
             if self.verbose:
-                print "(Dry run) Searching for old events..."
+                print("(Dry run) Searching for old events...")
             txn = self._store.newTransaction(label="Find old events")
             oldEvents = (yield txn.eventsOlderThan(self.cutoff))
             eventCount = len(oldEvents)
             if self.verbose:
                 if eventCount == 0:
-                    print "No events are older than %s" % (self.cutoff,)
+                    print("No events are older than %s" % (self.cutoff,))
                 elif eventCount == 1:
-                    print "1 event is older than %s" % (self.cutoff,)
+                    print("1 event is older than %s" % (self.cutoff,))
                 else:
-                    print "%d events are older than %s" % (eventCount, self.cutoff)
+                    print("%d events are older than %s" % (eventCount, self.cutoff))
             returnValue(eventCount)
 
         if self.verbose:
-            print "Removing events older than %s..." % (self.cutoff,)
+            print("Removing events older than %s..." % (self.cutoff,))
 
         numEventsRemoved = -1
         totalRemoved = 0
@@ -253,16 +254,16 @@
             if numEventsRemoved:
                 totalRemoved += numEventsRemoved
                 if self.verbose:
-                    print "%d," % (totalRemoved,),
+                    print("%d," % (totalRemoved,),)
 
         if self.verbose:
-            print
+            print("")
             if totalRemoved == 0:
-                print "No events were removed"
+                print("No events were removed")
             elif totalRemoved == 1:
-                print "1 event was removed in total"
+                print("1 event was removed in total")
             else:
-                print "%d events were removed in total" % (totalRemoved,)
+                print("%d events were removed in total" % (totalRemoved,))
 
         returnValue(totalRemoved)
 
@@ -280,20 +281,20 @@
     def usage(cls, e=None):
 
         name = os.path.basename(sys.argv[0])
-        print "usage: %s [options]" % (name,)
-        print ""
-        print "  Remove old or orphaned attachments from the calendar server"
-        print ""
-        print "options:"
-        print "  -h --help: print this help and exit"
-        print "  -f --config <path>: Specify caldavd.plist configuration path"
-        print "  -u --uuid <owner uid>: target a specific user UID"
-        #print "  -b --batch <number>: number of attachments to remove in each transaction (default=%d)" % (DEFAULT_BATCH_SIZE,)
-        print "  -d --days <number>: specify how many days in the past to retain (default=%d) zero means no removal of old attachments" % (DEFAULT_RETAIN_DAYS,)
-        print "  -n --dry-run: calculate how many attachments to purge, but do not purge data"
-        print "  -v --verbose: print progress information"
-        print "  -D --debug: debug logging"
-        print ""
+        print("usage: %s [options]" % (name,))
+        print("")
+        print("  Remove old or orphaned attachments from the calendar server")
+        print("")
+        print("options:")
+        print("  -h --help: print this help and exit")
+        print("  -f --config <path>: Specify caldavd.plist configuration path")
+        print("  -u --uuid <owner uid>: target a specific user UID")
+        #print("  -b --batch <number>: number of attachments to remove in each transaction (default=%d)" % (DEFAULT_BATCH_SIZE,))
+        print("  -d --days <number>: specify how many days in the past to retain (default=%d) zero means no removal of old attachments" % (DEFAULT_RETAIN_DAYS,))
+        print("  -n --dry-run: calculate how many attachments to purge, but do not purge data")
+        print("  -v --verbose: print progress information")
+        print("  -D --debug: debug logging")
+        print("")
 
         if e:
             sys.stderr.write("%s\n" % (e,))
@@ -343,14 +344,14 @@
                 try:
                     days = int(arg)
                 except ValueError, e:
-                    print "Invalid value for --days: %s" % (arg,)
+                    print("Invalid value for --days: %s" % (arg,))
                     cls.usage(e)
 
             elif opt in ("-b", "--batch"):
                 try:
                     batchSize = int(arg)
                 except ValueError, e:
-                    print "Invalid value for --batch: %s" % (arg,)
+                    print("Invalid value for --batch: %s" % (arg,))
                     cls.usage(e)
 
             elif opt in ("-v", "--verbose"):
@@ -438,7 +439,7 @@
     def _orphansDryRun(self):
 
         if self.verbose:
-            print "(Dry run) Searching for orphaned attachments..."
+            print("(Dry run) Searching for orphaned attachments...")
         txn = self._store.newTransaction(label="Find orphaned attachments")
         orphans = (yield txn.orphanedAttachments(self.uuid))
         returnValue(orphans)
@@ -448,7 +449,7 @@
     def _dropboxDryRun(self):
 
         if self.verbose:
-            print "(Dry run) Searching for old dropbox attachments..."
+            print("(Dry run) Searching for old dropbox attachments...")
         txn = self._store.newTransaction(label="Find old dropbox attachments")
         cutoffs = (yield txn.oldDropboxAttachments(self.cutoff, self.uuid))
         yield txn.commit()
@@ -460,7 +461,7 @@
     def _managedDryRun(self):
 
         if self.verbose:
-            print "(Dry run) Searching for old managed attachments..."
+            print("(Dry run) Searching for old managed attachments...")
         txn = self._store.newTransaction(label="Find old managed attachments")
         cutoffs = (yield txn.oldManagedAttachments(self.cutoff, self.uuid))
         yield txn.commit()
@@ -525,8 +526,8 @@
             table.addFooter(("Total:", "",) + tuple(totals))
             total = totals[7]
 
-            print "\n"
-            print "Orphaned/Old Attachments by User:\n"
+            print("\n")
+            print("Orphaned/Old Attachments by User:\n")
             table.printTable()
         else:
             total = sum([x[3] for x in orphans]) + sum([x[3] for x in dropbox]) + sum([x[3] for x in managed])
@@ -538,7 +539,7 @@
     def _orphansPurge(self):
 
         if self.verbose:
-            print "Removing orphaned attachments...",
+            print("Removing orphaned attachments...",)
 
         numOrphansRemoved = -1
         totalRemoved = 0
@@ -549,18 +550,18 @@
             if numOrphansRemoved:
                 totalRemoved += numOrphansRemoved
                 if self.verbose:
-                    print " %d," % (totalRemoved,),
+                    print(" %d," % (totalRemoved,),)
             elif self.verbose:
-                print
+                print("")
 
         if self.verbose:
             if totalRemoved == 0:
-                print "No orphaned attachments were removed"
+                print("No orphaned attachments were removed")
             elif totalRemoved == 1:
-                print "1 orphaned attachment was removed in total"
+                print("1 orphaned attachment was removed in total")
             else:
-                print "%d orphaned attachments were removed in total" % (totalRemoved,)
-            print
+                print("%d orphaned attachments were removed in total" % (totalRemoved,))
+            print("")
 
         returnValue(totalRemoved)
 
@@ -569,7 +570,7 @@
     def _dropboxPurge(self):
 
         if self.verbose:
-            print "Removing old dropbox attachments...",
+            print("Removing old dropbox attachments...",)
 
         numOldRemoved = -1
         totalRemoved = 0
@@ -580,18 +581,18 @@
             if numOldRemoved:
                 totalRemoved += numOldRemoved
                 if self.verbose:
-                    print " %d," % (totalRemoved,),
+                    print(" %d," % (totalRemoved,),)
             elif self.verbose:
-                print
+                print("")
 
         if self.verbose:
             if totalRemoved == 0:
-                print "No old dropbox attachments were removed"
+                print("No old dropbox attachments were removed")
             elif totalRemoved == 1:
-                print "1 old dropbox attachment was removed in total"
+                print("1 old dropbox attachment was removed in total")
             else:
-                print "%d old dropbox attachments were removed in total" % (totalRemoved,)
-            print
+                print("%d old dropbox attachments were removed in total" % (totalRemoved,))
+            print("")
 
         returnValue(totalRemoved)
 
@@ -600,7 +601,7 @@
     def _managedPurge(self):
 
         if self.verbose:
-            print "Removing old managed attachments...",
+            print("Removing old managed attachments...",)
 
         numOldRemoved = -1
         totalRemoved = 0
@@ -611,18 +612,18 @@
             if numOldRemoved:
                 totalRemoved += numOldRemoved
                 if self.verbose:
-                    print " %d," % (totalRemoved,),
+                    print(" %d," % (totalRemoved,),)
             elif self.verbose:
-                print
+                print("")
 
         if self.verbose:
             if totalRemoved == 0:
-                print "No old managed attachments were removed"
+                print("No old managed attachments were removed")
             elif totalRemoved == 1:
-                print "1 old managed attachment was removed in total"
+                print("1 old managed attachment was removed in total")
             else:
-                print "%d old managed attachments were removed in total" % (totalRemoved,)
-            print
+                print("%d old managed attachments were removed in total" % (totalRemoved,))
+            print("")
 
         returnValue(totalRemoved)
 
@@ -644,18 +645,18 @@
     def usage(cls, e=None):
 
         name = os.path.basename(sys.argv[0])
-        print "usage: %s [options]" % (name,)
-        print ""
-        print "  Remove a principal's events and contacts from the calendar server"
-        print ""
-        print "options:"
-        print "  -c --completely: By default, only future events are canceled; this option cancels all events"
-        print "  -h --help: print this help and exit"
-        print "  -f --config <path>: Specify caldavd.plist configuration path"
-        print "  -n --dry-run: calculate how many events and contacts to purge, but do not purge data"
-        print "  -v --verbose: print progress information"
-        print "  -D --debug: debug logging"
-        print ""
+        print("usage: %s [options]" % (name,))
+        print("")
+        print("  Remove a principal's events and contacts from the calendar server")
+        print("")
+        print("options:")
+        print("  -c --completely: By default, only future events are canceled; this option cancels all events")
+        print("  -h --help: print this help and exit")
+        print("  -f --config <path>: Specify caldavd.plist configuration path")
+        print("  -n --dry-run: calculate how many events and contacts to purge, but do not purge data")
+        print("  -v --verbose: print progress information")
+        print("  -D --debug: debug logging")
+        print("")
 
         if e:
             sys.stderr.write("%s\n" % (e,))
@@ -769,9 +770,9 @@
         if self.verbose:
             amount = "%d event%s" % (total, "s" if total > 1 else "")
             if self.dryrun:
-                print "Would have modified or deleted %s" % (amount,)
+                print("Would have modified or deleted %s" % (amount,))
             else:
-                print "Modified or deleted %s" % (amount,)
+                print("Modified or deleted %s" % (amount,))
 
         returnValue((total, allAssignments,))
 
@@ -819,9 +820,9 @@
             for child in children:
                 if self.verbose:
                     if self.dryrun:
-                        print "Would unshare: %s" % (child.name(),)
+                        print("Would unshare: %s" % (child.name(),))
                     else:
-                        print "Unsharing: %s" % (child.name(),)
+                        print("Unsharing: %s" % (child.name(),))
                 if not self.dryrun:
                     (yield child.unshare())
 
@@ -895,9 +896,9 @@
                                 )
                                 if self.verbose:
                                     if self.dryrun:
-                                        print "Would modify: %s" % (uri,)
+                                        print("Would modify: %s" % (uri,))
                                     else:
-                                        print "Modifying: %s" % (uri,)
+                                        print("Modifying: %s" % (uri,))
                                 if not self.dryrun:
                                     result = (yield storer.run())
 
@@ -906,37 +907,37 @@
                                 request._rememberResource(childResource, uri)
                                 if self.verbose:
                                     if self.dryrun:
-                                        print "Would delete: %s" % (uri,)
+                                        print("Would delete: %s" % (uri,))
                                     else:
-                                        print "Deleting: %s" % (uri,)
+                                        print("Deleting: %s" % (uri,))
                                 if not self.dryrun:
                                     retry = False
                                     try:
                                         result = (yield childResource.storeRemove(request, self.doimplicit, uri))
                                         if result != NO_CONTENT:
-                                            print "Error deleting %s/%s/%s: %s" % (uid,
-                                                collName, childName, result)
+                                            print("Error deleting %s/%s/%s: %s" % (uid,
+                                                collName, childName, result))
                                             retry = True
                                         else:
                                             incrementCount = True
 
                                     except Exception, e:
-                                        print "Exception deleting %s/%s/%s: %s" % (uid,
-                                            collName, childName, str(e))
+                                        print("Exception deleting %s/%s/%s: %s" % (uid,
+                                            collName, childName, str(e)))
                                         retry = True
 
                                     if retry and self.doimplicit:
                                         # Try again with implicit scheduling off
-                                        print "Retrying deletion of %s/%s/%s with implicit scheduling turned off" % (uid, collName, childName)
+                                        print("Retrying deletion of %s/%s/%s with implicit scheduling turned off" % (uid, collName, childName))
                                         try:
                                             result = (yield childResource.storeRemove(request, False, uri))
                                             if result != NO_CONTENT:
-                                                print "Error deleting %s/%s/%s: %s" % (uid,
-                                                    collName, childName, result)
+                                                print("Error deleting %s/%s/%s: %s" % (uid,
+                                                    collName, childName, result))
                                             else:
                                                 incrementCount = True
                                         except Exception, e:
-                                            print "Still couldn't delete %s/%s/%s even with implicit scheduling turned off: %s" % (uid, collName, childName, str(e))
+                                            print("Still couldn't delete %s/%s/%s even with implicit scheduling turned off: %s" % (uid, collName, childName, str(e)))
 
                                 if incrementCount:
                                     count += 1
@@ -968,18 +969,18 @@
                         calendarName = calColl.name()
                         if self.verbose:
                             if self.dryrun:
-                                print "Would delete calendar: %s" % (calendarName,)
+                                print("Would delete calendar: %s" % (calendarName,))
                             else:
-                                print "Deleting calendar: %s" % (calendarName,)
+                                print("Deleting calendar: %s" % (calendarName,))
                         if not self.dryrun:
                             (yield storeCalHome.removeChildWithName(calendarName))
 
                 if not remainingCalendars:
                     if self.verbose:
                         if self.dryrun:
-                            print "Would delete calendar home"
+                            print("Would delete calendar home")
                         else:
-                            print "Deleting calendar home"
+                            print("Deleting calendar home")
                     if not self.dryrun:
                         (yield storeCalHome.remove())
 
@@ -992,27 +993,27 @@
                         if self.verbose:
                             uri = "/addressbooks/__uids__/%s/%s/%s" % (uid, abColl.name(), cardName)
                             if self.dryrun:
-                                print "Would delete: %s" % (uri,)
+                                print("Would delete: %s" % (uri,))
                             else:
-                                print "Deleting: %s" % (uri,)
+                                print("Deleting: %s" % (uri,))
                         if not self.dryrun:
                             (yield abColl.removeObjectResourceWithName(cardName))
                         count += 1
                     if self.verbose:
                         abName = abColl.name()
                         if self.dryrun:
-                            print "Would delete addressbook: %s" % (abName,)
+                            print("Would delete addressbook: %s" % (abName,))
                         else:
-                            print "Deleting addressbook: %s" % (abName,)
+                            print("Deleting addressbook: %s" % (abName,))
                     if not self.dryrun:
                         # Also remove the addressbook collection itself
                         (yield storeAbHome.removeChildWithName(abColl.name()))
 
                 if self.verbose:
                     if self.dryrun:
-                        print "Would delete addressbook home"
+                        print("Would delete addressbook home")
                     else:
-                        print "Deleting addressbook home"
+                        print("Deleting addressbook home")
                 if not self.dryrun:
                     (yield storeAbHome.remove())
 
@@ -1026,7 +1027,7 @@
 
         if self.proxies and not self.dryrun:
             if self.verbose:
-                print "Deleting any proxy assignments"
+                print("Deleting any proxy assignments")
             assignments = (yield self._purgeProxyAssignments(principal))
 
         returnValue((count, assignments))

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/push.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/push.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/push.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from calendarserver.tap.util import getRootResource
 from calendarserver.tools.cmdline import utilityMain
@@ -33,15 +34,15 @@
 def usage(e=None):
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] [user ...]" % (name,)
-    print ""
-    print "  Display Apple Push Notification subscriptions"
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -f --config <path>: Specify caldavd.plist configuration path"
-    print "  -D --debug: debug logging"
-    print ""
+    print("usage: %s [options] [user ...]" % (name,))
+    print("")
+    print("  Display Apple Push Notification subscriptions")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -f --config <path>: Specify caldavd.plist configuration path")
+    print("  -D --debug: debug logging")
+    print("")
 
     if e:
         sys.stderr.write("%s\n" % (e,))
@@ -157,7 +158,7 @@
         print
         record = directory.recordWithShortName("users", user)
         if record is not None:
-            print "User %s (%s)..." % (user, record.uid)
+            print("User %s (%s)..." % (user, record.uid))
             txn = store.newTransaction(label="Display APN Subscriptions")
             subscriptions = (yield txn.apnSubscriptionsBySubscriber(record.uid))
             (yield txn.commit())
@@ -180,15 +181,20 @@
                     record = directory.recordWithUID(uid)
                     user = record.shortNames[0]
                     if collection:
-                        print "...is subscribed to a share from %s's %s home" % (user, resource),
+                        print("...is subscribed to a share from %s's %s home" % (user, resource),)
                     else:
-                        print "...is subscribed to %s's %s home" % (user, resource),
-                        # print "   (key: %s)\n" % (key,)
-                    print "with %d device(s):" % (len(tokens),)
+                        print("...is subscribed to %s's %s home" % (user, resource),)
+                        # print("   (key: %s)\n" % (key,))
+                    print("with %d device(s):" % (len(tokens),))
                     for token, timestamp, userAgent, ipAddr in tokens:
-                        print " %s\n   '%s' from %s\n   %s" % (token, userAgent, ipAddr,
-                            time.strftime("on %a, %d %b %Y at %H:%M:%S %z(%Z)", time.localtime(timestamp)))
+                        print(" %s\n   '%s' from %s\n   %s" % (
+                            token, userAgent, ipAddr,
+                            time.strftime(
+                                "on %a, %d %b %Y at %H:%M:%S %z(%Z)",
+                                time.localtime(timestamp)
+                            )
+                        ))
             else:
-                print " ...is not subscribed to anything."
+                print(" ...is not subscribed to anything.")
         else:
-            print "User %s not found" % (user,)
+            print("User %s not found" % (user,))

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/resources.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/resources.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/resources.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from calendarserver.tools.util import loadConfig, getDirectory, setupMemcached, checkDirectory
 from getopt import getopt, GetoptError
@@ -39,15 +40,15 @@
 def usage():
 
     name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] " % (name,)
-    print ""
-    print "  Migrates resources and locations from OD to Calendar Server"
-    print ""
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -f --config <path>: Specify caldavd.plist configuration path"
-    print "  -v --verbose: print debugging information"
-    print ""
+    print("usage: %s [options] " % (name,))
+    print("")
+    print("  Migrates resources and locations from OD to Calendar Server")
+    print("")
+    print("options:")
+    print("  -h --help: print this help and exit")
+    print("  -f --config <path>: Specify caldavd.plist configuration path")
+    print("  -v --verbose: print debugging information")
+    print("")
 
     sys.exit(0)
 
@@ -175,7 +176,7 @@
     ]
 
     if verbose:
-        print "Querying for all %s records" % (recordType,)
+        print("Querying for all %s records" % (recordType,))
 
     results = list(sourceService.odModule.listAllRecordsWithAttributes_list(
         sourceService.directory,
@@ -184,7 +185,7 @@
     ))
 
     if verbose:
-        print "Found %d records" % (len(results),)
+        print("Found %d records" % (len(results),))
 
     return results
 
@@ -210,7 +211,7 @@
                 record = destService.recordWithGUID(guid)
                 if record is None:
                     if verbose:
-                        print "Migrating %s (%s)" % (fullName, recordType)
+                        print("Migrating %s (%s)" % (fullName, recordType))
 
                     if autoSchedules is not None:
                         autoSchedule = autoSchedules.get(guid, 1)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/shell/terminal.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/shell/terminal.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/shell/terminal.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 Interactive shell for terminals.
@@ -56,8 +57,8 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
     try:
         ShellOptions().opt_help()
     except SystemExit:
@@ -340,7 +341,7 @@
 
         if tokens:
             cmd = tokens.pop(0)
-            #print "Arguments: %r" % (tokens,)
+            #print("Arguments: %r" % (tokens,))
 
             m = getattr(self.commands, "cmd_%s" % (cmd,), None)
             if m:
@@ -410,6 +411,6 @@
         directory = getDirectory()
         return ShellService(store, directory, options, reactor, config)
 
-    print "Initializing shell..."
+    print("Initializing shell...")
 
     utilityMain(options["config"], makeService, reactor)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_calverify.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_calverify.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_calverify.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 Tests for calendarserver.tools.calverify
@@ -20,7 +21,8 @@
 
 from StringIO import StringIO
 from calendarserver.tap.util import getRootResource
-from calendarserver.tools.calverify import CalVerifyService
+from calendarserver.tools.calverify import BadDataService, \
+    SchedulingMismatchService, DoubleBookingService
 from pycalendar.datetime import PyCalendarDateTime
 from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks, returnValue
@@ -530,6 +532,7 @@
 
         options = {
             "ical": True,
+            "fix": False,
             "nobase64": False,
             "verbose": False,
             "uid": "",
@@ -537,9 +540,9 @@
             "tzid": "",
         }
         output = StringIO()
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
+        calverify = BadDataService(self._sqlCalendarStore, options, output, reactor, config)
         calverify.emailDomain = "example.com"
-        yield calverify.doScan(True, False, False)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 13)
         self.verifyResultsByUID(calverify.results["Bad iCalendar data"], set((
@@ -572,6 +575,7 @@
 
         options = {
             "ical": True,
+            "fix": True,
             "nobase64": False,
             "verbose": False,
             "uid": "",
@@ -583,9 +587,9 @@
         # Do fix
         self.patch(config.Scheduling.Options, "PrincipalHostAliases", "demo.com")
         self.patch(config, "HTTPPort", 8008)
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
+        calverify = BadDataService(self._sqlCalendarStore, options, output, reactor, config)
         calverify.emailDomain = "example.com"
-        yield calverify.doScan(True, False, True)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 13)
         self.verifyResultsByUID(calverify.results["Bad iCalendar data"], set((
@@ -603,9 +607,10 @@
         )))
 
         # Do scan
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
+        options["fix"] = False
+        calverify = BadDataService(self._sqlCalendarStore, options, output, reactor, config)
         calverify.emailDomain = "example.com"
-        yield calverify.doScan(True, False, False)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 13)
         self.verifyResultsByUID(calverify.results["Bad iCalendar data"], set((
@@ -640,6 +645,7 @@
 
         options = {
             "ical": False,
+            "fix": False,
             "badcua": True,
             "nobase64": False,
             "verbose": False,
@@ -648,9 +654,9 @@
             "tzid": "",
         }
         output = StringIO()
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
+        calverify = BadDataService(self._sqlCalendarStore, options, output, reactor, config)
         calverify.emailDomain = "example.com"
-        yield calverify.doScan(True, False, False)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 13)
         self.verifyResultsByUID(calverify.results["Bad iCalendar data"], set((
@@ -679,6 +685,7 @@
 
         options = {
             "ical": False,
+            "fix": True,
             "badcua": True,
             "nobase64": False,
             "verbose": False,
@@ -691,9 +698,9 @@
         # Do fix
         self.patch(config.Scheduling.Options, "PrincipalHostAliases", "demo.com")
         self.patch(config, "HTTPPort", 8008)
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
+        calverify = BadDataService(self._sqlCalendarStore, options, output, reactor, config)
         calverify.emailDomain = "example.com"
-        yield calverify.doScan(True, False, True)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 13)
         self.verifyResultsByUID(calverify.results["Bad iCalendar data"], set((
@@ -707,9 +714,10 @@
         )))
 
         # Do scan
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
+        options["fix"] = False
+        calverify = BadDataService(self._sqlCalendarStore, options, output, reactor, config)
         calverify.emailDomain = "example.com"
-        yield calverify.doScan(True, False, False)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 13)
         self.verifyResultsByUID(calverify.results["Bad iCalendar data"], set((
@@ -907,7 +915,7 @@
             "uuid": "",
             "tzid": "",
         }
-        calverifyNo64 = CalVerifyService(self._sqlCalendarStore, optionsNo64, StringIO(), reactor, config)
+        calverifyNo64 = BadDataService(self._sqlCalendarStore, optionsNo64, StringIO(), reactor, config)
         calverifyNo64.emailDomain = "example.com"
 
         options64 = {
@@ -918,7 +926,7 @@
             "uuid": "",
             "tzid": "",
         }
-        calverify64 = CalVerifyService(self._sqlCalendarStore, options64, StringIO(), reactor, config)
+        calverify64 = BadDataService(self._sqlCalendarStore, options64, StringIO(), reactor, config)
         calverify64.emailDomain = "example.com"
 
         for bad, oknobase64, okbase64 in data:
@@ -1467,15 +1475,17 @@
             "badcua": False,
             "mismatch": True,
             "nobase64": False,
+            "fix": False,
             "verbose": False,
             "details": False,
             "uid": "",
             "uuid": "",
             "tzid": "",
+            "start": PyCalendarDateTime(now, 1, 1, 0, 0, 0),
         }
         output = StringIO()
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
-        yield calverify.doScan(False, True, False, start=PyCalendarDateTime(now, 1, 1, 0, 0, 0))
+        calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 17)
         self.assertEqual(calverify.results["Missing Attendee"], set((
@@ -1505,7 +1515,7 @@
         self.assertTrue("Fix remove" not in calverify.results)
         self.assertTrue("Fix remove" not in calverify.results)
         self.assertTrue("Fix failures" not in calverify.results)
-        self.assertTrue("Fixed Auto-Accepts" not in calverify.results)
+        self.assertTrue("Auto-Accepts" not in calverify.results)
 
         sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
         sync_token_new2 = (yield (yield self.calendarUnderTest(self.uuid2)).syncToken())
@@ -1532,15 +1542,17 @@
             "badcua": False,
             "mismatch": True,
             "nobase64": False,
+            "fix": True,
             "verbose": False,
             "details": False,
             "uid": "",
             "uuid": "",
             "tzid": "",
+            "start": PyCalendarDateTime(now, 1, 1, 0, 0, 0),
         }
         output = StringIO()
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
-        yield calverify.doScan(False, True, True, start=PyCalendarDateTime(now, 1, 1, 0, 0, 0))
+        calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 17)
         self.assertEqual(calverify.results["Missing Attendee"], set((
@@ -1604,7 +1616,7 @@
         self.assertEqual(obj, None)
 
         self.assertEqual(calverify.results["Fix failures"], 0)
-        self.assertEqual(calverify.results["Fixed Auto-Accepts"], [])
+        self.assertEqual(calverify.results["Auto-Accepts"], [])
 
         sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
         sync_token_new2 = (yield (yield self.calendarUnderTest(self.uuid2)).syncToken())
@@ -1615,8 +1627,9 @@
 
         # Re-scan after changes to make sure there are no errors
         self.commit()
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
-        yield calverify.doScan(False, True, False, start=PyCalendarDateTime(now, 1, 1, 0, 0, 0))
+        options["fix"] = False
+        calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 14)
         self.assertTrue("Missing Attendee" not in calverify.results)
@@ -1627,7 +1640,7 @@
         self.assertTrue("Fix add inbox" not in calverify.results)
         self.assertTrue("Fix remove" not in calverify.results)
         self.assertTrue("Fix failures" not in calverify.results)
-        self.assertTrue("Fixed Auto-Accepts" not in calverify.results)
+        self.assertTrue("Auto-Accepts" not in calverify.results)
 
 
 
@@ -1738,15 +1751,17 @@
             "badcua": False,
             "mismatch": True,
             "nobase64": False,
+            "fix": False,
             "verbose": False,
             "details": False,
             "uid": "",
             "uuid": "",
             "tzid": "",
+            "start": PyCalendarDateTime(now, 1, 1, 0, 0, 0),
         }
         output = StringIO()
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
-        yield calverify.doScan(False, True, False, start=PyCalendarDateTime(now, 1, 1, 0, 0, 0))
+        calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 3)
         self.assertEqual(calverify.results["Missing Attendee"], set((
@@ -1763,7 +1778,7 @@
         self.assertTrue("Fix add inbox" not in calverify.results)
         self.assertTrue("Fix remove" not in calverify.results)
         self.assertTrue("Fix failures" not in calverify.results)
-        self.assertTrue("Fixed Auto-Accepts" not in calverify.results)
+        self.assertTrue("Auto-Accepts" not in calverify.results)
 
         sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
         sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
@@ -1787,15 +1802,17 @@
             "badcua": False,
             "mismatch": True,
             "nobase64": False,
+            "fix": True,
             "verbose": False,
             "details": False,
             "uid": "",
             "uuid": "",
             "tzid": "",
+            "start": PyCalendarDateTime(now, 1, 1, 0, 0, 0),
         }
         output = StringIO()
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
-        yield calverify.doScan(False, True, True, start=PyCalendarDateTime(now, 1, 1, 0, 0, 0))
+        calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 3)
         self.assertEqual(calverify.results["Missing Attendee"], set((
@@ -1823,7 +1840,7 @@
         self.assertTrue("Fix remove" not in calverify.results)
 
         self.assertEqual(calverify.results["Fix failures"], 0)
-        testResults = sorted(calverify.results["Fixed Auto-Accepts"], key=lambda x: x["uid"])
+        testResults = sorted(calverify.results["Auto-Accepts"], key=lambda x: x["uid"])
         self.assertEqual(testResults[0]["path"], "/calendars/__uids__/%s/calendar/mismatched_attendee.ics" % self.uuidl1)
         self.assertEqual(testResults[0]["uid"], "MISMATCH_ATTENDEE_ICS")
         self.assertEqual(testResults[0]["start"].getText(), "%s0307T031500" % (now,))
@@ -1837,8 +1854,9 @@
 
         # Re-scan after changes to make sure there are no errors
         self.commit()
-        calverify = CalVerifyService(self._sqlCalendarStore, options, output, reactor, config)
-        yield calverify.doScan(False, True, False, start=PyCalendarDateTime(now, 1, 1, 0, 0, 0))
+        options["fix"] = False
+        calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
 
         self.assertEqual(calverify.results["Number of events to process"], 4)
         self.assertTrue("Missing Attendee" not in calverify.results)
@@ -1849,4 +1867,721 @@
         self.assertTrue("Fix add inbox" not in calverify.results)
         self.assertTrue("Fix remove" not in calverify.results)
         self.assertTrue("Fix failures" not in calverify.results)
-        self.assertTrue("Fixed Auto-Accepts" not in calverify.results)
+        self.assertTrue("Auto-Accepts" not in calverify.results)
+
+
+
+class CalVerifyMismatchTestsUUID(CalVerifyMismatchTestsBase):
+    """
+    Tests calverify for iCalendar mismatch problems for auto-accept attendees.
+    """
+
+    # Organizer has event, attendee do not
+    MISSING_ATTENDEE_1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:MISSING_ATTENDEE_ICS
+DTEND:%(year)s0307T151500Z
+TRANSP:OPAQUE
+SUMMARY:Ancient event
+DTSTART:%(year)s0307T111500Z
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    # Attendee partstat mismatch
+    MISMATCH_ATTENDEE_1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:MISMATCH_ATTENDEE_ICS
+DTEND:%(year)s0307T151500Z
+TRANSP:OPAQUE
+SUMMARY:Ancient event
+DTSTART:%(year)s0307T111500Z
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE;PARTSTAT=ACCEPTED:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE;PARTSTAT=NEEDS-ACTION:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    MISMATCH_ATTENDEE_L1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:MISMATCH_ATTENDEE_ICS
+DTEND:%(year)s0307T151500Z
+TRANSP:OPAQUE
+SUMMARY:Ancient event
+DTSTART:%(year)s0307T111500Z
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE;PARTSTAT=ACCEPTED:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE;PARTSTAT=ACCEPTED:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    requirements = {
+        CalVerifyMismatchTestsBase.uuid1 : {
+            "calendar" : {
+                 "missing_attendee.ics"      : (MISSING_ATTENDEE_1_ICS, CalVerifyMismatchTestsBase.metadata,),
+                 "mismatched_attendee.ics"   : (MISMATCH_ATTENDEE_1_ICS, CalVerifyMismatchTestsBase.metadata,),
+           },
+           "inbox" : {},
+        },
+        CalVerifyMismatchTestsBase.uuid2 : {
+            "calendar" : {},
+            "inbox" : {},
+        },
+        CalVerifyMismatchTestsBase.uuid3 : {
+            "calendar" : {},
+            "inbox" : {},
+        },
+        CalVerifyMismatchTestsBase.uuidl1 : {
+            "calendar" : {
+                "mismatched_attendee.ics"   : (MISMATCH_ATTENDEE_L1_ICS, CalVerifyMismatchTestsBase.metadata,),
+            },
+            "inbox" : {},
+        },
+    }
+
+    @inlineCallbacks
+    def test_scanMismatchOnly(self):
+        """
+        CalVerifyService.doScan without fix for mismatches. Make sure it detects
+        as much as it can. Make sure sync-token is not changed.
+        """
+
+        sync_token_old1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
+        sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+        self.commit()
+
+        options = {
+            "ical": False,
+            "badcua": False,
+            "mismatch": True,
+            "nobase64": False,
+            "fix": False,
+            "verbose": False,
+            "details": False,
+            "uid": "",
+            "uuid": CalVerifyMismatchTestsBase.uuidl1,
+            "tzid": "",
+            "start": PyCalendarDateTime(now, 1, 1, 0, 0, 0),
+        }
+        output = StringIO()
+        calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
+
+        self.assertEqual(calverify.results["Number of events to process"], 2)
+        self.assertTrue("Missing Attendee" not in calverify.results)
+        self.assertEqual(calverify.results["Mismatch Attendee"], set((
+            ("MISMATCH_ATTENDEE_ICS", self.uuid1, self.uuidl1,),
+        )))
+        self.assertTrue("Missing Organizer" not in calverify.results)
+        self.assertTrue("Mismatch Organizer" not in calverify.results)
+
+        self.assertTrue("Fix change event" not in calverify.results)
+        self.assertTrue("Fix add event" not in calverify.results)
+        self.assertTrue("Fix add inbox" not in calverify.results)
+        self.assertTrue("Fix remove" not in calverify.results)
+        self.assertTrue("Fix failures" not in calverify.results)
+        self.assertTrue("Auto-Accepts" not in calverify.results)
+
+        sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
+        sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+        self.assertEqual(sync_token_old1, sync_token_new1)
+        self.assertEqual(sync_token_oldl1, sync_token_newl1)
+
+
+    @inlineCallbacks
+    def test_fixMismatch(self):
+        """
+        CalVerifyService.doScan with fix for mismatches. Make sure it detects
+        and fixes as much as it can. Make sure sync-token is not changed.
+        """
+
+        sync_token_old1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
+        sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+        self.commit()
+
+        options = {
+            "ical": False,
+            "badcua": False,
+            "mismatch": True,
+            "nobase64": False,
+            "fix": True,
+            "verbose": False,
+            "details": False,
+            "uid": "",
+            "uuid": CalVerifyMismatchTestsBase.uuidl1,
+            "tzid": "",
+            "start": PyCalendarDateTime(now, 1, 1, 0, 0, 0),
+        }
+        output = StringIO()
+        calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
+
+        self.assertEqual(calverify.results["Number of events to process"], 2)
+        self.assertTrue("Missing Attendee" not in calverify.results)
+        self.assertEqual(calverify.results["Mismatch Attendee"], set((
+            ("MISMATCH_ATTENDEE_ICS", self.uuid1, self.uuidl1,),
+        )))
+        self.assertTrue("Missing Organizer" not in calverify.results)
+        self.assertTrue("Mismatch Organizer" not in calverify.results)
+
+        self.assertEqual(calverify.results["Fix change event"], set((
+            (self.uuidl1, "calendar", "MISMATCH_ATTENDEE_ICS",),
+        )))
+
+        self.assertTrue("Fix add event" not in calverify.results)
+
+        self.assertEqual(calverify.results["Fix add inbox"], set((
+            (self.uuidl1, "MISMATCH_ATTENDEE_ICS",),
+        )))
+
+        self.assertTrue("Fix remove" not in calverify.results)
+
+        self.assertEqual(calverify.results["Fix failures"], 0)
+        testResults = sorted(calverify.results["Auto-Accepts"], key=lambda x: x["uid"])
+        self.assertEqual(testResults[0]["path"], "/calendars/__uids__/%s/calendar/mismatched_attendee.ics" % self.uuidl1)
+        self.assertEqual(testResults[0]["uid"], "MISMATCH_ATTENDEE_ICS")
+        self.assertEqual(testResults[0]["start"].getText(), "%s0307T031500" % (now,))
+
+        sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
+        sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+        self.assertEqual(sync_token_old1, sync_token_new1)
+        self.assertNotEqual(sync_token_oldl1, sync_token_newl1)
+
+        # Re-scan after changes to make sure there are no errors
+        self.commit()
+        options["fix"] = False
+        options["uuid"] = CalVerifyMismatchTestsBase.uuidl1
+        calverify = SchedulingMismatchService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
+
+        self.assertEqual(calverify.results["Number of events to process"], 2)
+        self.assertTrue("Missing Attendee" not in calverify.results)
+        self.assertTrue("Mismatch Attendee" not in calverify.results)
+        self.assertTrue("Missing Organizer" not in calverify.results)
+        self.assertTrue("Mismatch Organizer" not in calverify.results)
+        self.assertTrue("Fix add event" not in calverify.results)
+        self.assertTrue("Fix add inbox" not in calverify.results)
+        self.assertTrue("Fix remove" not in calverify.results)
+        self.assertTrue("Fix failures" not in calverify.results)
+        self.assertTrue("Auto-Accepts" not in calverify.results)
+
+
+
+class CalVerifyDoubleBooked(CalVerifyMismatchTestsBase):
+    """
+    Tests calverify for double-bookings.
+    """
+
+    # No overlap
+    INVITE_NO_OVERLAP_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_OVERLAP_ICS
+DTSTART:%(year)s0307T100000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    # Two overlapping
+    INVITE_NO_OVERLAP1_1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP1_1_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_OVERLAP1_1_ICS
+DTSTART:%(year)s0307T110000Z
+DURATION:PT2H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    INVITE_NO_OVERLAP1_2_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP1_2_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_OVERLAP1_2_ICS
+DTSTART:%(year)s0307T120000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    # Two overlapping with one transparent
+    INVITE_NO_OVERLAP2_1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP2_1_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_OVERLAP2_1_ICS
+DTSTART:%(year)s0307T140000Z
+DURATION:PT2H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    INVITE_NO_OVERLAP2_2_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP2_2_ICS
+SUMMARY:INVITE_NO_OVERLAP2_2_ICS
+DTSTART:%(year)s0307T150000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    # Two overlapping with one cancelled
+    INVITE_NO_OVERLAP3_1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP3_1_ICS
+TRANSP:OPAQUE
+SUMMARY:Ancient event
+DTSTART:%(year)s0307T170000Z
+DURATION:PT2H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    INVITE_NO_OVERLAP3_2_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP3_2_ICS
+SUMMARY:INVITE_NO_OVERLAP3_2_ICS
+DTSTART:%(year)s0307T180000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+STATUS:CANCELLED
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    # Two overlapping recurring
+    INVITE_NO_OVERLAP4_1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP4_1_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_OVERLAP4_1_ICS
+DTSTART:%(year)s0308T120000Z
+DURATION:PT2H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+RRULE:FREQ=DAILY;COUNT=3
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    INVITE_NO_OVERLAP4_2_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP4_2_ICS
+SUMMARY:INVITE_NO_OVERLAP4_2_ICS
+DTSTART:%(year)s0309T120000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+RRULE:FREQ=DAILY;COUNT=2
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    # Two overlapping on one recurrence instance
+    INVITE_NO_OVERLAP5_1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP5_1_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_OVERLAP5_1_ICS
+DTSTART:%(year)s0312T120000Z
+DURATION:PT2H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+RRULE:FREQ=DAILY;COUNT=3
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    INVITE_NO_OVERLAP5_2_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP5_2_ICS
+SUMMARY:INVITE_NO_OVERLAP5_2_ICS
+DTSTART:%(year)s0313T140000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+RRULE:FREQ=DAILY;COUNT=2
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP5_2_ICS
+SUMMARY:INVITE_NO_OVERLAP5_2_ICS
+RECURRENCE-ID:%(year)s0314T140000Z
+DTSTART:%(year)s0314T130000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    # Two not overlapping - one all-day
+    INVITE_NO_OVERLAP6_1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:America/Los_Angeles
+BEGIN:DAYLIGHT
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
+TZNAME:PDT
+TZOFFSETFROM:-0800
+TZOFFSETTO:-0700
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
+TZNAME:PST
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0800
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP6_1_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_OVERLAP6_1_ICS
+DTSTART;TZID=America/Los_Angeles:%(year)s0320T200000
+DURATION:PT2H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    INVITE_NO_OVERLAP6_2_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP6_2_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_OVERLAP6_2_ICS
+DTSTART;VALUE=DATE:%(year)s0321
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    # Two overlapping - same organizer and summary
+    INVITE_NO_OVERLAP7_1_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP7_1_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_OVERLAP7_1_ICS
+DTSTART:%(year)s0323T110000Z
+DURATION:PT2H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    INVITE_NO_OVERLAP7_2_ICS = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.1//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20100303T181216Z
+UID:INVITE_NO_OVERLAP7_2_ICS
+TRANSP:OPAQUE
+SUMMARY:INVITE_NO_OVERLAP7_1_ICS
+DTSTART:%(year)s0323T120000Z
+DURATION:PT1H
+DTSTAMP:20100303T181220Z
+SEQUENCE:2
+ORGANIZER:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0
+ATTENDEE:urn:uuid:75EA36BE-F71B-40F9-81F9-CF59BF40CA8F
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n") % {"year": now}
+
+    allEvents = {
+        "invite1.ics"      : (INVITE_NO_OVERLAP_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite2.ics"      : (INVITE_NO_OVERLAP1_1_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite3.ics"      : (INVITE_NO_OVERLAP1_2_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite4.ics"      : (INVITE_NO_OVERLAP2_1_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite5.ics"      : (INVITE_NO_OVERLAP2_2_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite6.ics"      : (INVITE_NO_OVERLAP3_1_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite7.ics"      : (INVITE_NO_OVERLAP3_2_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite8.ics"      : (INVITE_NO_OVERLAP4_1_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite9.ics"      : (INVITE_NO_OVERLAP4_2_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite10.ics"     : (INVITE_NO_OVERLAP5_1_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite11.ics"     : (INVITE_NO_OVERLAP5_2_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite12.ics"     : (INVITE_NO_OVERLAP6_1_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite13.ics"     : (INVITE_NO_OVERLAP6_2_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite14.ics"     : (INVITE_NO_OVERLAP7_1_ICS, CalVerifyMismatchTestsBase.metadata,),
+        "invite15.ics"     : (INVITE_NO_OVERLAP7_2_ICS, CalVerifyMismatchTestsBase.metadata,),
+    }
+
+    requirements = {
+        CalVerifyMismatchTestsBase.uuid1 : {
+            "calendar" : allEvents,
+            "inbox" : {},
+        },
+        CalVerifyMismatchTestsBase.uuid2 : {
+            "calendar" : {},
+            "inbox" : {},
+        },
+        CalVerifyMismatchTestsBase.uuid3 : {
+            "calendar" : {},
+            "inbox" : {},
+        },
+        CalVerifyMismatchTestsBase.uuidl1 : {
+            "calendar" : allEvents,
+            "inbox" : {},
+        },
+    }
+
+    @inlineCallbacks
+    def test_scanDoubleBookingOnly(self):
+        """
+        CalVerifyService.doScan without fix for mismatches. Make sure it detects
+        as much as it can. Make sure sync-token is not changed.
+        """
+
+        sync_token_old1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
+        sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+        self.commit()
+
+        options = {
+            "ical": False,
+            "badcua": False,
+            "mismatch": False,
+            "nobase64": False,
+            "double": True,
+            "fix": False,
+            "verbose": False,
+            "details": False,
+            "summary": False,
+            "days": 365,
+            "uid": "",
+            "uuid": self.uuidl1,
+            "tzid": "utc",
+            "start": PyCalendarDateTime(now, 1, 1, 0, 0, 0),
+        }
+        output = StringIO()
+        calverify = DoubleBookingService(self._sqlCalendarStore, options, output, reactor, config)
+        yield calverify.doAction()
+
+        self.assertEqual(calverify.results["Number of events to process"], len(self.requirements[CalVerifyMismatchTestsBase.uuidl1]["calendar"]))
+        self.assertEqual(
+            [(sorted((i.uid1, i.uid2,)), str(i.start),) for i in calverify.results["Double-bookings"]],
+            [
+                (["INVITE_NO_OVERLAP1_1_ICS", "INVITE_NO_OVERLAP1_2_ICS"], "%(year)s0307T120000Z" % {"year": now}),
+                (["INVITE_NO_OVERLAP4_1_ICS", "INVITE_NO_OVERLAP4_2_ICS"], "%(year)s0309T120000Z" % {"year": now}),
+                (["INVITE_NO_OVERLAP4_1_ICS", "INVITE_NO_OVERLAP4_2_ICS"], "%(year)s0310T120000Z" % {"year": now}),
+                (["INVITE_NO_OVERLAP5_1_ICS", "INVITE_NO_OVERLAP5_2_ICS"], "%(year)s0314T130000Z" % {"year": now}),
+            ],
+        )
+        self.assertEqual(calverify.results["Number of double-bookings"], 4)
+        self.assertEqual(calverify.results["Number of unique double-bookings"], 3)
+
+        sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
+        sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+        self.assertEqual(sync_token_old1, sync_token_new1)
+        self.assertEqual(sync_token_oldl1, sync_token_newl1)
+
+
+    def test_instance(self):
+        """
+        CalVerifyService.doScan without fix for mismatches. Make sure it detects
+        as much as it can. Make sure sync-token is not changed.
+        """
+
+        s = """BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VTIMEZONE
+TZID:America/Los_Angeles
+BEGIN:DAYLIGHT
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
+TZNAME:PDT
+TZOFFSETFROM:-0800
+TZOFFSETTO:-0700
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
+TZNAME:PST
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0800
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:4760FF93-C7F8-4EB0-B3E8-0B22A96DB1BC
+DTSTART;TZID=America/Los_Angeles:20130221T170000
+DTEND;TZID=America/Los_Angeles:20130221T180000
+ATTENDEE;CN=Casa Blanca APPLE EMP ONLY (12) DA03 4th;CUTYPE=ROOM;PARTSTAT=
+ ACCEPTED;ROLE=REQ-PARTICIPANT:urn:uuid:366CC7BE-FEF7-4FFF-B713-6B883538A24
+ 9
+ATTENDEE;CN=Mark Chu;CUTYPE=INDIVIDUAL;EMAIL=markchu at apple.com;PARTSTAT=AC
+ CEPTED;ROLE=REQ-PARTICIPANT:urn:uuid:46F9D5D9-08E8-4987-9636-CC796F4093C6
+ATTENDEE;CN=Kristie Phan;CUTYPE=INDIVIDUAL;EMAIL=kristie_phan at apple.com;PA
+ RTSTAT=ACCEPTED:urn:uuid:97E8720F-4364-DBEC-6721-123E9A92B980
+CREATED:20130220T200530Z
+DTSTAMP:20130222T002246Z
+EXDATE:20130228T010000Z
+EXDATE:20130314T000000Z
+EXDATE:20130321T000000Z
+EXDATE:20130327T000000Z
+EXDATE:20130328T000000Z
+EXDATE:20130403T000000Z
+LOCATION:Casa Blanca APPLE EMP ONLY (12) DA03 4th
+ORGANIZER;CN=Kristie Phan;EMAIL=kristie_phan at apple.com;SCHEDULE-STATUS=1.2
+ :urn:uuid:97E8720F-4364-DBEC-6721-123E9A92B980
+RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;WKST=SU
+SEQUENCE:13
+SUMMARY:ESD Daily Meeting
+END:VEVENT
+END:VCALENDAR
+"""
+        from twistedcaldav.ical import Component
+        c = Component.fromString(s)
+        start = PyCalendarDateTime.getToday()
+        start.setDateOnly(False)
+        end = start.duplicate()
+        end.offsetDay(30)
+        config.MaxAllowedInstances = 3000
+        i = c.expandTimeRanges(end, start, ignoreInvalidInstances=True)
+        print(i)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_gateway.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_gateway.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_gateway.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import os
 import sys
@@ -95,7 +96,7 @@
         try:
             plist = readPlistFromString(output)
         except xml.parsers.expat.ExpatError, e:
-            print "Error (%s) parsing (%s)" % (e, output)
+            print("Error (%s) parsing (%s)" % (e, output))
             raise
 
         returnValue(plist)

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/upgrade.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/upgrade.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 This tool allows any necessary upgrade to complete, then exits.
@@ -38,8 +39,8 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
     try:
         UpgradeOptions().opt_help()
     except SystemExit:
@@ -63,7 +64,7 @@
     """
     Command-line options for 'calendarserver_upgrade'
 
-    @ivar upgradeers: a list of L{DirectoryUpgradeer} objects which can identify the
+    @ivar upgraders: a list of L{DirectoryUpgradeer} objects which can identify the
         calendars to upgrade, given a directory service.  This list is built by
         parsing --record and --collection options.
     """
@@ -71,6 +72,7 @@
     synopsis = description
 
     optFlags = [
+        ['status', 's', "Check database status and exit."],
         ['postprocess', 'p', "Perform post-database-import processing."],
         ['debug', 'D', "Debug logging."],
     ]
@@ -121,6 +123,8 @@
     Service which runs, exports the appropriate records, then stops the reactor.
     """
 
+    started = False
+
     def __init__(self, store, options, output, reactor, config):
         super(UpgraderService, self).__init__()
         self.store = store
@@ -135,7 +139,13 @@
         """
         Immediately stop.  The upgrade will have been run before this.
         """
-        self.output.write("Upgrade complete, shutting down.\n")
+        # If we get this far the database is OK
+        if self.options["status"]:
+            self.output.write("Database OK.\n")
+        else:
+            self.output.write("Upgrade complete, shutting down.\n")
+        UpgraderService.started = True
+
         from twisted.internet import reactor
         from twisted.internet.error import ReactorNotRunning
         try:
@@ -188,16 +198,29 @@
         output.write(logDateString() + ' ' + log.textFromEventDict(event) + "\n")
         output.flush()
 
-    setLogLevelForNamespace(None, "debug")
-    log.addObserver(onlyUpgradeEvents)
+    if not options["status"]:
+        setLogLevelForNamespace(None, "debug")
+        log.addObserver(onlyUpgradeEvents)
+
+
     def customServiceMaker():
         customService = CalDAVServiceMaker()
         customService.doPostImport = options["postprocess"]
         return customService
-    utilityMain(options["config"], makeService, reactor, customServiceMaker, verbose=options["debug"])
 
 
+    def _patchConfig(config):
+        config.FailIfUpgradeNeeded = options["status"]
 
+
+    def _onShutdown():
+        if not UpgraderService.started:
+            print("Failed to start service.")
+
+    utilityMain(options["config"], makeService, reactor, customServiceMaker, patchConfig=_patchConfig, onShutdown=_onShutdown, verbose=options["debug"])
+
+
+
 def logDateString():
     logtime = time.localtime()
     Y, M, D, h, m, s = logtime[:6]
@@ -219,3 +242,6 @@
         return '-%02d%02d' % (h, m)
     else:
         return '+%02d%02d' % (h, m)
+
+if __name__ == '__main__':
+    main()

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/util.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/util.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -81,6 +81,7 @@
                     # to get a txn in order to create a Work item
                     notifierFactory = NotifierFactory(
                         None, config.ServerHostName,
+                        config.Notifications.CoalesceSeconds,
                     )
                 else:
                     notifierFactory = None

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/validcalendardata.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/validcalendardata.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/validcalendardata.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 This tool takes data from stdin and validates it as iCalendar data suitable
@@ -32,8 +33,8 @@
 
 def usage(e=None):
     if e:
-        print e
-        print ""
+        print(e)
+        print("")
     try:
         ValidOptions().opt_help()
     except SystemExit:
@@ -145,9 +146,9 @@
             result, message = self.validCalendarData()
 
         if result:
-            print "Calendar data OK"
+            print("Calendar data OK")
         else:
-            print message
+            print(message)
         self.reactor.stop()
 
 
@@ -167,7 +168,7 @@
             if unfixed:
                 raise InvalidICalendarDataError("Calendar data had unfixable problems:\n  %s" % ("\n  ".join(unfixed),))
             if fixed:
-                print "Calendar data had fixable problems:\n  %s" % ("\n  ".join(fixed),)
+                print("Calendar data had fixable problems:\n  %s" % ("\n  ".join(fixed),))
 
         except ValueError, e:
             result = False

Deleted: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/warmup.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/warmup.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/warmup.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,187 +0,0 @@
-#!/usr/bin/env python
-
-##
-# 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.
-##
-
-"""
-This tool trawls through the server's data store, reading data.
-
-This is useful for ensuring that any on-demand data format upgrades
-are done.
-
-This tool requires access to the calendar server's configuration and
-data storage.
-"""
-
-import os
-import sys
-import sqlite3
-from getopt import getopt, GetoptError
-from os.path import dirname, abspath
-
-from twistedcaldav.config import ConfigurationError
-from twistedcaldav.resource import isPseudoCalendarCollectionResource,\
-    CalendarHomeResource
-from twistedcaldav.static import CalDAVFile
-from twistedcaldav.directory.directory import DirectoryService
-
-from calendarserver.tools.util import loadConfig, getDirectory, dummyDirectoryRecord
-
-class UsageError (StandardError):
-    pass
-
-def usage(e=None):
-    if e:
-        print e
-        print ""
-
-    name = os.path.basename(sys.argv[0])
-    print "usage: %s [options] [input_specifiers]" % (name,)
-    print ""
-    print "Warm up data store by reading everything once."
-    print __doc__
-    print "options:"
-    print "  -h --help: print this help and exit"
-    print "  -f --config: Specify caldavd.plist configuration path"
-    print ""
-    print "input specifiers:"
-    print "  -a --all: add all calendar homes"
-    print "  -H --home: add a calendar home (and all calendars within it)"
-    print "  -r --record: add a directory record's calendar home (format: 'recordType:shortName')"
-    print "  -u --user: add a user's calendar home (shorthand for '-r users:shortName')"
-
-    if e:
-        sys.exit(64)
-    else:
-        sys.exit(0)
-
-def main():
-    try:
-        (optargs, args) = getopt(
-            sys.argv[1:], "hf:o:aH:r:u:", [
-                "config=",
-                "output=",
-                "help",
-                "all", "home=", "record=", "user=",
-            ],
-        )
-    except GetoptError, e:
-        usage(e)
-
-    configFileName = None
-
-    calendarHomes = set()
-    records = set()
-    allRecords = False
-
-    def checkExists(resource):
-        if not resource.exists():
-            sys.stderr.write("No such file: %s\n" % (resource.fp.path,))
-            sys.exit(1)
-
-    for opt, arg in optargs:
-        if opt in ("-h", "--help"):
-            usage()
-
-        elif opt in ("-f", "--config"):
-            configFileName = arg
-
-        elif opt in ("-a", "--all"):
-            allRecords = True
-
-        elif opt in ("-H", "--home"):
-            path = abspath(arg)
-            parent = CalDAVFile(dirname(abspath(path)))
-            calendarHome = CalendarHomeResource(arg, parent, dummyDirectoryRecord)
-            checkExists(calendarHome)
-            calendarHomes.add(calendarHome)
-
-        elif opt in ("-r", "--record"):
-            try:
-                recordType, shortName = arg.split(":", 1)
-                if not recordType or not shortName:
-                    raise ValueError()
-            except ValueError:
-                sys.stderr.write("Invalid record identifier: %r\n" % (arg,))
-                sys.exit(1)
-
-            records.add((recordType, shortName))
-
-        elif opt in ("-u", "--user"):
-            records.add((DirectoryService.recordType_users, arg))
-
-    if args:
-        usage("Too many arguments: %s" % (" ".join(args),))
-
-    if records or allRecords:
-        try:
-            config = loadConfig(configFileName)
-            config.directory = getDirectory()
-        except ConfigurationError, e:
-            sys.stdout.write("%s\n" % (e,))
-            sys.exit(1)
-
-        for record in records:
-            recordType, shortName = record
-            calendarHome = config.directory.calendarHomeForShortName(recordType, shortName)
-            if not calendarHome:
-                sys.stderr.write("No calendar home found for record: (%s)%s\n" % (recordType, shortName))
-                sys.exit(1)
-            calendarHomes.add(calendarHome)
-
-        if allRecords:
-            for record in config.directory.allRecords():
-                calendarHome = config.directory.calendarHomeForRecord(record)
-                if not calendarHome:
-                    pass
-                else:
-                    calendarHomes.add(calendarHome)
-
-    calendarCollections = set()
-
-    for calendarHome in calendarHomes:
-        #print calendarHome
-        #sys.stdout.write("*")
-        readProperties(calendarHome)
-
-        for childName in calendarHome.listChildren():
-            child = calendarHome.getChild(childName)
-            if isPseudoCalendarCollectionResource(child):
-                calendarCollections.add(child)
-
-    for calendarCollection in calendarCollections:
-        try:
-            for name, uid, type in calendarCollection.index().indexedSearch(None):
-                child = calendarCollection.getChild(name)
-
-                #sys.stdout.write("+")
-                child._text()
-
-                readProperties(child)
-
-        except sqlite3.OperationalError:
-            # Outbox doesn't live on disk
-            if calendarCollection.fp.basename() != "outbox":
-                raise
-
-def readProperties(resource):
-    #sys.stdout.write("-")
-    for qname in resource.deadProperties().list():
-        resource.readDeadProperty(qname)
-        #sys.stdout.write(".")
-
-if __name__ == "__main__":
-    main()


Property changes on: CalendarServer/branches/users/gaya/sharedgroups/conf
___________________________________________________________________
Modified: svn:ignore
   - caldavd-dev.plist

   + caldavd-dev.plist
caldavd-apns.plist
caldavd-corpds-ldap.plist.latest
caldavd-included.plist
caldavd-ldap-separate-groupcacher-memcache.plist
caldavd-server.plist
caldavd-with-imip.plist


Modified: CalendarServer/branches/users/gaya/sharedgroups/conf/caldavd-apple.plist
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/conf/caldavd-apple.plist	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/conf/caldavd-apple.plist	2013-03-07 22:42:21 UTC (rev 10867)
@@ -355,30 +355,6 @@
 
       <key>Services</key>
       <dict>
-        <key>XMPPNotifier</key>
-        <dict>
-          <!-- XMPP notification service -->
-          <key>Service</key>
-          <string>twistedcaldav.notify.XMPPNotifierService</string>
-          <key>Enabled</key>
-          <false/>
-
-          <!-- XMPP host and port to contact -->
-          <key>Host</key>
-          <string>xmpp.host.name</string>
-          <key>Port</key>
-          <integer>5222</integer>
-
-          <!-- Jabber ID and password for the server -->
-          <key>JID</key>
-          <string>jid at xmpp.host.name/resource</string>
-          <key>Password</key>
-          <string>password_goes_here</string>
-
-          <!-- PubSub service address -->
-          <key>ServiceAddress</key>
-          <string>pubsub.xmpp.host.name</string>
-        </dict>
       </dict>
     </dict>
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/conf/caldavd-test.plist
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/conf/caldavd-test.plist	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/conf/caldavd-test.plist	2013-03-07 22:42:21 UTC (rev 10867)
@@ -656,21 +656,13 @@
       <key>CoalesceSeconds</key>
       <integer>3</integer>
 
-      <key>InternalNotificationHost</key>
-      <string>localhost</string>
-
-      <key>InternalNotificationPort</key>
-      <integer>62309</integer>
-
       <key>Services</key>
       <dict>
 
-        <key>AMPNotifier</key>
+        <key>AMP</key>
         <dict>
-          <key>Service</key>
-          <string>calendarserver.push.amppush.AMPPushNotifierService</string>
           <key>Enabled</key>
-          <true/>
+          <false/>
           <key>Port</key>
           <integer>62311</integer>
           <key>EnableStaggering</key>
@@ -679,81 +671,6 @@
           <integer>3</integer>
         </dict>
 
-        <key>SimpleLineNotifier</key>
-        <dict>
-          <!-- Simple line notification service (for testing) -->
-          <key>Service</key>
-          <string>twistedcaldav.notify.SimpleLineNotifierService</string>
-          <key>Enabled</key>
-          <false/>
-          <key>Port</key>
-          <integer>62308</integer>
-        </dict>
-
-        <key>XMPPNotifier</key>
-        <dict>
-          <!-- XMPP notification service -->
-          <key>Service</key>
-          <string>twistedcaldav.notify.XMPPNotifierService</string>
-          <key>Enabled</key>
-          <false/>
-
-          <!-- XMPP host and port to contact -->
-          <key>Host</key>
-          <string>xmpp.host.name</string>
-          <key>Port</key>
-          <integer>5222</integer>
-
-          <!-- Jabber ID and password for the server -->
-          <key>JID</key>
-          <string>jid at xmpp.host.name/resource</string>
-          <key>Password</key>
-          <string>password_goes_here</string>
-
-          <!-- PubSub service address -->
-          <key>ServiceAddress</key>
-          <string>pubsub.xmpp.host.name</string>
-
-          <!-- Apple-specific config -->
-          <key>CalDAV</key>
-          <dict>
-              <key>APSBundleID</key>
-              <string></string>
-              <key>SubscriptionURL</key>
-              <string></string>
-          </dict>
-          <key>CardDAV</key>
-          <dict>
-              <key>APSBundleID</key>
-              <string></string>
-              <key>SubscriptionURL</key>
-              <string></string>
-          </dict>
-
-          <key>NodeConfiguration</key>
-          <dict>
-            <key>pubsub#deliver_payloads</key>
-            <string>1</string>
-            <key>pubsub#persist_items</key>
-            <string>1</string>
-          </dict>
-
-          <!-- Sends a presence notification to XMPP server at this interval (prevents disconnect) -->
-          <key>KeepAliveSeconds</key>
-          <integer>120</integer>
-
-          <!-- Sends a pubsub publish to a particular heartbeat node at this interval -->
-          <key>HeartbeatMinutes</key>
-          <integer>30</integer>
-
-          <!-- List of glob-like expressions defining which XMPP JIDs can converse with the server (for debugging) -->
-          <key>AllowedJIDs</key>
-          <array>
-            <!--
-            <string>*.example.com</string>
-             -->
-          </array>
-        </dict>
       </dict>
     </dict>
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarcommonextra.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarcommonextra.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarcommonextra.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -9,6 +9,7 @@
 # Software License Agreement accompanying the package this file is a
 # part of.  You may not port this file to another platform without
 # Apple's written consent.
+from __future__ import print_function
 
 import datetime
 import subprocess
@@ -32,7 +33,7 @@
     try:
         timestamp = datetime.datetime.now().strftime("%b %d %H:%M:%S")
         msg = "calendarcommonextra: %s %s" % (timestamp, msg)
-        print msg # so it appears in Setup.log
+        print(msg) # so it appears in Setup.log
         with open(LOG, 'a') as output:
             output.write("%s\n" % (msg,)) # so it appears in our log
     except IOError:

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendardemotion.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendardemotion.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendardemotion.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -9,6 +9,7 @@
 # Software License Agreement accompanying the package this file is a
 # part of.  You may not port this file to another platform without
 # Apple's written consent.
+from __future__ import print_function
 
 import os
 from plistlib import readPlist, writePlist
@@ -30,7 +31,7 @@
             writePlist(plistData, plistPath)
 
         except Exception, e:
-            print "Unable to disable services in %s: %s" % (plistPath, e)
+            print("Unable to disable services in %s: %s" % (plistPath, e))
 
 
 if __name__ == '__main__':

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarmigrator.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarmigrator.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarmigrator.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -17,7 +17,7 @@
 # Software License Agreement accompanying the package this file is a
 # part of.  You may not port this file to another platform without
 # Apple's written consent.
-
+from __future__ import print_function
 from __future__ import with_statement
 
 import datetime
@@ -513,7 +513,7 @@
     try:
         timestamp = datetime.datetime.now().strftime("%b %d %H:%M:%S")
         msg = "calendarmigrator: %s %s" % (timestamp, msg)
-        print msg # so it appears in Setup.log
+        print(msg) # so it appears in Setup.log
         with open(LOG, 'a') as output:
             output.write("%s\n" % (msg,)) # so it appears in our log
     except IOError:

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarpromotion.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarpromotion.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/calendarpromotion.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -9,6 +9,7 @@
 # Software License Agreement accompanying the package this file is a
 # part of.  You may not port this file to another platform without
 # Apple's written consent.
+from __future__ import print_function
 
 import os
 import shutil
@@ -77,7 +78,7 @@
             gid = getgrnam(GROUP_NAME).gr_gid
             os.chown(dirName, uid, gid)
         except Exception, e:
-            print "Unable to chown %s: %s" % (dirName, e)
+            print("Unable to chown %s: %s" % (dirName, e))
 
 
     plistPath = os.path.join(DEST_CONFIG_DIR, CALDAVD_PLIST)
@@ -89,7 +90,7 @@
             writePlist(plistData, plistPath)
 
         except Exception, e:
-            print "Unable to disable update values in %s: %s" % (plistPath, e)
+            print("Unable to disable update values in %s: %s" % (plistPath, e))
 
     else:
         # Copy configuration

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/test/test_migrator.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/test/test_migrator.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/migration/test/test_migrator.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import twistedcaldav.test.util
 from contrib.migration.calendarmigrator import (
@@ -1093,7 +1094,7 @@
         ]
 
         for description, (source, target), paths, expected in info:
-            # print "-=-=-=- %s -=-=-=-" % (description,)
+            # print("-=-=-=- %s -=-=-=-" % (description,))
             accessor = StubDiskAccessor(paths)
             actual = examinePreviousSystem(source, target, diskAccessor=accessor)
             self.assertEquals(expected, actual)

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/benchlib.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/benchlib.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/benchlib.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import pickle
 from time import time
@@ -192,7 +193,7 @@
     msg('dtrace stopped')
     for (k, v) in leftOver.items():
         if v:
-            print 'Extra', k, ':', v
+            print('Extra', k, ':', v)
     returnValue(data)
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/benchmark.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/benchmark.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/benchmark.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import sys, os, plistlib
 from os.path import dirname
@@ -335,7 +336,7 @@
         statistics[name] = {}
         parameters = scalingParameters.get(name, [1, 9, 81])
         for p in parameters:
-            print '%s, parameter=%s' % (name, p)
+            print('%s, parameter=%s' % (name, p))
             dtrace = DTraceCollector("io_measure.d", pids)
             data = yield measure(host, port, dtrace, p, sampleTime)
             statistics[name][p] = data
@@ -446,7 +447,7 @@
     try:
         options.parseOptions(sys.argv[1:])
     except UsageError, e:
-        print e
+        print(e)
         return 1
 
     if options['debug']:

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/compare.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/compare.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/compare.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import sys
 
@@ -68,7 +69,7 @@
     p = ttest_1samp(second, fmean)[1]
     if p >= 0.95:
         # rejected the null hypothesis
-        print sys.argv[1], 'mean of', fmean, 'differs from', sys.argv[2], 'mean of', smean, '(%2.0f%%)' % (p * 100,)
+        print(sys.argv[1], 'mean of', fmean, 'differs from', sys.argv[2], 'mean of', smean, '(%2.0f%%)' % (p * 100,))
     else:
         # failed to reject the null hypothesis
-        print 'cannot prove means (%s, %s) differ (%2.0f%%)' % (fmean, smean, p * 100,)
+        print('cannot prove means (%s, %s) differ (%2.0f%%)' % (fmean, smean, p * 100,))

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/display-calendar-events.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/display-calendar-events.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/display-calendar-events.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,16 +13,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import eventkitframework as EventKit
 from Cocoa import NSDate
 
 store = EventKit.EKEventStore.alloc().init()
 calendars = store.calendarsForEntityType_(0)
-print calendars
+print(calendars)
 raise SystemExit
 
 predicate = store.predicateForEventsWithStartDate_endDate_calendars_(
      NSDate.date(), NSDate.distantFuture(),
      [calendars[2]])
-print store.eventsMatchingPredicate_(predicate)
+print(store.eventsMatchingPredicate_(predicate))

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/httpauth.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/httpauth.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/httpauth.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import urlparse, urllib2
 
@@ -170,8 +171,8 @@
     d = agent.request(
         'DELETE', 'http://localhost:8008/calendars/users/user01/monkeys3/')
     def deleted(response):
-        print response.code
-        print response.headers
+        print(response.code)
+        print(response.headers)
         reactor.stop()
     d.addCallback(deleted)
     d.addErrback(err)

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/ampsim.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/ampsim.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/ampsim.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -188,4 +188,3 @@
         msg(**event)
         return {}
 
-

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/ical.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/ical.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/ical.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # limitations under the License.
 #
 ##
+from __future__ import print_function
 
 from caldavclientlibrary.protocol.caldav.definitions import caldavxml
 from caldavclientlibrary.protocol.caldav.definitions import csxml
@@ -316,10 +317,10 @@
         self._client = client
 
     def initFailed(self, reason):
-        print 'XMPP initialization failed', reason
+        print('XMPP initialization failed', reason)
 
     def authFailed(self, reason):
-        print 'XMPP Authentication failed', reason
+        print('XMPP Authentication failed', reason)
 
     def handleMessageEventItems(self, iq):
         item = iq.firstChildElement().firstChildElement()
@@ -1986,7 +1987,7 @@
                 formatArgs['success'] = self.success
             else:
                 formatArgs['success'] = self.failure
-            print (self.format % formatArgs).encode('utf-8')
+            print((self.format % formatArgs).encode('utf-8'))
 
 
     def report(self, output):

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/population.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/population.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/population.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # limitations under the License.
 #
 ##
+from __future__ import print_function
 
 """
 Tools for generating a population of CalendarServer users based on
@@ -336,10 +337,10 @@
     def eventReceived(self, event):
         self._times.append(event['duration'])
         if len(self._times) == 200:
-            print 'mean:', mean(self._times)
-            print 'median:', median(self._times)
-            print 'stddev:', stddev(self._times)
-            print 'mad:', mad(self._times)
+            print('mean:', mean(self._times))
+            print('median:', median(self._times))
+            print('stddev:', stddev(self._times))
+            print('mad:', mad(self._times))
             del self._times[:100]
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/sim.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/sim.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/loadtest/sim.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # limitations under the License.
 #
 ##
+from __future__ import print_function
 
 from collections import namedtuple
 from os import environ, mkdir
@@ -261,8 +262,8 @@
                         try:
                             mkdir(serializationPath)
                         except OSError:
-                            print "Unable to create client data serialization directory: %s" % (serializationPath)
-                            print "Please consult the clientDataSerialization stanza of contrib/performance/loadtest/config.plist"
+                            print("Unable to create client data serialization directory: %s" % (serializationPath))
+                            print("Please consult the clientDataSerialization stanza of contrib/performance/loadtest/config.plist")
                             raise
 
             if 'arrival' in config:

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/massupload.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/massupload.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/massupload.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import sys, pickle
 
@@ -41,7 +42,7 @@
     try:
         options.parseOptions(sys.argv[1:])
     except UsageError, e:
-        print e
+        print(e)
         return 1
 
     fname = options['filename']

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/report.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/report.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/report.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import sys, pickle
 
@@ -20,14 +21,14 @@
 
 def main():
     if len(sys.argv) < 5:
-        print 'Usage: %s <datafile> <benchmark name> <parameter value> <metric> [command]' % (sys.argv[0],)
+        print('Usage: %s <datafile> <benchmark name> <parameter value> <metric> [command]' % (sys.argv[0],))
     else:
         stat, samples = select(pickle.load(file(sys.argv[1])), *sys.argv[2:5])
         if len(sys.argv) == 5:
-            print 'Samples'
-            print '\t' + '\n\t'.join(map(str, stat.squash(samples)))
-            print 'Commands'
-            print '\t' + '\n\t'.join(stat.commands)
+            print('Samples')
+            print('\t' + '\n\t'.join(map(str, stat.squash(samples))))
+            print('Commands')
+            print('\t' + '\n\t'.join(stat.commands))
         else:
-            print getattr(stat, sys.argv[5])(samples, *sys.argv[6:])
+            print(getattr(stat, sys.argv[5])(samples, *sys.argv[6:]))
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/sqlusage/sqlusage.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/sqlusage/sqlusage.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/sqlusage/sqlusage.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from StringIO import StringIO
 from caldavclientlibrary.client.clientsession import CalDAVSession
@@ -127,11 +128,11 @@
         
         # Now loop over sets of events
         for count in counts:
-            print "Testing count = %d" % (count,)
+            print("Testing count = %d" % (count,))
             self.ensureEvents(sessions[0], sessions[0].calendarHref, count)
             result = {}
             for request in requests:
-                print "  Test = %s" % (request.label,)
+                print("  Test = %s" % (request.label,))
                 result[request.label] = request.execute()
             self.results[count] = result
     
@@ -144,7 +145,7 @@
     def _printReport(self, title, attr, colFormat):
         table = tables.Table()
         
-        print title
+        print(title)
         headers = ["Events"] + self.requestLabels
         table.addHeader(headers)
         formats = [tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY)] + \
@@ -155,8 +156,8 @@
             table.addRow(row)
         os = StringIO()
         table.printTable(os=os)
-        print os.getvalue()
-        print
+        print(os.getvalue())
+        print("")
             
     def ensureEvents(self, session, calendarhref, n):
         """
@@ -175,9 +176,9 @@
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: sqlusage.py [options] [FILE]
+    print("""Usage: sqlusage.py [options] [FILE]
 Options:
     -h             Print this help and exit
     --server       Server hostname
@@ -191,7 +192,7 @@
 
 Description:
 This utility will analyze the output of s pg_stat_statement table.
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/sqlwatch.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/sqlwatch.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/sqlwatch.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import sys, signal, time
 
@@ -52,20 +53,20 @@
     while True:
         pids = instancePIDs(directory)
         dtrace = DTraceCollector("sql_measure.d", pids)
-        print 'Starting'
+        print('Starting')
         yield dtrace.start()
-        print 'Started'
+        print('Started')
         try:
             yield waitForInterrupt()
         except Stop:
             yield dtrace.stop()
             break
-        print 'Stopping'
+        print('Stopping')
         stats = yield dtrace.stop()
         for s in stats:
             if s.name == 'execute':
                 s.statements(stats[s])
-        print 'Stopped'
+        print('Stopped')
 
 
 def main():

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/stats.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/stats.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/stats.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import random, time
 
@@ -190,10 +191,10 @@
         if byTime:
             header = '%10s %10s %10s %s'
             row = '%10.5f %10.5f %10d %s'
-            print header % ('TOTAL MS', 'PERCALL MS', 'NCALLS', 'STATEMENT')
+            print(header % ('TOTAL MS', 'PERCALL MS', 'NCALLS', 'STATEMENT'))
             for (time, count, statement) in byTime:
                 time = time / NANO * 1000
-                print row % (time, time / count, count, statement)
+                print(row % (time, time / count, count, statement))
 
 
     def transcript(self, samples):
@@ -470,8 +471,8 @@
     
     total = 0
     for k, v in sorted(result.items(), key=lambda x:x[0]):
-        print "%d\t%.5f" % (k, float(v)/result[1])
+        print("%d\t%.5f" % (k, float(v)/result[1]))
         total += k * v
         
-    print "Average: %.2f" % (float(total) / sum(result.values()),)
+    print("Average: %.2f" % (float(total) / sum(result.values()),))
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/upload.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/upload.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/performance/upload.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import sys
 import pickle
@@ -71,13 +72,13 @@
         'max': str(max_value),
         'min': str(min_value),
         }
-    print 'uploading', data
+    print('uploading', data)
     agent = Agent(reactor)
     d = agent.request('POST', url, None, StringProducer(urlencode(data)))
     def check(response):
         d = readBody(response)
         def read(body):
-            print 'body', repr(body)
+            print('body', repr(body))
             if response.code != 200:
                 raise Exception("Upload failed: %r" % (response.code,))
         d.addCallback(read)
@@ -110,7 +111,7 @@
     try:
         options.parseOptions(sys.argv[1:])
     except UsageError, e:
-        print e
+        print(e)
         return 1
 
     fname, benchmark, param, statistic = options['statistic'].split(',')

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/anonymous_log.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/anonymous_log.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/anonymous_log.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from gzip import GzipFile
 import getopt
@@ -47,10 +48,10 @@
                 
                 if not line.startswith("Log"):
                     line = self.anonymizeLine(line)
-                print line,
+                print(line, end="")
         
         except Exception, e:
-            print "Exception: %s for %s" % (e, line,)
+            print("Exception: %s for %s" % (e, line,))
             raise
 
     def anonymizeLine(self, line):
@@ -108,9 +109,9 @@
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: anonymous_log [options] [FILE]
+    print("""Usage: anonymous_log [options] [FILE]
 Options:
     -h            Print this help and exit
 
@@ -120,7 +121,7 @@
 Description:
     This utility will anonymize the content of an access log.
 
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)
@@ -153,11 +154,11 @@
             if arg.endswith("/"):
                 arg = arg[:-1]
             if not os.path.exists(arg):
-                print "Path does not exist: '%s'. Ignoring." % (arg,)
+                print("Path does not exist: '%s'. Ignoring." % (arg,))
                 continue
 
             CalendarServerLogAnalyzer().anonymizeLogFile(arg)
 
     except Exception, e:
         sys.exit(str(e))
-        print traceback.print_exc()
+        print(traceback.print_exc())

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/dtraceanalyze.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/dtraceanalyze.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/dtraceanalyze.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -16,8 +16,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
+from __future__ import with_statement
 
-from __future__ import with_statement
 import collections
 import getopt
 import os
@@ -55,7 +56,7 @@
             
             re_matched = re.match("(..) ([^ ]+) \(([^\)]+)\)", line)
             if re_matched is None:
-                print line
+                print(line)
             results = re_matched.groups()
             if results[0] == "<-":
                 self.entering = False
@@ -175,7 +176,7 @@
                             backstack.pop()
                         if backstack: backstack.pop()
                         if indent < 0:
-                            print "help"
+                            print("help")
                     current_line = current_line.parent if current_line else None
                 min_indent = min(min_indent, indent)
 
@@ -229,7 +230,7 @@
 
     def analyze(self, do_stack, no_collapse):
         
-        print "Parsing dtrace output."
+        print("Parsing dtrace output.")
         
         # Parse the trace lines first and look for the start of the call times
         lines = []
@@ -254,22 +255,22 @@
         self.printTraceDetails(lines, do_stack, no_collapse)
         
         for ctr, title in enumerate(("Sorted by Count", "Sorted by Exclusive", "Sorted by Inclusive",)):
-            print title
+            print(title)
             self.printCallTimeTotals(ctr)
 
     def printTraceDetails(self, lines, do_stack, no_collapse):
 
-        print "Found %d lines" % (len(lines),)
-        print "============================"
-        print ""
+        print("Found %d lines" % (len(lines),))
+        print("============================")
+        print("")
         
         self.stack = Dtrace.DtraceStack(lines, no_collapse)
         if do_stack:
             with file("stacked.txt", "w") as f:
                 self.stack.prettyPrint(f)
-            print "Wrote stack calls to 'stacked.txt'"
-            print "============================"
-            print ""
+            print("Wrote stack calls to 'stacked.txt'")
+            print("============================")
+            print("")
 
         # Get stats for each call
         stats = {}
@@ -285,17 +286,17 @@
             else:
                 last_exit = line.getPartialKey()
         
-        print "Function Call Counts"
-        print ""
+        print("Function Call Counts")
+        print("")
         table = tables.Table()
         table.addHeader(("Count", "Function", "File",))
         for key, value in sorted(stats.iteritems(), key=lambda x: x[1][0], reverse=True):
             table.addRow(("%d (%d)" % value, key[1], key[0],))
         table.printTable()
 
-        print ""
-        print "Called By Counts"
-        print ""
+        print("")
+        print("Called By Counts")
+        print("")
         table = tables.Table()
         table.addHeader(("Function", "Caller", "Count",))
         for main_key in sorted(self.stack.called_by.keys(), key=lambda x: x[1] + x[0]):
@@ -309,9 +310,9 @@
                 first = False
         table.printTable()
 
-        print ""
-        print "Call Into Counts"
-        print ""
+        print("")
+        print("Call Into Counts")
+        print("")
         table = tables.Table()
         table.addHeader(("Function", "Calls", "Count",))
         for main_key in sorted(self.stack.call_into.keys(), key=lambda x: x[1] + x[0]):
@@ -324,7 +325,7 @@
                 ))
                 first = False
         table.printTable()
-        print ""
+        print("")
 
     def parseCallTimeLine(self, line, index):
     
@@ -370,13 +371,13 @@
         ))
     
         table.printTable()
-        print ""
+        print("")
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: dtraceanalyze [options] FILE
+    print("""Usage: dtraceanalyze [options] FILE
 Options:
     -h          Print this help and exit
     --stack     Save indented stack to file
@@ -396,7 +397,7 @@
     > sudo ./trace.d PID > results.txt
     ...
     > ./dtraceanalyze.py results.txt
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)
@@ -432,17 +433,17 @@
         if not os.path.exists(filepath):
             usage("File '%s' does not exist" % (filepath,))
             
-        print "CalendarServer dtrace analysis tool tool"
-        print "====================================="
-        print ""
+        print("CalendarServer dtrace analysis tool tool")
+        print("=====================================")
+        print("")
         if do_stack:
-            print "Generating nested stack call file."
+            print("Generating nested stack call file.")
         if no_collapse:
-            print "Consecutive function calls will not be removed."
+            print("Consecutive function calls will not be removed.")
         else:
-            print "Consecutive function calls will be removed."
-        print "============================"
-        print ""
+            print("Consecutive function calls will be removed.")
+        print("============================")
+        print("")
     
         Dtrace(filepath).analyze(do_stack, no_collapse)
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/fakecalendardata.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/fakecalendardata.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/fakecalendardata.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import datetime
 import getopt
@@ -116,9 +117,9 @@
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: fakecalendardata [options]
+    print("""Usage: fakecalendardata [options]
 Options:
     -h          Print this help and exit
     -a          Percentage of events that should include attendees
@@ -133,7 +134,7 @@
 Description:
 This utility will generate fake iCalendar data either into a single .ics
 file or into multiple .ics files.
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)
@@ -206,7 +207,7 @@
 
     vevents = []
     for count, (recurring, attendees, date, hour) in enumerate(eventTypes):
-        #print recurring, attendees, date, hour
+        #print(recurring, attendees, date, hour)
         vevents.append(makeVEVENT(recurring, attendees, date, hour, count+1))
 
-    print calendar_template % {"VEVENTS" : "".join(vevents)}
+    print(calendar_template % {"VEVENTS" : "".join(vevents)})

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/harpoon.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/harpoon.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/harpoon.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 # Sends SIGTERM to any calendar server child process whose VSIZE exceeds 2GB
 # Only for use in a specific environment
@@ -54,9 +55,9 @@
                 continue
             serverProcessCount += 1
             if vsize > CUTOFFBYTES:
-                print "Killing process %d with VSIZE %d" % (pidNumber, vsize)
+                print("Killing process %d with VSIZE %d" % (pidNumber, vsize))
                 os.kill(pidNumber, signal.SIGTERM)
                 numKilled += 1
 
-print "Examined %d server processes" % (serverProcessCount,)
-print "Killed %d processes" % (numKilled,)
+print("Examined %d server processes" % (serverProcessCount,))
+print("Killed %d processes" % (numKilled,))

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/monitoranalysis.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/monitoranalysis.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/monitoranalysis.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import matplotlib.pyplot as plt
 import getopt
@@ -26,7 +27,7 @@
 
 def analyze(fpath, noweekends, startDate=None, endDate=None, title=None):
     
-    print "Analyzing data for %s" % (fpath,)
+    print("Analyzing data for %s" % (fpath,))
     data = []
     firstDate = None
     global initialDate
@@ -77,7 +78,7 @@
     
                     if reqs <= 80:
                         data.append((dtstamp, reqs, resp, lqnon, cpu))
-                    #print "%s %d %d %d %d" % (dtstamp, reqs, resp, lqnon, cpu)
+                    #print("%s %d %d %d %d" % (dtstamp, reqs, resp, lqnon, cpu))
             except StopIteration:
                 break
     
@@ -93,7 +94,7 @@
 
     dataset.append((title, data,))
     
-    print "Stored %d data points" % (len(data),)
+    print("Stored %d data points" % (len(data),))
 
 def plotListenQBands(data, first, last, xlim, ylim):
 
@@ -161,7 +162,7 @@
 
 def plot(figure, noshow, nosave, pngDir, xlim, ylim):
     
-    print "Plotting data"
+    print("Plotting data")
     
     plt.figure(figure, figsize=(16, 5 * len(dataset)))
 
@@ -193,9 +194,9 @@
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: monitoranalysis [options] [FILE+]
+    print("""Usage: monitoranalysis [options] [FILE+]
 Options:
     -h             Print this help and exit
     -d             Directory to save PNGs to
@@ -216,7 +217,7 @@
 Description:
 This utility will analyze the output of the request monitor tool and
 generate some pretty plots of data.
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)
@@ -273,7 +274,7 @@
         count = 1
         for name in fnames:
             if name.startswith("request.log"):
-                print "Found file: %s" % (os.path.join(scanDir, name),)
+                print("Found file: %s" % (os.path.join(scanDir, name),))
                 trailer = name[len("request.log"):]
                 if trailer.startswith("."):
                     trailer = trailer[1:]

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/monitorsplit.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/monitorsplit.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/monitorsplit.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import getopt
 import sys
@@ -29,7 +30,7 @@
     
     global outputFile, fileCount, lastWeek
 
-    print "Splitting data for %s" % (fpath,)
+    print("Splitting data for %s" % (fpath,))
     f = GzipFile(fpath) if fpath.endswith(".gz") else open(fpath)
     for line in f:
         if line.startswith("2010/0"):
@@ -48,7 +49,7 @@
                 outputFile = open(os.path.join(outputDir, "request.log.%s" % (date,)), "w")
                 fileCount += 1
                 lastWeek = currentWeek
-                print "Changed to week of %s" % (date,)
+                print("Changed to week of %s" % (date,))
         
             output = ["-----\n"]
             output.append(line)
@@ -75,9 +76,9 @@
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: monitoranalysis [options] FILE+
+    print("""Usage: monitoranalysis [options] FILE+
 Options:
     -h          Print this help and exit
     -d          Directory to store split files in
@@ -92,7 +93,7 @@
 Description:
 This utility will analyze the output of the request monitor tool and
 generate some pretty plots of data.
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)
@@ -125,4 +126,4 @@
     for arg in args:
         split(argPath(arg), outputDir)
     
-    print "Created %d files" % (fileCount,)
+    print("Created %d files" % (fileCount,))

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/netstatus.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/netstatus.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/netstatus.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 Tool to monitor network connection status and track queue sizes and
@@ -80,20 +81,20 @@
             else:
                 pendingq[key] = (timestamp, recv, sendq,)
 
-        print "------------------------"
-        print ""
-        print time.asctime()
-        print "State        Total    RecvQ    SendQ"
+        print("------------------------")
+        print("")
+        print(time.asctime())
+        print("State        Total    RecvQ    SendQ")
         for ctr, items in enumerate(stateNames):
-            print "%11s  %5d    %5d    %5d" % (items[0], states[ctr][0], states[ctr][1], states[ctr][2])
+            print("%11s  %5d    %5d    %5d" % (items[0], states[ctr][0], states[ctr][1], states[ctr][2]))
     
-        print ""
-        print "Source IP              Established (secs)    RecvQ    SendQ"
+        print("")
+        print("Source IP              Established (secs)    RecvQ    SendQ")
         for key, value in sorted(pendingq.iteritems(), key=lambda x:x[1]):
             startedat, recv, sendq = value
             deltatime = timestamp - startedat
             if deltatime > 0:
-                print "%-20s   %3d                   %5s    %5s" % (key, deltatime, recv, sendq,)
+                print("%-20s   %3d                   %5s    %5s" % (key, deltatime, recv, sendq,))
 
         sys.stdout.flush()
         time.sleep(5)

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/pg_stats_analysis.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/pg_stats_analysis.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/pg_stats_analysis.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import sqlparse
 import os
@@ -51,7 +52,7 @@
     try:
         statements = sqlparse.parse(sql)
     except ValueError, e:
-        print e
+        print(e)
     # Replace any literal values with placeholders
     qmark = sqlparse.sql.Token('Operator', '?')
     _substitute(statements[0], qmark)
@@ -134,9 +135,9 @@
                     None,
                 ))
 
-        print "Queries sorted by %s" % (sorttype,)
+        print("Queries sorted by %s" % (sorttype,))
         table.printTable()
-        print ""
+        print("")
  
 def parseStats(logFilePath, donormlize=True, verbose=False):
     
@@ -175,20 +176,20 @@
                 bits = [bit.strip() for bit in bits]
                 entries.append(bits)
                 if verbose and divmod(len(entries), 1000)[1] == 0:
-                    print "%d entries" % (len(entries),)
+                    print("%d entries" % (len(entries),))
                 #if float(bits[COLUMN_total_time]) > 1:
-                #    print bits[COLUMN_total_time], bits[COLUMN_query]
+                #    print(bits[COLUMN_total_time], bits[COLUMN_query])
     
     if verbose:
-        print "Read %d entries" % (len(entries,))
+        print("Read %d entries" % (len(entries,)))
     
     sqlStatementsReport(entries)
             
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: pg_stats_analysis.py [options] FILE
+    print("""Usage: pg_stats_analysis.py [options] FILE
 Options:
     -h             Print this help and exit
     -v             Generate progress information
@@ -199,7 +200,7 @@
 
 Description:
 This utility will analyze the output of s pg_stat_statement table.
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/protocolanalysis.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/protocolanalysis.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/protocolanalysis.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from gzip import GzipFile
 import collections
@@ -319,7 +320,7 @@
                 try:
                     self.parseLine(line)
                 except:
-                    print "Could not parse line:\n%s" % (line,)
+                    print("Could not parse line:\n%s" % (line,))
                     continue
         
                 # Filter method
@@ -480,7 +481,7 @@
                 self.userInteractionAnalysis(adjustedMethod)
 
         except Exception:
-            print "Failed to process line:\n%s" % (line,)
+            print("Failed to process line:\n%s" % (line,))
             raise
     
         # Average various items
@@ -942,85 +943,85 @@
 
         self.printInfo(doTabs)
         
-        print "Load Analysis"
+        print("Load Analysis")
         self.printHourlyTotals(doTabs, summary)
         
         if not summary:
-            print "Client Analysis"
+            print("Client Analysis")
             self.printClientTotals(doTabs)
             
-            print "Protocol Analysis Count"
+            print("Protocol Analysis Count")
             self.printHourlyByXXXDetails(
                 self.hourlyByOKMethodCount if self.separate401s else self.hourlyByMethodCount,
                 doTabs,
             )
             
-            print "Protocol Analysis Average Response Time (ms)"
+            print("Protocol Analysis Average Response Time (ms)")
             self.printHourlyByXXXDetails(
                 self.averagedHourlyByOKMethodTime if self.separate401s else self.averagedHourlyByMethodTime,
                 doTabs,
                 showAverages=True,
             )
             
-            print "Protocol Analysis Total Response Time (ms)"
+            print("Protocol Analysis Total Response Time (ms)")
             self.printHourlyByXXXDetails(
                 self.hourlyByOKMethodTime if self.separate401s else self.hourlyByMethodTime,
                 doTabs,
                 showFloatPercent=True,
             )
             
-            print "Status Code Analysis"
+            print("Status Code Analysis")
             self.printHourlyByXXXDetails(self.hourlyByStatus, doTabs)
             
-            print "Protocol Analysis by Status"
+            print("Protocol Analysis by Status")
             self.printXXXMethodDetails(self.statusByMethodCount, doTabs, False)
             
-            print "Cache Analysis"
+            print("Cache Analysis")
             self.printHourlyCacheDetails(doTabs)
             
             if len(self.hourlyPropfindByResponseCount):
-                print "PROPFIND Calendar response count distribution"
+                print("PROPFIND Calendar response count distribution")
                 self.printHourlyByXXXDetails(self.hourlyPropfindByResponseCount, doTabs)
             
             if len(self.averagedHourlyByRecipientCount):
-                print "Average Recipient Counts"
+                print("Average Recipient Counts")
                 self.printHourlyByXXXDetails(self.averagedHourlyByRecipientCount, doTabs, showTotals=False)
                 
-            print "Queue Depth vs Response Time"
+            print("Queue Depth vs Response Time")
             self.printQueueDepthResponseTime(doTabs)
             
-            print "Instance Count Distribution"
+            print("Instance Count Distribution")
             self.printInstanceCount(doTabs)
     
-            print "Protocol Analysis by Client"
+            print("Protocol Analysis by Client")
             self.printXXXMethodDetails(self.clientIDByMethodCount, doTabs)
             
             if len(self.requestSizeByBucket):
-                print "Request size distribution"
+                print("Request size distribution")
                 self.printHourlyByXXXDetails(self.requestSizeByBucket, doTabs)
             
             if len(self.responseSizeByBucket):
-                print "Response size distribution (excluding GET Dropbox)"
+                print("Response size distribution (excluding GET Dropbox)")
                 self.printHourlyByXXXDetails(self.responseSizeByBucket, doTabs)
             
             if len(self.averageResponseCountByMethod):
-                print "Average response count by method"
+                print("Average response count by method")
                 self.printResponseCounts(doTabs)
             
             if len(self.requestTimeByBucket):
-                print "Response time distribution"
+                print("Response time distribution")
                 self.printHourlyByXXXDetails(self.requestTimeByBucket, doTabs)
             
-            print "URI Counts"
+            print("URI Counts")
             self.printURICounts(doTabs)
     
-            #print "User Interaction Counts"
+            #print("User Interaction Counts")
             #self.printUserInteractionCounts(doTabs)
     
-            print "User Weights (top 100)"
+            print("User Weights (top 100)")
             self.printUserWeights(doTabs)
     
-            #print "User Response times"
+            #print("User Response times")
             #self.printUserResponseTimes(doTabs)
 
     def printInfo(self, doTabs):
@@ -1037,7 +1038,7 @@
         table.addRow(("Lines Analyzed:", sum(self.linesRead.values()),))
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
     
     def getHourFromIndex(self, index):
         
@@ -1112,7 +1113,7 @@
         )
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
     
     def printClientTotals(self, doTabs):
         
@@ -1145,7 +1146,7 @@
         ))
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
     
     def printHourlyByXXXDetails(self, hourlyByXXX, doTabs, showTotals=True, showAverages=False, showFloatPercent=False):
     
@@ -1235,7 +1236,7 @@
             table.addFooter(row)
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
     
     def printHourlyCacheDetails(self, doTabs):
     
@@ -1326,7 +1327,7 @@
         table.addFooter(row)
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
     
     def printQueueDepthResponseTime(self, doTabs):
         
@@ -1347,7 +1348,7 @@
             ))
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
     
     def printXXXMethodDetails(self, data, doTabs, verticalTotals=True):
     
@@ -1383,7 +1384,7 @@
         table.addFooter(row)
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
 
     def printInstanceCount(self, doTabs):
     
@@ -1412,7 +1413,7 @@
             ))
    
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
 
     def printURICounts(self, doTabs):
     
@@ -1435,7 +1436,7 @@
             ))
    
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
 
     def printUserWeights(self, doTabs):
     
@@ -1458,7 +1459,7 @@
             ))
    
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
 
     def printResponseCounts(self, doTabs):
     
@@ -1480,7 +1481,7 @@
         table.addFooter(("Total:", self.averageResponseCountByMethod[" TOTAL"],))
    
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
 
     def printUserResponseTimes(self, doTabs):
     
@@ -1508,7 +1509,7 @@
             ))
    
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
 
     def printUserInteractionCounts(self, doTabs):
         table = tables.Table()
@@ -1524,7 +1525,7 @@
             # Chop off the "(a):" part.
             table.addRow((k[4:], v, safePercent(float(v), total)))
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
 
 
 class TablePrinter(object):
@@ -1583,7 +1584,7 @@
             table.addFooter(row)
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
                     
 class Differ(TablePrinter):
     
@@ -1595,24 +1596,24 @@
         
         self.printInfo(doTabs)
 
-        print "Load Analysis Differences"
+        print("Load Analysis Differences")
         #self.printLoadAnalysisDetails(doTabs)
         self.printHourlyTotals(doTabs)
 
         if not summary:
-            print "Client Differences"
+            print("Client Differences")
             self.printClientTotals(doTabs)
     
-            print "Protocol Count Differences"
+            print("Protocol Count Differences")
             self.printMethodCountDetails(doTabs)
     
-            print "Average Response Time Differences"
+            print("Average Response Time Differences")
             self.printMethodTimingDetails("clientByMethodAveragedTime", doTabs)
     
-            print "Total Response Time Differences"
+            print("Total Response Time Differences")
             self.printMethodTimingDetails("clientByMethodTotalTime", doTabs)
             
-            print "Average Response Count Differences"
+            print("Average Response Count Differences")
             self.printResponseCountDetails(doTabs)
 
     def printInfo(self, doTabs):
@@ -1626,7 +1627,7 @@
             table.addRow(("Filtered to user:", self.analyzers[0].filterByUser,))
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
     
     def printLoadAnalysisDetails(self, doTabs):
         
@@ -1781,7 +1782,7 @@
         table.addFooter(ftr, columnFormats=fmt)
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
     
     def printClientTotals(self, doTabs):
         
@@ -1863,7 +1864,7 @@
         table.addFooter(footer)
     
         table.printTabDelimitedData() if doTabs else table.printTable()
-        print ""
+        print("")
     
     def printMethodCountDetails(self, doTabs):
         
@@ -1953,9 +1954,9 @@
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: protocolanalysis [options] [FILE]
+    print("""Usage: protocolanalysis [options] [FILE]
 Options:
     -h            Print this help and exit
     --hours       Range of hours (local time) to analyze [0:23]
@@ -1976,7 +1977,7 @@
     tabulated statistics. It can also display statistics about the
     differences between two logs.
 
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)
@@ -2053,7 +2054,7 @@
                 logs.extend(glob.iglob(arg))
             else:
                 if not os.path.exists(arg):
-                    print "Path does not exist: '%s'. Ignoring." % (arg,)
+                    print("Path does not exist: '%s'. Ignoring." % (arg,))
                     continue
                 logs.append(arg)
            
@@ -2061,7 +2062,7 @@
         for log in logs:
             if diffMode or not analyzers:
                 analyzers.append(CalendarServerLogAnalyzer(startHour, endHour, utcoffset, resolution, filterByUser, filterByClient))
-            print "Analyzing: %s" % (log,)
+            print("Analyzing: %s" % (log,))
             analyzers[-1].analyzeLogFile(log)
 
         if diffMode and len(analyzers) > 1:
@@ -2074,12 +2075,12 @@
                     again = raw_input("Repeat analysis [y/n]:")
                     if again.lower()[0] == "n":
                         break
-                    print "\n\n\n"
+                    print("\n\n\n")
                     for arg in args:
-                        print "Analyzing: %s" % (arg,)
+                        print("Analyzing: %s" % (arg,))
                         analyzers[0].analyzeLogFile(arg)
                     analyzers[0].printAll(doTabDelimited, summary)
                 
     except Exception, e:
-        print traceback.print_exc()
+        print(traceback.print_exc())
         sys.exit(str(e))

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/readStats.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/readStats.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/readStats.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from StringIO import StringIO
 import collections
@@ -72,23 +73,23 @@
 
 def printStat(stats, index, showMethods, topUsers, showAgents):
 
-    print "- " * 40
-    print "Server: %s" % (stats["Server"],)
-    print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
-    print "Service Uptime: %s" % (datetime.timedelta(seconds=(int(time.time() - stats["System"]["start time"]))),)
+    print("- " * 40)
+    print("Server: %s" % (stats["Server"],))
+    print(datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S"))
+    print("Service Uptime: %s" % (datetime.timedelta(seconds=(int(time.time() - stats["System"]["start time"]))),))
     if stats["System"]["cpu count"] > 0:
-        print "Current CPU: %.1f%% (%d CPUs)" % (
+        print("Current CPU: %.1f%% (%d CPUs)" % (
             stats["System"]["cpu use"],
             stats["System"]["cpu count"],
-        )
-        print "Current Memory Used: %d bytes (%.1f GB) (%.1f%% of total)" % (
+        ))
+        print("Current Memory Used: %d bytes (%.1f GB) (%.1f%% of total)" % (
             stats["System"]["memory used"],
             stats["System"]["memory used"] / (1024.0 * 1024 * 1024),
             stats["System"]["memory percent"],
-        )
+        ))
     else:
-        print "Current CPU: Unavailable"
-        print "Current Memory Used: Unavailable"
+        print("Current CPU: Unavailable")
+        print("Current Memory Used: Unavailable")
     print
     printRequestSummary(stats)
     printHistogramSummary(stats[index], index)
@@ -105,8 +106,8 @@
 
     labels = serverLabels(stats)
 
-    print "- " * 40
-    print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
+    print("- " * 40)
+    print(datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S"))
 
     times = []
     for stat in stats:
@@ -163,10 +164,10 @@
 
 def printFailedStats(message):
 
-    print "- " * 40
-    print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
-    print message
-    print
+    print("- " * 40)
+    print(datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S"))
+    print(message)
+    print("")
 
 
 
@@ -209,7 +210,7 @@
 
     os = StringIO()
     table.printTable(os=os)
-    print os.getvalue()
+    print(os.getvalue())
 
 
 
@@ -274,13 +275,13 @@
 
     os = StringIO()
     table.printTable(os=os)
-    print os.getvalue()
+    print(os.getvalue())
 
 
 
 def printHistogramSummary(stat, index):
 
-    print "%s average response histogram" % (index,)
+    print("%s average response histogram" % (index,))
     table = tables.Table()
     table.addHeader(
         ("", "<10ms", "10ms<->100ms", "100ms<->1s", "1s<->10s", "10s<->30s", "30s<->60s", ">60s", "Over 1s", "Over 10s"),
@@ -314,7 +315,7 @@
         ))
     os = StringIO()
     table.printTable(os=os)
-    print os.getvalue()
+    print(os.getvalue())
 
 
 
@@ -339,7 +340,7 @@
 
 def printMethodCounts(stat):
 
-    print "Method Counts"
+    print("Method Counts")
     table = tables.Table()
     table.addHeader(
         ("Method", "Count", "%", "Av. Response", "%", "Total Resp. %"),
@@ -377,7 +378,7 @@
         ))
     os = StringIO()
     table.printTable(os=os)
-    print os.getvalue()
+    print(os.getvalue())
 
 
 
@@ -397,7 +398,7 @@
 
 def printUserCounts(stat, topUsers):
 
-    print "User Counts"
+    print("User Counts")
     table = tables.Table()
     table.addHeader(
         ("User", "Total", "Percentage"),
@@ -419,7 +420,7 @@
         ))
     os = StringIO()
     table.printTable(os=os)
-    print os.getvalue()
+    print(os.getvalue())
 
 
 
@@ -436,7 +437,7 @@
 
 def printAgentCounts(stat):
 
-    print "User-Agent Counts"
+    print("User-Agent Counts")
     table = tables.Table()
     table.addHeader(
         ("User-Agent", "Total", "Percentage"),
@@ -458,7 +459,7 @@
         ))
     os = StringIO()
     table.printTable(os=os)
-    print os.getvalue()
+    print(os.getvalue())
 
 
 
@@ -475,9 +476,9 @@
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: readStats [options]
+    print("""Usage: readStats [options]
 Options:
     -h            Print this help and exit
     -s            Name of local socket to read from
@@ -495,7 +496,7 @@
     This utility will print a summary of statistics read from a
     server continuously with the specified delay.
 
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/request_monitor.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/request_monitor.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/request_monitor.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from dateutil.parser import parse as dateparse
 from subprocess import Popen, PIPE, STDOUT
@@ -41,7 +42,7 @@
 elif output == "Linux":
     OS = "Linux"
 else:
-    print "Unknown OS: %s" % (output,)
+    print("Unknown OS: %s" % (output,))
     sys.exit(1)
 
 # Some system commands we need to detect
@@ -65,10 +66,10 @@
     VMSTAT = "/usr/bin/vmstat"
     enableFreeMem = os.path.exists(VMSTAT)
 
-sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) 
+sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
 
 
-filenames = ["/var/log/caldavd/access.log",]
+filenames = ["/var/log/caldavd/access.log", ]
 debug = False
 
 def listenq():
@@ -79,7 +80,7 @@
         stdout=PIPE, stderr=STDOUT,
     )
     output, _ignore_error = child.communicate()
-    ssl = nonssl = 0   
+    ssl = nonssl = 0
     for line in output.split("\n"):
         if line.find("8443") != -1:
             ssl = int(line.split("/")[0])
@@ -121,6 +122,8 @@
         results[filename].extend(output.splitlines())
     return results
 
+
+
 def range(filenames, start, end):
     results = collections.defaultdict(list)
     for filename in filenames:
@@ -132,6 +135,8 @@
                     break
     return results
 
+
+
 def cpuPerDaemon():
     a = {}
     child = Popen(
@@ -155,6 +160,7 @@
     return ", ".join([v for _ignore_k, v in sorted(a.items(), key=lambda i:i[0])])
 
 
+
 def cpuidle():
     if OS == "OS X":
         child = Popen(
@@ -175,6 +181,8 @@
         output, _ignore_ = child.communicate()
         return output.splitlines()[-2].split()[5]
 
+
+
 def freemem():
     try:
         if OS == "OS X":
@@ -186,11 +194,11 @@
             )
             output, _ignore_ = child.communicate()
             lines = output.split("\n")
-            
+
             line = lines[0]
-            pageSize = int(line[line.find("page size of")+12:].split()[0])
+            pageSize = int(line[line.find("page size of") + 12:].split()[0])
             line = lines[1]
-            freeSize = int(line[line.find("Pages free:")+11:].split()[0][:-1])
+            freeSize = int(line[line.find("Pages free:") + 11:].split()[0][:-1])
             freed = freeSize * pageSize
             return "%d bytes (%.1f GB)" % (freed, freed / (1024.0 * 1024 * 1024),)
         elif OS == "Linux":
@@ -202,21 +210,23 @@
             )
             output, _ignore_ = child.communicate()
             lines = output.splitlines()
-            
+
             line = lines[4]
             freed = int(line.split()[0]) * 1024
             return "%d bytes (%.1f GB)" % (freed, freed / (1024.0 * 1024 * 1024),)
     except Exception, e:
         if debug:
-            print "freemem failure", e
-            print traceback.print_exc()
+            print("freemem failure", e)
+            print(traceback.print_exc())
         return "error"
 
+
+
 def parseLine(line):
 
     startPos = line.find("- ")
     endPos = line.find(" [")
-    userId = line[startPos+2:endPos]
+    userId = line[startPos + 2:endPos]
 
     startPos = endPos + 2
     endPos = line.find(']', startPos)
@@ -236,7 +246,7 @@
         uri = line[startPos:endPos]
         startPos = endPos + 11
 
-    status = int(line[startPos:startPos+3])
+    status = int(line[startPos:startPos + 3])
 
     startPos += 4
     endPos = line.find(' ', startPos)
@@ -266,40 +276,46 @@
         endPos = line.find(' ', startPos)
         extended["or"] = int(line[startPos:endPos])
     else:
-        
+
         items = line[startPos:].split()
         extended = dict([item.split('=') for item in items if item.find("=") != -1])
 
     return userId, logTime, method, uri, status, bytes, referer, client, extended
 
+
+
 def safePercent(value, total):
-    
+
     return value * 100.0 / total if total else 0.0
 
+
+
 def usage():
-    print "request_monitor [OPTIONS] [FILENAME]"
-    print
-    print "FILENAME   optional path of access log to monitor [/var/log/caldavd/access.log]"
-    print
-    print "OPTIONS"
-    print "-h         print help and exit"
-    print "--debug    print tracebacks and error details"
-    print "--lines N  specifies how many lines to tail from access.log (default: 10000)"
-    print "--range M:N  specifies a range of lines to analyze from access.log (default: all)"
-    print "--procs N  specifies how many python processes are expected in the log file (default: 80)"
-    print "--top N    how many long requests to print (default: 10)"
-    print "--router   analyze a partition server router node"
-    print "--worker   analyze a partition server worker node"
-    print
-    print "Version: 5"
+    print("request_monitor [OPTIONS] [FILENAME]")
+    print("")
+    print("FILENAME   optional path of access log to monitor [/var/log/caldavd/access.log]")
+    print("")
+    print("OPTIONS")
+    print("-h         print help and exit")
+    print("--debug    print tracebacks and error details")
+    print("--lines N  specifies how many lines to tail from access.log (default: 10000)")
+    print("--range M:N  specifies a range of lines to analyze from access.log (default: all)")
+    print("--procs N  specifies how many python processes are expected in the log file (default: 80)")
+    print("--top N    how many long requests to print (default: 10)")
+    print("--users N  how many top users to print (default: 5)")
+    print("--router   analyze a partition server router node")
+    print("--worker   analyze a partition server worker node")
+    print("")
+    print("Version: 5")
 
 numLines = 10000
 numProcs = 80
 numTop = 10
+numUsers = 5
 lineRange = None
 router = False
 worker = False
-options, args = getopt.getopt(sys.argv[1:], "h", ["debug", "router", "worker", "lines=", "range=", "procs=", "top="])
+options, args = getopt.getopt(sys.argv[1:], "h", ["debug", "router", "worker", "lines=", "range=", "procs=", "top=", "users="])
 for option, value in options:
     if option == "-h":
         usage()
@@ -318,6 +334,8 @@
         numProcs = int(value)
     elif option == "--top":
         numTop = int(value)
+    elif option == "--users":
+        numUsers = int(value)
 
 if len(args):
     filenames = sorted([os.path.expanduser(arg) for arg in args])
@@ -325,21 +343,21 @@
 
 for filename in filenames:
     if not os.path.isfile(filename):
-        print "Path %s does not exist" % (filename,)
-        print
+        print("Path %s does not exist" % (filename,))
+        print("")
         usage()
         sys.exit(1)
 
 for filename in filenames:
     if not os.access(filename, os.R_OK):
-        print "Path %s does not exist" % (filename,)
-        print
+        print("Path %s does not exist" % (filename,))
+        print("")
         usage()
         sys.exit(1)
 
 if debug:
-    print "Starting: access log files: %s" % (", ".join(filenames),)
-    print
+    print("Starting: access log files: %s" % (", ".join(filenames),))
+    print("")
 
 while True:
 
@@ -367,7 +385,7 @@
     totalOver1s = [0, 0]
     totalOver10s = [0, 0]
     requests = []
-    users = { }
+    users = {}
     startTime = None
     endTime = None
     errorCount = 0
@@ -379,35 +397,35 @@
             for line in lines[filename]:
                 if not line or line.startswith("Log"):
                     continue
-    
+
                 numRequests[filename] += 1
-    
+
                 try:
                     userId, logTime, method, uri, status, bytes, _ignore_referer, client, extended = parseLine(line)
                 except Exception, e:
                     parseErrors += 1
-                    
+
                     if debug:
-                        print "Access log line parse failure", e
-                        print traceback.print_exc()
-                        print "---"
-                        print line
-                        print "---"
-                        
+                        print("Access log line parse failure", e)
+                        print(traceback.print_exc())
+                        print("---")
+                        print(line)
+                        print("---")
+
                     continue
-    
+
                 logTime = dateparse(logTime, fuzzy=True)
                 times.append(logTime)
                 perfile_times[filename].append(logTime)
-    
+
                 if status >= 500:
                     errorCount += 1
-    
+
                 if uri == "/ischedule":
                     numServerToServer[filename] += 1
                 elif uri.startswith("/calendars"):
                     numProxied[filename] += 1
-    
+
                 outstanding = int(extended['or'])
                 logId = int(extended['i'] if extended['i'] else 0)
                 raw = rawCounts.get(logId, 0) + 1
@@ -416,7 +434,7 @@
                 if outstanding > prevMax:
                     ids[logId] = outstanding
                 slotCount[filename] += outstanding
-    
+
                 respTime = float(extended['t'])
                 wrTime = float(extended.get('t-resp-wr', 0.0))
                 timeSpent = timesSpent.get(logId, 0.0) + respTime
@@ -425,86 +443,84 @@
                 totalRespWithoutWRTime[filename] += respTime - wrTime
                 if respTime > maxRespTime[filename]:
                     maxRespTime[filename] = respTime
-    
+
                 for index, testTime in enumerate((respTime, respTime - wrTime,)):
                     if testTime >= 60000.0:
                         over60s[index] += 1
                     elif testTime >= 30000.0:
-                        over30s[index] +=1
+                        over30s[index] += 1
                     elif testTime >= 10000.0:
-                        over10s[index] +=1
+                        over10s[index] += 1
                     elif testTime >= 1000.0:
-                        over1s[index] +=1
+                        over1s[index] += 1
                     elif testTime >= 100.0:
-                        over100ms[index] +=1
+                        over100ms[index] += 1
                     elif testTime >= 10.0:
-                        over10ms[index] +=1
+                        over10ms[index] += 1
                     else:
-                        under10ms[index] +=1
+                        under10ms[index] += 1
                     if testTime >= 1000.0:
-                        totalOver1s[index] +=1
+                        totalOver1s[index] += 1
                     if testTime >= 10000.0:
-                        totalOver10s[index] +=1
-    
-    
+                        totalOver10s[index] += 1
+
                 ext = []
                 for key, value in extended.iteritems():
                     if key not in ('i', 't'):
                         if key == "cl":
-                            value = float(value)/1024
+                            value = float(value) / 1024
                             value = "%.1fKB" % (value,)
                             key = "req"
                         ext.append("%s:%s" % (key, value))
                 ext = ", ".join(ext)
-    
+
                 try:
                     client = client.split(";")[2]
                     client = client.strip()
                 except:
                     pass
-    
+
                 if userId != "-":
-                    userStat = users.get(userId, { 'count' : 0, 'clients' : {} })
+                    userStat = users.get(userId, {'count' : 0, 'clients' : {}})
                     userStat['count'] += 1
                     clientCount = userStat['clients'].get(client, 0)
                     userStat['clients'][client] = clientCount + 1
                     users[userId] = userStat
-    
+
                 reqStartTime = logTime - datetime.timedelta(milliseconds=respTime)
-                requests.append((respTime, userId, method, bytes/1024.0, ext, client, logId, logTime, reqStartTime))
+                requests.append((respTime, userId, method, bytes / 1024.0, ext, client, logId, logTime, reqStartTime))
 
-
         times.sort()
         if len(times) == 0:
-            print "No data to analyze"
+            print("No data to analyze")
             time.sleep(10)
             continue
-        
+
         totalRequests = sum(numRequests.values())
 
-        print "- " * 40
-        print datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S"), 
+        print("- " * 40)
+        print(datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S"),)
         if enableListenQueue:
             q, lqssl, lqnon = listenQueueHistory()
-            print "Listenq (ssl+non):", q[0], " (Recent", ", ".join(q[1:]), "Oldest)"
+            print("Listenq (ssl+non):", q[0], " (Recent", ", ".join(q[1:]), "Oldest)")
         if enableCpuIdle:
             q = idleHistory()
-            print "CPU idle %:", q[0], " (Recent", ", ".join(q[1:]), "Oldest)"
+            print("CPU idle %:", q[0], " (Recent", ", ".join(q[1:]), "Oldest)")
         if enableFreeMem:
-            print "Memory free:", freemem()
-        print "CPU Per Daemon:", cpuPerDaemon()
-        print
+            print("Memory free:", freemem())
+        print("CPU Per Daemon:", cpuPerDaemon())
+        print("")
 
         table = tables.Table()
         table.addHeader(
-            ("Instance", "Requests", "Av. Requests", "Av. Response", "Av. Response", "Max. Response",     "Slot", "Start",  "End", "File Name"),
+            ("Instance", "Requests", "Av. Requests", "Av. Response", "Av. Response", "Max. Response", "Slot", "Start", "End", "File Name"),
         )
         table.addHeader(
-            (        "",         "",   "per second",         "(ms)", "no write(ms)",          "(ms)",  "Average", "Time", "Time",          ""),
+            ("", "", "per second", "(ms)", "no write(ms)", "(ms)", "Average", "Time", "Time", ""),
         )
         table.setDefaultColumnFormats(
            (
-                tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.CENTER_JUSTIFY), 
+                tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.CENTER_JUSTIFY),
                 tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
                 tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
                 tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
@@ -516,7 +532,7 @@
                 tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
             )
         )
-        
+
         totalAverage = 0.0
         totalResponseTime = 0.0
         totalResponseWithoutWRTime = 0.0
@@ -525,14 +541,14 @@
         minStartTime = None
         maxEndTime = None
         for ctr, filename in enumerate(sorted(perfile_times.keys())):
-            
+
             times = sorted(perfile_times[filename])
             startTime = times[0]
             minStartTime = startTime if minStartTime is None else min(minStartTime, startTime)
 
             endTime = times[-1]
             maxEndTime = endTime if maxEndTime is None else min(maxEndTime, endTime)
-            
+
             deltaTime = endTime - startTime
 
             avgRequests = float(len(times)) / deltaTime.seconds
@@ -540,16 +556,16 @@
 
             avgResponse = totalRespTime[filename] / len(times)
             totalResponseTime += totalRespTime[filename]
-            
+
             avgResponseWithWR = totalRespWithoutWRTime[filename] / len(times)
             totalResponseWithoutWRTime += totalRespWithoutWRTime[filename]
-            
+
             maxResponseTime = max(maxResponseTime, maxRespTime[filename])
-            
+
             totalSlots += slotCount[filename]
 
             table.addRow((
-                "#%s" % (ctr+1,),
+                "#%s" % (ctr + 1,),
                 len(times),
                 avgRequests,
                 avgResponse,
@@ -560,7 +576,7 @@
                 endTime,
                 filename[prefix:],
             ))
-            
+
         if len(perfile_times) > 1:
             table.addFooter((
                 "Total:",
@@ -574,25 +590,25 @@
                 maxEndTime,
                 "",
             ))
-            
+
         os = StringIO()
         table.printTable(os=os)
-        print os.getvalue()
+        print(os.getvalue())
 
         if enableListenQueue:
             lqlatency = (lqssl / avgRequests, lqnon / avgRequests,) if avgRequests else (0.0, 0.0,)
-            print " listenq latency (ssl+non): %.1f s %.1f s" % (
+            print(" listenq latency (ssl+non): %.1f s %.1f s" % (
                 lqlatency[0],
                 lqlatency[1],
-            )
-        
+            ))
+
         table = tables.Table()
         table.addHeader(
-            ("", "<10ms", "10ms<->100ms", "100ms<->1s", "1s<->10s", "10s<->30s", "30s<->60s", ">60s",  "Over 1s", "Over 10s"),
+            ("", "<10ms", "10ms<->100ms", "100ms<->1s", "1s<->10s", "10s<->30s", "30s<->60s", ">60s", "Over 1s", "Over 10s"),
         )
         table.setDefaultColumnFormats(
            (
-                tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.CENTER_JUSTIFY), 
+                tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.CENTER_JUSTIFY),
                 tables.Table.ColumnFormat("%d (%.1f%%)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
                 tables.Table.ColumnFormat("%d (%.1f%%)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
                 tables.Table.ColumnFormat("%d (%.1f%%)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
@@ -619,44 +635,43 @@
             ))
         os = StringIO()
         table.printTable(os=os)
-        print os.getvalue()
+        print(os.getvalue())
         print
         if errorCount:
-            print "Number of 500 errors: %d" % (errorCount,)
+            print("Number of 500 errors: %d" % (errorCount,))
         if parseErrors:
-            print "Number of access log parsing errors: %d" % (parseErrors,)
+            print("Number of access log parsing errors: %d" % (parseErrors,))
         if errorCount or parseErrors:
-            print
+            print("")
 
-        print "Proc:   Peak outstanding:        Seconds of processing (number of requests):"
-        for l in xrange((numProcs-1)/10 + 1):
+        print("Proc:   Peak outstanding:        Seconds of processing (number of requests):")
+        for l in xrange((numProcs - 1) / 10 + 1):
             base = l * 10
-            print "%2d-%2d: " % (base, base+9),
+            print("%2d-%2d: " % (base, base + 9),)
 
-            for i in xrange(base, base+10):
+            for i in xrange(base, base + 10):
                 try:
                     r = ids[i]
                     s = "%1d" % (r,)
                 except KeyError:
                     s = "."
-                print s,
+                print(s, end="")
 
-            print "    ",
+            print("    ", end="")
 
-            for i in xrange(base, base+10):
+            for i in xrange(base, base + 10):
                 try:
                     r = timesSpent[i] / 1000
                     c = rawCounts[i]
-                    s = "%4.0f(%4d)" % (r,c)
+                    s = "%4.0f(%4d)" % (r, c)
                 except KeyError:
                     s = "         ."
-                print s,
+                print(s, end="")
 
+            print("")
 
-            print
-
-        print
-        print "Top %d longest (in most recent %d requests):" % (numTop, sum(numRequests.values()),)
+        print("")
+        print("Top %d longest (in most recent %d requests):" % (numTop, sum(numRequests.values()),))
         requests.sort()
         requests.reverse()
         for i in xrange(numTop):
@@ -669,46 +684,44 @@
                     if _logId == logId and _logTime > reqStartTime and _reqStartTime < logTime:
                         overlapCount += 1
 
-                print "%7.1fms  %-12s %s res:%.1fKB, %s [%s] #%d +%d %s->%s" % (respTime, userId, method, kb, ext, client, logId, overlapCount, reqStartTime.strftime("%H:%M:%S"), logTime.strftime("%H:%M:%S"),)
+                print("%7.1fms  %-12s %s res:%.1fKB, %s [%s] #%d +%d %s->%s" % (respTime, userId, method, kb, ext, client, logId, overlapCount, reqStartTime.strftime("%H:%M:%S"), logTime.strftime("%H:%M:%S"),))
                 """
-                print "%7.1fms  %-12s %s res:%.1fKB, %s [%s] #%d %s->%s" % (respTime, userId, method, kb, ext, client, logId, reqStartTime.strftime("%H:%M:%S"), logTime.strftime("%H:%M:%S"),)
+                print("%7.1fms  %-12s %s res:%.1fKB, %s [%s] #%d %s->%s" % (respTime, userId, method, kb, ext, client, logId, reqStartTime.strftime("%H:%M:%S"), logTime.strftime("%H:%M:%S"),))
             except:
                 pass
 
-            
-
-        print
-        print "Top 5 busiest users (in most recent %d requests):" % (totalRequests,)
+        print("")
+        print("Top %d busiest users (in most recent %d requests):" % (numUsers, totalRequests,))
         userlist = []
         for user, userStat in users.iteritems():
             userlist.append((userStat['count'], user, userStat))
         userlist.sort()
         userlist.reverse()
-        for i in xrange(5):
+        for i in xrange(numUsers):
             try:
                 count, user, userStat = userlist[i]
-                print "%3d  %-12s " % (count, user),
+                print("%3d  %-12s " % (count, user), end="")
                 clientStat = userStat['clients']
                 clients = clientStat.keys()
                 if len(clients) == 1:
-                    print "[%s]" % (clients[0],)
+                    print("[%s]" % (clients[0],))
                 else:
                     clientList = []
                     for client in clients:
                         clientList.append("%s: %d" % (client, clientStat[client]))
-                    print "[%s]" % ", ".join(clientList)
+                    print("[%s]" % ", ".join(clientList))
             except:
                 pass
 
         print
-        
+
         # lineRange => do loop only once
         if lineRange is not None:
             break
 
     except Exception, e:
-        print "Script failure", e
+        print("Script failure", e)
         if debug:
-            print traceback.print_exc()
+            print(traceback.print_exc())
 
     time.sleep(10)

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/sortrecurrences.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/sortrecurrences.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/sortrecurrences.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import getopt
 import os
@@ -23,9 +24,9 @@
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print """Usage: sortrecurrences FILE
+    print("""Usage: sortrecurrences FILE
 Options:
     -h            Print this help and exit
 
@@ -35,7 +36,7 @@
 Description:
     This utility will output a sorted iCalendar component.
 
-"""
+""")
 
     if error_msg:
         raise ValueError(error_msg)
@@ -68,13 +69,13 @@
             if arg.endswith("/"):
                 arg = arg[:-1]
             if not os.path.exists(arg):
-                print "Path does not exist: '%s'. Ignoring." % (arg,)
+                print("Path does not exist: '%s'. Ignoring." % (arg,))
                 continue
 
             cal = PyCalendar()
             cal.parse(open(arg))
-            print str(cal.serialize())
+            print(str(cal.serialize()))
 
     except Exception, e:
         sys.exit(str(e))
-        print traceback.print_exc()
+        print(traceback.print_exc())

Modified: CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/sqldata_from_path.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/sqldata_from_path.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/contrib/tools/sqldata_from_path.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 Prints out an SQL statement that can be used in an SQL shell against
@@ -27,16 +28,16 @@
 
 def usage(error_msg=None):
     if error_msg:
-        print error_msg
+        print(error_msg)
 
-    print "sqldata_from_path PATH"
-    print
-    print "PATH   filestore or HTTP path"
-    print
-    print """Prints out an SQL statement that can be used in an SQL shell against
-an sqlstore database to return the calendar or address data for the provided
-filestore or HTTP path. Path must be a __uids__ path.
-"""
+    print("sqldata_from_path PATH")
+    print("")
+    print("PATH   filestore or HTTP path")
+    print("""
+Prints out an SQL statement that can be used in an SQL shell against
+an sqlstore database to return the calendar or address data for the
+provided filestore or HTTP path. Path must be a __uids__ path.
+""")
 
     if error_msg:
         raise ValueError(error_msg)
@@ -105,11 +106,11 @@
     sqlstrings[datatype]["collection"] = collection
     sqlstrings[datatype]["resource"] = resource
 
-    print """select %(object_data)s from %(object_table)s where
+    print("""select %(object_data)s from %(object_table)s where
     %(object_name)s = '%(resource)s' and %(object_bind_id)s = (
         select %(bind_id)s from %(bind_table)s where
             %(bind_name)s = '%(collection)s' and %(bind_home_id)s = (
                 select RESOURCE_ID from %(home_table)s where OWNER_UID = '%(uid)s'
             )
-    );""" % sqlstrings[datatype]
+    );""" % sqlstrings[datatype])
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/setup.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/setup.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/setup.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -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
 import os
@@ -172,7 +173,7 @@
         for script in dist.scripts:
             scriptPath = os.path.join(install_scripts, os.path.basename(script))
 
-            print "rewriting %s" % (scriptPath,)
+            print("rewriting %s" % (scriptPath,))
 
             script = []
 

Deleted: CalendarServer/branches/users/gaya/sharedgroups/support/directorysetup.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/support/directorysetup.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/support/directorysetup.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,302 +0,0 @@
-#!/usr/bin/env python
-#
-##
-# Copyright (c) 2007-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 getopt
-import os
-import sys
-
-def usage():
-    print """Usage: directorysetup [options] init|addUser|disableUser|removeUser <<user>>
-Options:
-    -h       Print this help and exit
-    -n node  OpenDirectory node to target (/LDAPv3/127.0.0.1)
-    -u uid   OpenDirectory Admin user id
-    -p pswd  OpenDirectory Admin user password
-    -c cname OpenDirectory /Computers record name for the calendar server
-    
-Description:
-This is a little command line utility to setup a directory server with records
-conforming to the new schema used by the calendar server. It has several "actions":
-
-"init" - this action will modify the computer record for the host calendar server to
-add the new "com.apple.macosxserver.virtualhosts" entry.
-
-"addUser" - modifies a user record to enable use of the calendar server.
-
-"disableUser" - modifies a user record to disable use of the calendar server.
-
-"removeUser" - modifies a user record to prevent use of the calendar server by
- removing any reference to the service.
-
-"""
-
-def initComputerRecord(admin_user, admin_pswd, node, recordname):
-    plistdefault = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-        <key>ReplicaName</key>
-        <string>Master</string>
-        <key>com.apple.od.role</key>
-        <string>master</string>
-</dict>
-</plist>
-"""
-    plistdefault = plistdefault.replace('"', '\\"')
-    plistdefault = plistdefault.replace('\n', '')
-
-    plist_good = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-    <dict>
-        <key>ReplicaName</key>
-        <string>Master</string>
-
-        <key>com.apple.od.role</key>
-        <string>master</string>
-
-        <key>com.apple.macosxserver.virtualhosts</key>
-        <dict>
-            <key>4F088107-51FD-4DE5-904D-2C0AD9C6C893</key>
-            <dict>
-                <key>hostname</key>
-                <string>foo.apple.com</string>
-
-                <key>hostDetails</key>
-                <dict>
-                    <key>http</key>
-                    <dict>
-                        <key>port</key>
-                        <integer>80</integer>
-                    </dict>
-                    <key>https</key>
-                    <dict>
-                        <key>port</key>
-                        <integer>443</integer>
-                    </dict>
-                </dict>
-
-                <key>serviceType</key>
-                <array>
-                    <string>wiki</string>
-                    <string>webCalendar</string>
-                    <string>webMailingList</string>
-                </array>
-
-                <key>serviceInfo</key>
-                <dict>
-                    <key>webCalendar</key>
-                    <dict>
-                        <key>enabled</key>
-                        <true/>
-                        <key>urlMask</key>
-                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(name)s/webcalendar</string>
-                    </dict>
-                    <key>wiki</key>
-                    <dict>
-                        <key>enabled</key>
-                        <true/>
-                        <key>urlMask</key>
-                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(name)s/wiki</string>
-                    </dict>
-                    <key>webMailingList</key>
-                    <dict>
-                        <key>enabled</key>
-                        <true/>
-                        <key>urlMask</key>
-                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(name)s/mailinglist</string>
-                    </dict>
-                </dict>
-            </dict>
-            
-            <key>C18C34AC-3D9E-403C-8A33-BFC303F3840E</key>
-            <dict>
-                <key>hostname</key>
-                <string>calendar.apple.com</string>
-
-                <key>hostDetails</key>
-                <dict>
-                    <key>http</key>
-                    <dict>
-                        <key>port</key>
-                        <integer>8800</integer>
-                    </dict>
-                    <key>https</key>
-                    <dict>
-                        <key>port</key>
-                        <integer>8843</integer>
-                    </dict>
-                </dict>
-
-                <key>serviceType</key>
-                <array>
-                    <string>calendar</string>
-                </array>
-
-                <key>serviceInfo</key>
-                <dict>
-                    <key>calendar</key>
-                    <dict>
-                        <key>templates</key>
-                        <dict>
-                            <key>principalPath</key>
-                            <string>/principals/%(type)s/%(name)s</string>
-                            <key>calendarUserAddresses</key>
-                            <array>
-                                <string>%(scheme)s://%(hostname)s:%(port)s/principals/%(type)s/%(name)s</string>
-                                <string>mailto:%(email)s</string>
-                                <string>urn:uuid:%(guid)s</string>
-                            </array>
-                        </dict>
-                    </dict>
-                </dict>
-            </dict>
-
-        </dict>
-    </dict>
-</plist>
-"""
-
-    plist_good = plist_good.replace('"', '\\"')
-    plist_good = plist_good.replace('\n', '')
-    cmd = "dscl -u %s -P %s %s -create /Computers/%s \"dsAttrTypeStandard:XMLPlist\" \"%s\"" % (admin_user, admin_pswd, node, recordname, plist_good,)
-    print cmd
-    os.system(cmd)
-
-def getComputerRecordGUID(admin_user, admin_pswd, node, computername):
-    # First get the generatedGUID for this computer
-    cmd = "dscl -u %s -P %s %s -read /Computers/%s \"dsAttrTypeStandard:GeneratedUID\"" % (admin_user, admin_pswd, node, computername,)
-    print cmd
-    result = os.popen(cmd, "r")
-    for line in result:
-        return line[len("GeneratedUID: "):-1]
-
-def addUser(admin_user, admin_pswd, node, computername, username):
-
-    uid = getComputerRecordGUID(admin_user, admin_pswd, node, computername)
-    servicetag = "%s:%s:calendar" % (uid, "C18C34AC-3D9E-403C-8A33-BFC303F3840E")
-
-    cmd = "dscl -u %s -P %s %s -create /Users/%s \"dsAttrTypeStandard:ServicesLocator\" \"%s\"" % (admin_user, admin_pswd, node, username, servicetag,)
-    print cmd
-    os.system(cmd)
-
-def disableUser(admin_user, admin_pswd, node, computername, username):
-
-    uid = getComputerRecordGUID(admin_user, admin_pswd, node, computername)
-    servicetag = "%s:%s:calendar:disabled" % (uid, "C18C34AC-3D9E-403C-8A33-BFC303F3840E")
-
-    cmd = "dscl -u %s -P %s %s -create /Users/%s \"dsAttrTypeStandard:ServicesLocator\" \"%s\"" % (admin_user, admin_pswd, node, username, servicetag,)
-    print cmd
-    os.system(cmd)
-
-def removeUser(admin_user, admin_pswd, node, computername, username):
-    cmd = "dscl -u %s -P %s %s -delete /Users/%s \"dsAttrTypeStandard:ServicesLocator\"" % (admin_user, admin_pswd, node, username,)
-    print cmd
-    os.system(cmd)
-
-if __name__ == "__main__":
-
-    try:
-        options, args = getopt.getopt(sys.argv[1:], "hc:n:p:u:")
-
-        node = "/LDAPv3/127.0.0.1"
-        admin_user = None
-        admin_pswd = None
-        computername = None
-
-        for option, value in options:
-            if option == "-h":
-                usage()
-                sys.exit(0)
-            elif option == "-n":
-                node = value
-            elif option == "-u":
-                admin_user = value
-            elif option == "-p":
-                admin_pswd = value
-            elif option == "-c":
-                computername = value
-            else:
-                print "Unrecognized option: %s" % (option,)
-                usage()
-                raise ValueError
-
-        # Some options are required
-        if not admin_user:
-            print "A user name must be specified with the -u option"
-        if not admin_pswd:
-            print "A password must be specified with the -p option"
-        if not computername:
-            print "A computer record name must be specified with the -c option"
-        if not admin_user or not admin_pswd or not computername:
-            usage()
-            raise ValueError
-            
-        # Process arguments
-        if len(args) == 0:
-            print "No arguments given. One of 'init', 'addUser', 'disableUser', 'removeUser' must be present."
-            usage()
-            raise ValueError
-        elif args[0] not in ("init", "addUser", "disableUser", "removeUser"):
-            print "Wrong arguments given: %s" % (args[0],)
-            usage()
-            raise ValueError
-        
-        if args[0] == "init":
-            if len(args) > 1:
-                print "Too many arguments given to 'init'"
-                usage()
-                raise ValueError
-            initComputerRecord(admin_user, admin_pswd, node, computername)
-        elif args[0] == "addUser":
-            if len(args) > 2:
-                print "Too many arguments given to 'addUser'"
-                usage()
-                raise ValueError
-            elif len(args) != 2:
-                print "'addUser' must have one argument - the user name"
-                usage()
-                raise ValueError
-            addUser(admin_user, admin_pswd, node, computername, args[1])
-        elif args[0] == "disableUser":
-            if len(args) > 2:
-                print "Too many arguments given to 'disableUser'"
-                usage()
-                raise ValueError
-            elif len(args) != 2:
-                print "'disableUser' must have one argument - the user name"
-                usage()
-                raise ValueError
-            disableUser(admin_user, admin_pswd, node, computername, args[1])
-        elif args[0] == "removeUser":
-            if len(args) > 2:
-                print "Too many arguments given to 'removeUser'"
-                usage()
-                raise ValueError
-            elif len(args) != 2:
-                print "'removeUser' must have one argument - the user name"
-                usage()
-                raise ValueError
-            removeUser(admin_user, admin_pswd, node, computername, args[1])
-
-    except Exception, e:
-        sys.exit(str(e))

Modified: CalendarServer/branches/users/gaya/sharedgroups/support/version.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/support/version.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/support/version.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import os
 from os.path import dirname, basename
@@ -75,4 +76,4 @@
 
 if __name__ == "__main__":
     base_version, comment = version()
-    print "%s (%s)" % (base_version, comment)
+    print("%s (%s)" % (base_version, comment))

Modified: CalendarServer/branches/users/gaya/sharedgroups/test
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/test	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/test	2013-03-07 22:42:21 UTC (rev 10867)
@@ -95,11 +95,32 @@
   rm -f "${tmp}";
 fi;
 
+search_py ()
+{
+  find . \
+    ! '(' -type d '(' -path '*/.*' -or -name data ')' -prune ')' \
+    -type f -name '*.py' \
+    -print0 \
+    | xargs -0 -n 100 grep "$@";
+}
+
+#tmp="$(mktemp "/tmp/calendarserver_test_flakish.XXXXX")";
+#echo "";
+#echo "Checking for other issues..."
+#search_py 'print  *[^(]' | sed 's|#.*||' | grep 'print  *[^(]' > "${tmp}" || true;
+#if [ -s "${tmp}" ]; then
+#    echo "**** Use of legacy print statement found. ****";
+#    cat "${tmp}";
+#    exit 1;
+#fi;
+#rm -f "${tmp}";
+
 tmp="$(mktemp "/tmp/calendarserver_test_emtpy.XXXXX")";
-find "${wd}" '!' '(' -type d '(' -path '*/.*' -o -name data ')' -prune ')' -type f -size 0 > "${tmp}";
+find "${wd}" '!' '(' -type d '(' -path '*/.*' -or -name data ')' -prune ')' -type f -size 0 > "${tmp}";
 if [ -s "${tmp}" ]; then
     echo "**** Empty files: ****";
     cat "${tmp}";
     exit 1;
 fi;
 rm -f "${tmp}";
+

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/parseschema.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/parseschema.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/parseschema.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 Parser for SQL schema.
@@ -167,7 +168,7 @@
 
             schema.tableNamed(tableName).insertSchemaRow(rowData)
         else:
-            print 'unknown type:', stmt.get_type()
+            print('unknown type:', stmt.get_type())
     return schema
 
 
@@ -438,8 +439,8 @@
                 else:
                     expected = False
                 if not expected:
-                    print 'UNEXPECTED TOKEN:', repr(val), theColumn
-                    print self.parens
+                    print('UNEXPECTED TOKEN:', repr(val), theColumn)
+                    print(self.parens)
                     import pprint
                     pprint.pprint(self.parens.tokens)
                     return 0

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/record.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/record.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/record.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -190,9 +190,12 @@
     @classmethod
     @inlineCallbacks
     def load(cls, transaction, *primaryKey):
-        self = (yield cls.query(transaction,
-                                cls._primaryKeyComparison(primaryKey)))[0]
-        returnValue(self)
+        results = (yield cls.query(transaction,
+                                cls._primaryKeyComparison(primaryKey)))
+        if len(results) != 1:
+            raise NoSuchRecord()
+        else:
+            returnValue(results[0])
 
 
     @classmethod

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/test/test_record.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/test/test_record.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/dal/test/test_record.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -98,6 +98,16 @@
 
 
     @inlineCallbacks
+    def test_missingLoad(self):
+        """
+        Try loading an row which doesn't exist
+        """
+        txn = self.pool.connection()
+        yield txn.execSQL("insert into ALPHA values (:1, :2)", [234, "one"])
+        self.assertFailure(TestRecord.load(txn, 456), NoSuchRecord)
+
+
+    @inlineCallbacks
     def test_simpleCreate(self):
         """
         When a record object is created, a row with matching column values will

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/queue.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/queue.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/enterprise/queue.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -97,7 +97,7 @@
 from twext.enterprise.dal.syntax import SchemaSyntax, Lock, NamedValue
 
 from twext.enterprise.dal.model import ProcedureCall
-from twext.enterprise.dal.record import Record, fromTable
+from twext.enterprise.dal.record import Record, fromTable, NoSuchRecord
 from twisted.python.failure import Failure
 
 from twext.enterprise.dal.model import Table, Schema, SQLType, Constraint
@@ -826,15 +826,19 @@
     @inlineCallbacks
     def work(txn):
         workItemClass = WorkItem.forTable(table)
-        workItem = yield workItemClass.load(txn, workID)
-        if workItem.group is not None:
-            yield NamedLock.acquire(txn, workItem.group)
-        # TODO: what if we fail?  error-handling should be recorded someplace,
-        # the row should probably be marked, re-tries should be triggerable
-        # administratively.
-        yield workItem.delete()
-        # TODO: verify that workID is the primary key someplace.
-        yield workItem.doWork()
+        try:
+            workItem = yield workItemClass.load(txn, workID)
+            if workItem.group is not None:
+                yield NamedLock.acquire(txn, workItem.group)
+            # TODO: what if we fail?  error-handling should be recorded someplace,
+            # the row should probably be marked, re-tries should be triggerable
+            # administratively.
+            yield workItem.delete()
+            # TODO: verify that workID is the primary key someplace.
+            yield workItem.doWork()
+        except NoSuchRecord:
+            # The record has already been removed
+            pass
     return inTransaction(txnFactory, work)
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/internet/gaiendpoint.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/internet/gaiendpoint.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/internet/gaiendpoint.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 L{getaddrinfo}()-based endpoint
@@ -164,18 +165,18 @@
     from twisted.internet.protocol import Factory, Protocol
     class HelloGoobye(Protocol, object):
         def connectionMade(self):
-            print 'Hello!'
+            print('Hello!')
             self.transport.loseConnection()
 
         def connectionLost(self, reason):
-            print 'Goodbye'
+            print('Goodbye')
 
     class MyFactory(Factory, object):
         def buildProtocol(self, addr):
-            print 'Building protocol for:', addr
+            print('Building protocol for:', addr)
             return HelloGoobye()
     def bye(what):
-        print 'bye', what
+        print('bye', what)
         reactor.stop()
     gaie.connect(MyFactory()).addBoth(bye)
     reactor.run()

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/python/_plistlib.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/python/_plistlib.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/python/_plistlib.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,6 +1,8 @@
 #
 # Added to standard library in Python 2.6 (Mac only in prior versions)
 #
+from __future__ import print_function
+
 """plistlib.py -- a tool to generate and parse MacOSX .plist files.
 
 The PropertList (.plist) file format is a simple XML pickle supporting
@@ -50,7 +52,7 @@
 Parse Plist example::
 
     pl = readPlist(pathOrFile)
-    print pl["aKey"]
+    print(pl["aKey"])
 """
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/python/log.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/python/log.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/python/log.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 Classes and functions to do granular logging.
@@ -110,7 +111,7 @@
 #    # In case we add log levels that don't map to pythong logging levels:
 #    #
 #    for l in logLevels:
-#        print "Trying %s: %s, %s" % (l, l in pythonLogLevelMapping, cmpLogLevels(level, l) <= 0)
+#        print("Trying %s: %s, %s" % (l, l in pythonLogLevelMapping, cmpLogLevels(level, l) <= 0))
 #        if l in pythonLogLevelMapping and cmpLogLevels(level, l) <= 0:
 #            return pythonLogLevelMapping[l]
 #

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/python/memcacheclient.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/python/memcacheclient.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/python/memcacheclient.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+from __future__ import print_function
 
 """
 client module for memcached (memory cache daemon)
@@ -319,7 +320,7 @@
         for i in range(Client._SERVER_RETRIES):
             server = self.buckets[serverhash % len(self.buckets)]
             if server.connect():
-                #print "(using server %s)" % server,
+                #print("(using server %s)" % server, end="")
                 return server, key
             serverhash = serverHashFunction(str(serverhash) + str(i))
         log.error("Memcacheclient _get_server( ) failed to connect")
@@ -1310,9 +1311,9 @@
     return doctest.testmod(memcacheclient, globs=globs)
 
 if __name__ == "__main__":
-    print "Testing docstrings..."
+    print("Testing docstrings...")
     _doctest()
-    print "Running tests:"
+    print("Running tests:")
     print
     serverList = [["127.0.0.1:11211"]]
     if '--do-unix' in sys.argv:
@@ -1326,14 +1327,14 @@
                 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)),
+            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"
+                print("OK")
                 return 1
             else:
-                print "FAIL"
+                print("FAIL")
                 return 0
 
 
@@ -1350,107 +1351,107 @@
         test_setget("a_string", "some random string")
         test_setget("an_integer", 42)
         if test_setget("long", long(1<<30)):
-            print "Testing delete ...",
+            print("Testing delete ...", end="")
             if mc.delete("long"):
-                print "OK"
+                print("OK")
             else:
-                print "FAIL"
-        print "Testing get_multi ...",
-        print mc.get_multi(["a_string", "an_integer"])
+                print("FAIL")
+        print("Testing get_multi ...", end="")
+        print(mc.get_multi(["a_string", "an_integer"]))
 
-        print "Testing get(unknown value) ...",
-        print to_s(mc.get("unknown_value"))
+        print("Testing get(unknown value) ...", end="")
+        print(to_s(mc.get("unknown_value")))
 
         f = FooStruct()
         test_setget("foostruct", f)
 
-        print "Testing incr ...",
+        print("Testing incr ...", end="")
         x = mc.incr("an_integer", 1)
         if x == 43:
-            print "OK"
+            print("OK")
         else:
-            print "FAIL"
+            print("FAIL")
 
-        print "Testing decr ...",
+        print("Testing decr ...", end="")
         x = mc.decr("an_integer", 1)
         if x == 42:
-            print "OK"
+            print("OK")
         else:
-            print "FAIL"
+            print("FAIL")
 
         # sanity tests
-        print "Testing sending spaces...",
+        print("Testing sending spaces...", end="")
         try:
             x = mc.set("this has spaces", 1)
         except Client.MemcachedKeyCharacterError, msg:
-            print "OK"
+            print("OK")
         else:
-            print "FAIL"
+            print("FAIL")
 
-        print "Testing sending control characters...",
+        print("Testing sending control characters...", end="")
         try:
             x = mc.set("this\x10has\x11control characters\x02", 1)
         except Client.MemcachedKeyCharacterError, msg:
-            print "OK"
+            print("OK")
         else:
-            print "FAIL"
+            print("FAIL")
 
-        print "Testing using insanely long key...",
+        print("Testing using insanely long key...", end="")
         try:
             x = mc.set('a'*SERVER_MAX_KEY_LENGTH + 'aaaa', 1)
         except Client.MemcachedKeyLengthError, msg:
-            print "OK"
+            print("OK")
         else:
-            print "FAIL"
+            print("FAIL")
 
-        print "Testing sending a unicode-string key...",
+        print("Testing sending a unicode-string key...", end="")
         try:
             x = mc.set(u'keyhere', 1)
         except Client.MemcachedStringEncodingError, msg:
-            print "OK",
+            print("OK", end="")
         else:
-            print "FAIL",
+            print("FAIL", end="")
         try:
             x = mc.set((u'a'*SERVER_MAX_KEY_LENGTH).encode('utf-8'), 1)
         except:
-            print "FAIL",
+            print("FAIL", end="")
         else:
-            print "OK",
+            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"
+            print("OK")
         else:
-            print "FAIL"
+            print("FAIL")
 
-        print "Testing using a value larger than the memcached value limit...",
+        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",
+            print("OK", end="")
         else:
-            print "FAIL",
+            print("FAIL", end="")
         x = mc.set('keyhere', 'a'*SERVER_MAX_VALUE_LENGTH + 'aaa')
         if mc.get('keyhere') == None:
-            print "OK"
+            print("OK")
         else:
-            print "FAIL"
+            print("FAIL")
 
-        print "Testing set_multi() with no memcacheds running",
+        print("Testing set_multi() with no memcacheds running", end="")
         mc.disconnect_all()
         errors = mc.set_multi({'keyhere' : 'a', 'keythere' : 'b'})
         if errors != []:
-            print "FAIL"
+            print("FAIL")
         else:
-            print "OK"
+            print("OK")
 
-        print "Testing delete_multi() with no memcacheds running",
+        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"
+            print("FAIL")
         else:
-          print "OK"
+          print("OK")
 
 # vim: ts=4 sw=4 et :

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/web2/dav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/web2/dav/resource.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/web2/dav/resource.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -22,6 +22,7 @@
 #
 # DRI: Wilfredo Sanchez, wsanchez at apple.com
 ##
+from __future__ import print_function
 
 """
 WebDAV resources.
@@ -759,7 +760,7 @@
             )[2].append((resource, url))
 
         # Now determine whether each ace satisfies privileges
-        #print aclmap
+        #print(aclmap)
         for items in aclmap.itervalues():
             checked = (yield self.checkACLPrivilege(
                 request, items[0], items[1], privileges, inherited_aces

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/web2/fileupload.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/web2/fileupload.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/web2/fileupload.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -21,7 +21,7 @@
 # SOFTWARE.
 #
 ##
-from __future__ import generators
+from __future__ import print_function
 
 import re
 from zope.interface import implements
@@ -74,7 +74,7 @@
             line = defer.waitForDeferred(line)
             yield line
             line = line.getResult()
-        #print "GOT", line
+        #print("GOT", line)
         if not line.endswith('\r\n'):
             if line == "":
                 raise MimeFormatError("Unexpected end of stream.")
@@ -194,7 +194,7 @@
         return d
 
     def _readFirstBoundary(self):
-        #print "_readFirstBoundary"
+        #print("_readFirstBoundary")
         line = self.stream.readline(size=1024)
         if isinstance(line, defer.Deferred):
             line = defer.waitForDeferred(line)
@@ -209,7 +209,7 @@
     _readFirstBoundary = defer.deferredGenerator(_readFirstBoundary)
 
     def _readBoundaryLine(self):
-        #print "_readBoundaryLine"
+        #print("_readBoundaryLine")
         line = self.stream.readline(size=1024)
         if isinstance(line, defer.Deferred):
             line = defer.waitForDeferred(line)
@@ -227,7 +227,7 @@
     _readBoundaryLine = defer.deferredGenerator(_readBoundaryLine)
 
     def _doReadHeaders(self, morefields):
-        #print "_doReadHeaders", morefields
+        #print("_doReadHeaders", morefields)
         if not morefields:
             return None
         return _readHeaders(self.stream)
@@ -392,7 +392,7 @@
     log = Logger()
     d.addErrback(log.err)
     def pr(s):
-        print s
+        print(s)
     d.addCallback(pr)
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/web2/http_headers.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/web2/http_headers.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/web2/http_headers.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,5 +1,5 @@
 # -*- test-case-name: twext.web2.test.test_http_headers -*-
-# #
+##
 # Copyright (c) 2008 Twisted Matrix Laboratories.
 # Copyright (c) 2010-2013 Apple Computer, Inc. All rights reserved.
 #
@@ -21,7 +21,8 @@
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 # SOFTWARE.
 #
-# #
+##
+from __future__ import print_function
 
 """
 HTTP header representation, parsing, and serialization.
@@ -100,7 +101,7 @@
 
         try:
             for p in parser:
-                # print "Parsing %s: %s(%s)" % (name, repr(p), repr(h))
+                # print("Parsing %s: %s(%s)" % (name, repr(p), repr(h)))
                 header = p(header)
                 # if isinstance(h, types.GeneratorType):
                 #     h=list(h)
@@ -125,7 +126,7 @@
         generator = self.HTTPGenerators.get(name, None)
 
         if generator is None:
-            # print self.generators
+            # print(self.generators)
             raise ValueError("No header generator for header '%s', either add one or use setHeaderRaw." % (name,))
 
         for g in generator:

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/web2/server.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/web2/server.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/web2/server.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -22,6 +22,7 @@
 # SOFTWARE.
 #
 ##
+from __future__ import print_function
 
 """
 This is a web-server which integrates with the twisted.internet
@@ -297,7 +298,7 @@
         else:
             self.prepath = []
             self.postpath = path
-        #print "_parseURL", self.uri, (self.uri, self.scheme, self.host, self.path, self.params, self.querystring)
+        #print("_parseURL", self.uri, (self.uri, self.scheme, self.host, self.path, self.params, self.querystring))
 
     def _schemeFromPort(self, port):
         """

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/web2/test/test_client.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/web2/test/test_client.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/web2/test/test_client.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,5 +1,6 @@
 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
 # See LICENSE for details.
+from __future__ import print_function
 
 """
 Tests for HTTP client.
@@ -393,7 +394,7 @@
         req = http.ClientRequest('GET', '/', None, None)
 
         def gotResp(r):
-            print r
+            print(r)
 
         d = cxn.client.submitRequest(req).addCallback(gotResp)
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/who/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/__init__.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/__init__.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,3 +1,4 @@
+# -*- test-case-name: twext.who.test -*-
 ##
 # Copyright (c) 2013 Apple Inc. All rights reserved.
 #

Added: CalendarServer/branches/users/gaya/sharedgroups/twext/who/aggregate.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/aggregate.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/aggregate.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,91 @@
+# -*- test-case-name: twext.who.test.test_aggregate -*-
+##
+# 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.
+##
+
+"""
+Directory service which aggregates multiple directory services.
+"""
+
+__all__ = [
+    "DirectoryService",
+    "DirectoryRecord",
+]
+
+from itertools import chain
+
+from twisted.internet.defer import gatherResults, FirstError
+
+from twext.who.idirectory import DirectoryConfigurationError
+from twext.who.idirectory import IDirectoryService
+from twext.who.index import DirectoryService as BaseDirectoryService
+from twext.who.index import DirectoryRecord
+from twext.who.util import ConstantsContainer
+
+
+class DirectoryService(BaseDirectoryService):
+    """
+    Aggregate directory service.
+    """
+
+    def __init__(self, realmName, services):
+        recordTypes = set()
+
+        for service in services:
+            if not IDirectoryService.implementedBy(service.__class__):
+                raise ValueError("Not a directory service: %s" % (service,))
+
+            for recordType in service.recordTypes():
+                if recordType in recordTypes:
+                    raise DirectoryConfigurationError(
+                        "Aggregated services may not vend the same record type: %s"
+                        % (recordType,)
+                    )
+                recordTypes.add(recordType)
+
+        BaseDirectoryService.__init__(self, realmName)
+
+        self._services = tuple(services)
+
+
+    @property
+    def services(self):
+        return self._services
+
+
+    @property
+    def recordType(self):
+        if not hasattr(self, "_recordType"):
+            self._recordType = ConstantsContainer(chain(*tuple(
+                s.recordTypes()
+                for s in self.services
+            )))
+        return self._recordType
+
+
+    def recordsFromExpression(self, expression, records=None):
+        ds = []
+        for service in self.services:
+            d = service.recordsFromExpression(expression, records)
+            ds.append(d)
+
+        def unwrapFirstError(f):
+            f.trap(FirstError)
+            return f.value.subFailure
+
+        d = gatherResults(ds, consumeErrors=True)
+        d.addCallback(lambda results: chain(*results))
+        d.addErrback(unwrapFirstError)
+        return d

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/who/directory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/directory.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/directory.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,3 +1,4 @@
+# -*- test-case-name: twext.who.test.test_directory -*-
 ##
 # Copyright (c) 2006-2013 Apple Inc. All rights reserved.
 #
@@ -33,8 +34,8 @@
 from twext.who.idirectory import QueryNotSupportedError, NotAllowedError
 from twext.who.idirectory import FieldName, RecordType
 from twext.who.idirectory import Operand
-from twext.who.idirectory import DirectoryQueryMatchExpression
 from twext.who.idirectory import IDirectoryService, IDirectoryRecord
+from twext.who.expression import MatchExpression
 from twext.who.util import uniqueResult, describe
 
 
@@ -63,7 +64,7 @@
 
 
     def recordTypes(self):
-        return succeed(self.recordType.iterconstants())
+        return self.recordType.iterconstants()
 
 
     def recordsFromExpression(self, expression, records=None):
@@ -114,36 +115,43 @@
 
 
     def recordsWithFieldValue(self, fieldName, value):
-        return self.recordsFromExpression(DirectoryQueryMatchExpression(fieldName, value))
+        return self.recordsFromExpression(MatchExpression(fieldName, value))
 
+
     @inlineCallbacks
     def recordWithUID(self, uid):
         returnValue(uniqueResult((yield self.recordsWithFieldValue(FieldName.uid, uid))))
                
+
     @inlineCallbacks
     def recordWithGUID(self, guid):
         returnValue(uniqueResult((yield self.recordsWithFieldValue(FieldName.guid, guid))))
 
+
     def recordsWithRecordType(self, recordType):
         return self.recordsWithFieldValue(FieldName.recordType, recordType)
 
+
     @inlineCallbacks
     def recordWithShortName(self, recordType, shortName):
         returnValue(uniqueResult((yield self.recordsFromQuery((
-            DirectoryQueryMatchExpression(FieldName.recordType, recordType),
-            DirectoryQueryMatchExpression(FieldName.shortNames, shortName ),
+            MatchExpression(FieldName.recordType, recordType),
+            MatchExpression(FieldName.shortNames, shortName ),
         )))))
 
+
     def recordsWithEmailAddress(self, emailAddress):
         return self.recordsWithFieldValue(FieldName.emailAddresses, emailAddress)
 
+
     def updateRecords(self, records, create=False):
         for record in records:
-            raise NotAllowedError("Record updates not allowed.")
+            return fail(NotAllowedError("Record updates not allowed."))
 
+
     def removeRecords(self, uids):
         for uid in uids:
-            raise NotAllowedError("Record removal not allowed.")
+            return fail(NotAllowedError("Record removal not allowed."))
 
 
 

Added: CalendarServer/branches/users/gaya/sharedgroups/twext/who/expression.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/expression.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/expression.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,96 @@
+# -*- test-case-name: twext.who.test.test_expression -*-
+##
+# 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.
+##
+
+"""
+Directory query expressions.
+"""
+
+__all__ = [
+    "MatchType",
+    "MatchFlags",
+    "MatchExpression",
+]
+
+from twisted.python.constants import Names, NamedConstant
+from twisted.python.constants import Flags, FlagConstant
+
+
+
+##
+# Match expression
+##
+
+
+
+class MatchType(Names):
+    """
+    Query match types.
+    """
+    equals     = NamedConstant()
+    startsWith = NamedConstant()
+    contains   = NamedConstant()
+
+    equals.description     = "equals"
+    startsWith.description = "starts with"
+    contains.description   = "contains"
+
+
+
+class MatchFlags(Flags):
+    """
+    Match expression flags.
+    """
+    NOT = FlagConstant()
+    NOT.description = "not"
+
+    caseInsensitive = FlagConstant()
+    caseInsensitive.description = "case insensitive"
+
+
+
+class MatchExpression(object):
+    """
+    Query for a matching value in a given field.
+
+    @ivar fieldName: a L{NamedConstant} specifying the field
+    @ivar fieldValue: a text value to match
+    @ivar matchType: a L{NamedConstant} specifying the match algorythm
+    @ivar flags: L{NamedConstant} specifying additional options
+    """
+
+    def __init__(self, fieldName, fieldValue, matchType=MatchType.equals, flags=None):
+        self.fieldName  = fieldName
+        self.fieldValue = fieldValue
+        self.matchType  = matchType
+        self.flags      = flags
+
+    def __repr__(self):
+        def describe(constant):
+            return getattr(constant, "description", str(constant))
+
+        if self.flags is None:
+            flags = ""
+        else:
+            flags = " (%s)" % (describe(self.flags),)
+
+        return "<%s: %r %s %r%s>" % (
+            self.__class__.__name__,
+            describe(self.fieldName),
+            describe(self.matchType),
+            describe(self.fieldValue),
+            flags
+        )

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/who/idirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/idirectory.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/idirectory.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,3 +1,4 @@
+# -*- test-case-name: twext.who.test -*-
 ##
 # Copyright (c) 2006-2013 Apple Inc. All rights reserved.
 #
@@ -20,6 +21,7 @@
 
 __all__ = [
     "DirectoryServiceError",
+    "DirectoryConfigurationError",
     "DirectoryAvailabilityError",
     "UnknownRecordTypeError",
     "QueryNotSupportedError",
@@ -28,10 +30,7 @@
 
     "RecordType",
     "FieldName",
-    "MatchType",
     "Operand",
-    "QueryFlags",
-    "DirectoryQueryMatchExpression",
 
     "IDirectoryService",
     "IDirectoryRecord",
@@ -40,7 +39,6 @@
 from zope.interface import Attribute, Interface
 
 from twisted.python.constants import Names, NamedConstant
-from twisted.python.constants import Flags, FlagConstant
 
 
 
@@ -53,6 +51,11 @@
     Directory service generic error.
     """
 
+class DirectoryConfigurationError(DirectoryServiceError):
+    """
+    Directory configurtion error.
+    """
+
 class DirectoryAvailabilityError(DirectoryServiceError):
     """
     Directory not available.
@@ -126,20 +129,6 @@
 
 
 
-class MatchType(Names):
-    """
-    Query match types.
-    """
-    equals     = NamedConstant()
-    startsWith = NamedConstant()
-    contains   = NamedConstant()
-
-    equals.description     = "equals"
-    startsWith.description = "starts with"
-    contains.description   = "contains"
-
-
-
 class Operand(Names):
     OR  = NamedConstant()
     AND = NamedConstant()
@@ -149,53 +138,6 @@
 
 
 
-class QueryFlags(Flags):
-    """
-    Query flags.
-    """
-    NOT = FlagConstant()
-    NOT.description = "not"
-
-    caseInsensitive = FlagConstant()
-    caseInsensitive.description = "case insensitive"
-
-
-
-class DirectoryQueryMatchExpression(object):
-    """
-    Query for a matching value in a given field.
-
-    @ivar fieldName: a L{NamedConstant} specifying the field
-    @ivar fieldValue: a text value to match
-    @ivar matchType: a L{NamedConstant} specifying the match algorythm
-    @ivar flags: L{NamedConstant} specifying additional options
-    """
-
-    def __init__(self, fieldName, fieldValue, matchType=MatchType.equals, flags=None):
-        self.fieldName  = fieldName
-        self.fieldValue = fieldValue
-        self.matchType  = matchType
-        self.flags      = flags
-
-    def __repr__(self):
-        def describe(constant):
-            return getattr(constant, "description", str(constant))
-
-        if self.flags is None:
-            flags = ""
-        else:
-            flags = " (%s)" % (self.flags,)
-
-        return "<%s: %r %s %r%s>" % (
-            self.__class__.__name__,
-            describe(self.fieldName),
-            describe(self.matchType),
-            describe(self.fieldValue),
-            flags
-        )
-
-
-
 ##
 # Interfaces
 ##
@@ -219,16 +161,26 @@
 
     def recordTypes():
         """
-        @return: a deferred iterable of L{NamedConstant}s denoting the
-            record types that are kept in this directory.
+        @return: an iterable of L{NamedConstant}s denoting the record
+            types that are kept in this directory.
         """
 
+    def recordsFromExpression(self, expression):
+        """
+        Find records matching an expression.
+        @param expression: an expression to apply
+        @type expression: L{object}
+        @return: a deferred iterable of matching L{IDirectoryRecord}s.
+        @raises: L{QueryNotSupportedError} if the expression is not
+            supported by this directory service.
+        """
+
     def recordsFromQuery(expressions, operand=Operand.AND):
         """
-        Find records matching a query consisting of an iterable of
+        Find records by composing a query consisting of an iterable of
         expressions and an operand.
-        @param expressions: an iterable of expressions
-        @type expressions: L{object}
+        @param expressions: expressions to query against
+        @type expressions: iterable of L{object}s
         @param operand: an operand
         @type operand: a L{NamedConstant}
         @return: a deferred iterable of matching L{IDirectoryRecord}s.

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/who/index.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/index.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/index.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,3 +1,4 @@
+# -*- test-case-name: twext.who.test.test_xml -*-
 ##
 # Copyright (c) 2006-2013 Apple Inc. All rights reserved.
 #
@@ -23,13 +24,14 @@
     "DirectoryRecord",
 ]
 
+from itertools import chain
+
 from twisted.python.constants import Names, NamedConstant
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue
 
-from twext.who.util import MergedConstants, describe, uniqueResult, iterFlags
+from twext.who.util import ConstantsContainer, describe, uniqueResult, iterFlags
 from twext.who.idirectory import FieldName as BaseFieldName
-from twext.who.idirectory import MatchType, QueryFlags
-from twext.who.idirectory import DirectoryQueryMatchExpression
+from twext.who.expression import MatchExpression, MatchType, MatchFlags
 from twext.who.directory import DirectoryService as BaseDirectoryService
 from twext.who.directory import DirectoryRecord as BaseDirectoryRecord
 
@@ -55,7 +57,7 @@
     XML directory service.
     """
 
-    fieldName = MergedConstants(BaseDirectoryService.fieldName, FieldName)
+    fieldName = ConstantsContainer(chain(BaseDirectoryService.fieldName.iterconstants(), FieldName.iterconstants()))
 
     indexedFields = (
         BaseFieldName.recordType,
@@ -105,9 +107,9 @@
 
         if flags is not None:
             for flag in iterFlags(flags):
-                if flag == QueryFlags.NOT:
+                if flag == MatchFlags.NOT:
                     predicate = lambda x: not x
-                elif flag == QueryFlags.caseInsensitive:
+                elif flag == MatchFlags.caseInsensitive:
                     normalize = lambda x: x.lower()
                 else:
                     raise NotImplementedError("Unknown query flag: %s" % (describe(flag),))
@@ -186,11 +188,11 @@
                 if match(normalize(fieldValue)):
                     result.add(record)
 
-        return result
+        return succeed(result)
 
 
     def recordsFromExpression(self, expression, records=None):
-        if isinstance(expression, DirectoryQueryMatchExpression):
+        if isinstance(expression, MatchExpression):
             if expression.fieldName in self.indexedFields:
                 return self.indexedRecordsFromMatchExpression(expression, records=records)
             else:

Added: CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_aggregate.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_aggregate.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_aggregate.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,239 @@
+##
+# 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.
+##
+
+"""
+Aggregate directory service tests.
+"""
+
+from twisted.python.components import proxyForInterface
+from twisted.trial import unittest
+
+from twext.who.idirectory import IDirectoryService, DirectoryConfigurationError
+from twext.who.aggregate import DirectoryService
+from twext.who.util import ConstantsContainer
+
+from twext.who.test import test_directory, test_xml
+from twext.who.test.test_xml import QueryMixIn, xmlService, TestService as XMLTestService
+
+
+
+class BaseTest(object):
+    def service(self, services=None):
+        if services is None:
+            services = (self.xmlService(),)
+
+        #
+        # Make sure aggregate DirectoryService isn't making
+        # implementation assumptions about the IDirectoryService
+        # objects it gets.
+        #
+        services = tuple((
+            proxyForInterface(IDirectoryService)(s)
+            for s in services
+        ))
+
+        class TestService(DirectoryService, QueryMixIn):
+            pass
+
+        return TestService("xyzzy", services)
+
+
+    def xmlService(self, xmlData=None, serviceClass=None):
+        return xmlService(self.mktemp(), xmlData, serviceClass)
+
+
+
+class DirectoryServiceBaseTest(BaseTest, test_xml.DirectoryServiceBaseTest):
+    def test_repr(self):
+        service = self.service()
+        self.assertEquals(repr(service), "<TestService 'xyzzy'>")
+
+
+
+class DirectoryServiceQueryTest(BaseTest, test_xml.DirectoryServiceQueryTest):
+    pass
+
+
+
+class DirectoryServiceImmutableTest(BaseTest, test_directory.DirectoryServiceImmutableTest):
+    pass
+
+
+
+class AggregatedBaseTest(BaseTest):
+    def service(self):
+        class UsersDirectoryService(XMLTestService):
+            recordType = ConstantsContainer((XMLTestService.recordType.user,))
+
+        class GroupsDirectoryService(XMLTestService):
+            recordType = ConstantsContainer((XMLTestService.recordType.group,))
+
+        usersService  = self.xmlService(testXMLConfigUsers, UsersDirectoryService)
+        groupsService = self.xmlService(testXMLConfigGroups, GroupsDirectoryService)
+
+        return BaseTest.service(self, (usersService, groupsService))
+
+
+
+class DirectoryServiceAggregatedBaseTest(AggregatedBaseTest, DirectoryServiceBaseTest):
+    pass
+
+
+
+class DirectoryServiceAggregatedQueryTest(AggregatedBaseTest, test_xml.DirectoryServiceQueryTest):
+    pass
+
+
+
+class DirectoryServiceAggregatedImmutableTest(AggregatedBaseTest, test_directory.DirectoryServiceImmutableTest):
+    pass
+
+
+
+class DirectoryServiceTests(BaseTest, unittest.TestCase):
+    def test_conflictingRecordTypes(self):
+        self.assertRaises(
+            DirectoryConfigurationError,
+            BaseTest.service, self,
+            (self.xmlService(), self.xmlService(testXMLConfigUsers)),
+        )
+
+
+
+testXMLConfigUsers = """<?xml version="1.0" encoding="utf-8"?>
+
+<directory realm="Users Realm">
+
+  <record type="user">
+    <uid>__wsanchez__</uid>
+    <short-name>wsanchez</short-name>
+    <short-name>wilfredo_sanchez</short-name>
+    <full-name>Wilfredo Sanchez</full-name>
+    <password>zehcnasw</password>
+    <email>wsanchez at bitbucket.calendarserver.org</email>
+    <email>wsanchez at devnull.twistedmatrix.com</email>
+  </record>
+
+  <record type="user">
+    <uid>__glyph__</uid>
+    <short-name>glyph</short-name>
+    <full-name>Glyph Lefkowitz</full-name>
+    <password>hpylg</password>
+    <email>glyph at bitbucket.calendarserver.org</email>
+    <email>glyph at devnull.twistedmatrix.com</email>
+  </record>
+
+  <record type="user">
+    <uid>__sagen__</uid>
+    <short-name>sagen</short-name>
+    <full-name>Morgen Sagen</full-name>
+    <password>negas</password>
+    <email>sagen at bitbucket.calendarserver.org</email>
+    <email>shared at example.com</email>
+  </record>
+
+  <record type="user">
+    <uid>__cdaboo__</uid>
+    <short-name>cdaboo</short-name>
+    <full-name>Cyrus Daboo</full-name>
+    <password>suryc</password>
+    <email>cdaboo at bitbucket.calendarserver.org</email>
+  </record>
+
+  <record type="user">
+    <uid>__dre__</uid>
+    <short-name>dre</short-name>
+    <full-name>Andre LaBranche</full-name>
+    <password>erd</password>
+    <email>dre at bitbucket.calendarserver.org</email>
+    <email>shared at example.com</email>
+  </record>
+
+  <record type="user">
+    <uid>__exarkun__</uid>
+    <short-name>exarkun</short-name>
+    <full-name>Jean-Paul Calderone</full-name>
+    <password>nucraxe</password>
+    <email>exarkun at devnull.twistedmatrix.com</email>
+  </record>
+
+  <record type="user">
+    <uid>__dreid__</uid>
+    <short-name>dreid</short-name>
+    <full-name>David Reid</full-name>
+    <password>dierd</password>
+    <email>dreid at devnull.twistedmatrix.com</email>
+  </record>
+
+  <record> <!-- type defaults to "user" -->
+    <uid>__joe__</uid>
+    <short-name>joe</short-name>
+    <full-name>Joe Schmoe</full-name>
+    <password>eoj</password>
+    <email>joe at example.com</email>
+  </record>
+
+  <record> <!-- type defaults to "user" -->
+    <uid>__alyssa__</uid>
+    <short-name>alyssa</short-name>
+    <full-name>Alyssa P. Hacker</full-name>
+    <password>assyla</password>
+    <email>alyssa at example.com</email>
+  </record>
+
+</directory>
+"""
+
+
+testXMLConfigGroups = """<?xml version="1.0" encoding="utf-8"?>
+
+<directory realm="Groups Realm">
+
+  <record type="group">
+    <uid>__calendar-dev__</uid>
+    <short-name>calendar-dev</short-name>
+    <full-name>Calendar Server developers</full-name>
+    <email>dev at bitbucket.calendarserver.org</email>
+    <member-uid>__wsanchez__</member-uid>
+    <member-uid>__glyph__</member-uid>
+    <member-uid>__sagen__</member-uid>
+    <member-uid>__cdaboo__</member-uid>
+    <member-uid>__dre__</member-uid>
+  </record>
+
+  <record type="group">
+    <uid>__twisted__</uid>
+    <short-name>twisted</short-name>
+    <full-name>Twisted Matrix Laboratories</full-name>
+    <email>hack at devnull.twistedmatrix.com</email>
+    <member-uid>__wsanchez__</member-uid>
+    <member-uid>__glyph__</member-uid>
+    <member-uid>__exarkun__</member-uid>
+    <member-uid>__dreid__</member-uid>
+    <member-uid>__dre__</member-uid>
+  </record>
+
+  <record type="group">
+    <uid>__developers__</uid>
+    <short-name>developers</short-name>
+    <full-name>All Developers</full-name>
+    <member-uid>__calendar-dev__</member-uid>
+    <member-uid>__twisted__</member-uid>
+    <member-uid>__alyssa__</member-uid>
+  </record>
+
+</directory>
+"""

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_directory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_directory.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_directory.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,7 +15,7 @@
 ##
 
 """
-Generic directory service base implementation tests
+Generic directory service base implementation tests.
 """
 
 from zope.interface.verify import verifyObject, BrokenMethodImplementation
@@ -24,7 +24,7 @@
 from twisted.trial.unittest import SkipTest
 from twisted.internet.defer import inlineCallbacks
 
-from twext.who.idirectory import QueryNotSupportedError
+from twext.who.idirectory import QueryNotSupportedError, NotAllowedError
 from twext.who.idirectory import RecordType, FieldName
 from twext.who.idirectory import IDirectoryService, IDirectoryRecord
 from twext.who.directory import DirectoryService, DirectoryRecord
@@ -35,7 +35,7 @@
     realmName = "xyzzy"
 
 
-    def _testService(self):
+    def service(self):
         if not hasattr(self, "_service"):
             self._service = DirectoryService(self.realmName)
         return self._service
@@ -44,7 +44,7 @@
 
 class DirectoryServiceTest(BaseTest):
     def test_interface(self):
-        service = self._testService()
+        service = self.service()
         try:
             verifyObject(IDirectoryService, service)
         except BrokenMethodImplementation as e:
@@ -52,54 +52,92 @@
 
 
     def test_init(self):
-        service = self._testService()
+        service = self.service()
         self.assertEquals(service.realmName, self.realmName)
 
 
     def test_repr(self):
-        service = self._testService()
+        service = self.service()
         self.assertEquals(repr(service), "<DirectoryService 'xyzzy'>")
 
 
-    @inlineCallbacks
     def test_recordTypes(self):
-        service = self._testService()
+        service = self.service()
         self.assertEquals(
-            set((yield service.recordTypes())),
+            set(service.recordTypes()),
             set(service.recordType.iterconstants())
         )
 
 
     @inlineCallbacks
     def test_recordsFromQueryNone(self):
-        service = self._testService()
+        service = self.service()
         records = (yield service.recordsFromQuery(()))
         for record in records:
             self.failTest("No records expected")
 
 
     def test_recordsFromQueryBogus(self):
-        service = self._testService()
+        service = self.service()
         self.assertFailure(service.recordsFromQuery((object(),)), QueryNotSupportedError)
 
 
     def test_recordWithUID(self):
         raise SkipTest("Subclasses should implement this test.")
 
+
     def test_recordWithGUID(self):
         raise SkipTest("Subclasses should implement this test.")
 
+
     def test_recordsWithRecordType(self):
         raise SkipTest("Subclasses should implement this test.")
 
+
     def test_recordWithShortName(self):
         raise SkipTest("Subclasses should implement this test.")
 
+
     def test_recordsWithEmailAddress(self):
         raise SkipTest("Subclasses should implement this test.")
 
 
 
+class DirectoryServiceImmutableTest(BaseTest):
+    def test_updateRecordsNotAllowed(self):
+        service = self.service()
+
+        newRecord = DirectoryRecord(
+            service,
+            fields = {
+                service.fieldName.uid:        "__plugh__",
+                service.fieldName.recordType: service.recordType.user,
+                service.fieldName.shortNames: ("plugh",),
+            }
+        )
+
+        self.assertFailure(
+            service.updateRecords((newRecord,), create=True),
+            NotAllowedError,
+        )
+
+        self.assertFailure(
+            service.updateRecords((newRecord,), create=False),
+            NotAllowedError,
+        )
+
+
+    def test_removeRecordsNotAllowed(self):
+        service = self.service()
+
+        service.removeRecords(())
+        self.assertFailure(
+            service.removeRecords(("foo",)),
+            NotAllowedError,
+        )
+
+
+
 class DirectoryRecordTest(BaseTest):
     fields_wsanchez = {
         FieldName.uid:            "UID:wsanchez",
@@ -130,7 +168,7 @@
         if fields is None:
             fields = self.fields_wsanchez
         if service is None:
-            service = self._testService()
+            service = self.service()
         return DirectoryRecord(service, fields)
 
 
@@ -143,7 +181,7 @@
 
 
     def test_init(self):
-        service  = self._testService()
+        service  = self.service()
         wsanchez = self._testRecord(self.fields_wsanchez, service=service)
 
         self.assertEquals(wsanchez.service, service)

Added: CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_expression.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_expression.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_expression.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,55 @@
+##
+# 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.
+##
+
+"""
+Directory service expression tests.
+"""
+
+from twisted.trial import unittest
+
+from twext.who.idirectory import FieldName
+from twext.who.expression import MatchExpression, MatchType, MatchFlags
+
+
+
+class MatchExpressionTest(unittest.TestCase):
+    def test_repr(self):
+        self.assertEquals(
+            "<MatchExpression: 'full names' equals 'Wilfredo Sanchez'>",
+            repr(MatchExpression(
+                FieldName.fullNames,
+                "Wilfredo Sanchez",
+            )),
+        )
+
+        self.assertEquals(
+            "<MatchExpression: 'full names' contains 'Sanchez'>",
+            repr(MatchExpression(
+                FieldName.fullNames,
+                "Sanchez",
+                matchType=MatchType.contains,
+            )),
+        )
+
+        self.assertEquals(
+            "<MatchExpression: 'full names' starts with 'Wilfredo' (not)>",
+            repr(MatchExpression(
+                FieldName.fullNames,
+                "Wilfredo",
+                matchType=MatchType.startsWith,
+                flags=MatchFlags.NOT,
+            )),
+        )

Added: CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_util.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_util.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,120 @@
+##
+# 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.
+##
+
+"""
+Directory service utility tests.
+"""
+
+from twisted.trial import unittest
+from twisted.python.constants import Names, NamedConstant
+from twisted.python.constants import Flags, FlagConstant
+
+from twext.who.idirectory import DirectoryServiceError
+from twext.who.util import ConstantsContainer
+from twext.who.util import uniqueResult, describe
+
+
+
+class Tools(Names):
+    hammer      = NamedConstant()
+    screwdriver = NamedConstant()
+
+    hammer.description      = "nail pounder"
+    screwdriver.description = "screw twister"
+
+
+
+class Instruments(Names):
+    hammer = NamedConstant()
+    chisel = NamedConstant()
+
+
+
+class Switches(Flags):
+    r = FlagConstant()
+    g = FlagConstant()
+    b = FlagConstant()
+
+    r.description = "red"
+    g.description = "green"
+    b.description = "blue"
+
+    black = FlagConstant()
+
+
+
+class ConstantsContainerTest(unittest.TestCase):
+    def test_conflict(self):
+        constants = set((Tools.hammer, Instruments.hammer))
+        self.assertRaises(ValueError, ConstantsContainer, constants)
+
+
+    def test_attrs(self):
+        constants = set((Tools.hammer, Tools.screwdriver, Instruments.chisel))
+        container = ConstantsContainer(constants)
+
+        self.assertEquals(container.hammer, Tools.hammer)
+        self.assertEquals(container.screwdriver, Tools.screwdriver)
+        self.assertEquals(container.chisel, Instruments.chisel)
+        self.assertRaises(AttributeError, lambda: container.plugh)
+
+
+    def test_iterconstants(self):
+        constants = set((Tools.hammer, Tools.screwdriver, Instruments.chisel))
+        container = ConstantsContainer(constants)
+
+        self.assertEquals(
+            set(container.iterconstants()),
+            constants,
+        )
+
+    def test_lookupByName(self):
+        constants = set((Instruments.hammer, Tools.screwdriver, Instruments.chisel))
+        container = ConstantsContainer(constants)
+
+        self.assertEquals(
+            container.lookupByName("hammer"),
+            Instruments.hammer,
+        )
+        self.assertEquals(
+            container.lookupByName("screwdriver"),
+            Tools.screwdriver,
+        )
+        self.assertEquals(
+            container.lookupByName("chisel"),
+            Instruments.chisel,
+        )
+
+        self.assertRaises(
+            ValueError,
+            container.lookupByName, "plugh",
+        )
+
+
+
+class UtilTest(unittest.TestCase):
+    def test_uniqueResult(self):
+        self.assertEquals(1, uniqueResult((1,)))
+        self.assertRaises(DirectoryServiceError, uniqueResult, (1,2,3))
+
+    def test_describe(self):
+        self.assertEquals("nail pounder", describe(Tools.hammer))
+        self.assertEquals("hammer", describe(Instruments.hammer))
+
+    def test_describeFlags(self):
+        self.assertEquals("blue", describe(Switches.b))
+        self.assertEquals("red|green", describe(Switches.r|Switches.g))
+        self.assertEquals("blue|black", describe(Switches.b|Switches.black))

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_xml.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_xml.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/test/test_xml.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -15,17 +15,18 @@
 ##
 
 """
-XML directory service tests
+XML directory service tests.
 """
 
 from time import sleep
 
+from twisted.trial import unittest
 from twisted.python.filepath import FilePath
 from twisted.internet.defer import inlineCallbacks
 
 from twext.who.idirectory import NoSuchRecordError
-from twext.who.idirectory import DirectoryQueryMatchExpression
-from twext.who.idirectory import Operand, MatchType, QueryFlags
+from twext.who.idirectory import Operand
+from twext.who.expression import MatchExpression, MatchType, MatchFlags
 from twext.who.xml import ParseError
 from twext.who.xml import DirectoryService, DirectoryRecord
 
@@ -33,175 +34,119 @@
 
 
 
-xmlRealmName = "Test Realm"
+class BaseTest(unittest.TestCase):
+    def service(self, xmlData=None):
+        return xmlService(self.mktemp(), xmlData)
 
-testXMLConfig = """<?xml version="1.0" encoding="utf-8"?>
 
-<directory realm="xyzzy">
+    def assertRecords(self, records, uids):
+        self.assertEquals(
+            frozenset((record.uid for record in records)),
+            frozenset((uids)),
+        )
 
-  <record type="user">
-    <uid>__wsanchez__</uid>
-    <short-name>wsanchez</short-name>
-    <short-name>wilfredo_sanchez</short-name>
-    <full-name>Wilfredo Sanchez</full-name>
-    <password>zehcnasw</password>
-    <email>wsanchez at bitbucket.calendarserver.org</email>
-    <email>wsanchez at devnull.twistedmatrix.com</email>
-  </record>
 
-  <record type="user">
-    <uid>__glyph__</uid>
-    <short-name>glyph</short-name>
-    <full-name>Glyph Lefkowitz</full-name>
-    <password>hpylg</password>
-    <email>glyph at bitbucket.calendarserver.org</email>
-    <email>glyph at devnull.twistedmatrix.com</email>
-  </record>
 
-  <record type="user">
-    <uid>__sagen__</uid>
-    <short-name>sagen</short-name>
-    <full-name>Morgen Sagen</full-name>
-    <password>negas</password>
-    <email>sagen at bitbucket.calendarserver.org</email>
-    <email>shared at example.com</email>
-  </record>
+class DirectoryServiceBaseTest(BaseTest, test_directory.DirectoryServiceTest):
+    def test_repr(self):
+        service = self.service()
 
-  <record type="user">
-    <uid>__cdaboo__</uid>
-    <short-name>cdaboo</short-name>
-    <full-name>Cyrus Daboo</full-name>
-    <password>suryc</password>
-    <email>cdaboo at bitbucket.calendarserver.org</email>
-  </record>
+        self.assertEquals(repr(service), "<TestService (not loaded)>")
+        service.loadRecords()
+        self.assertEquals(repr(service), "<TestService 'xyzzy'>")
 
-  <record type="user">
-    <uid>__dre__</uid>
-    <short-name>dre</short-name>
-    <full-name>Andre LaBranche</full-name>
-    <password>erd</password>
-    <email>dre at bitbucket.calendarserver.org</email>
-    <email>shared at example.com</email>
-  </record>
 
-  <record type="user">
-    <uid>__exarkun__</uid>
-    <short-name>exarkun</short-name>
-    <full-name>Jean-Paul Calderone</full-name>
-    <password>nucraxe</password>
-    <email>exarkun at devnull.twistedmatrix.com</email>
-  </record>
+    @inlineCallbacks
+    def test_recordWithUID(self):
+        service = self.service()
 
-  <record type="user">
-    <uid>__dreid__</uid>
-    <short-name>dreid</short-name>
-    <full-name>David Reid</full-name>
-    <password>dierd</password>
-    <email>dreid at devnull.twistedmatrix.com</email>
-  </record>
+        record = (yield service.recordWithUID("__null__"))
+        self.assertEquals(record, None)
 
-  <record> <!-- type defaults to "user" -->
-    <uid>__joe__</uid>
-    <short-name>joe</short-name>
-    <full-name>Joe Schmoe</full-name>
-    <password>eoj</password>
-    <email>joe at example.com</email>
-  </record>
+        record = (yield service.recordWithUID("__wsanchez__"))
+        self.assertEquals(record.uid, "__wsanchez__")
 
-  <record>
-    <uid>__alyssa__</uid>
-    <short-name>alyssa</short-name>
-    <full-name>Alyssa P. Hacker</full-name>
-    <password>assyla</password>
-    <email>alyssa at example.com</email>
-  </record>
 
-  <record type="group">
-    <uid>__calendar-dev__</uid>
-    <short-name>calendar-dev</short-name>
-    <full-name>Calendar Server developers</full-name>
-    <email>dev at bitbucket.calendarserver.org</email>
-    <member-uid>__wsanchez__</member-uid>
-    <member-uid>__glyph__</member-uid>
-    <member-uid>__sagen__</member-uid>
-    <member-uid>__cdaboo__</member-uid>
-    <member-uid>__dre__</member-uid>
-  </record>
+    @inlineCallbacks
+    def test_recordWithGUID(self):
+        service = self.service()
+        record = (yield service.recordWithGUID("6C495FCD-7E78-4D5C-AA66-BC890AD04C9D"))
+        self.assertEquals(record, None)
 
-  <record type="group">
-    <uid>__twisted__</uid>
-    <short-name>twisted</short-name>
-    <full-name>Twisted Matrix Laboratories</full-name>
-    <email>hack at devnull.twistedmatrix.com</email>
-    <member-uid>__wsanchez__</member-uid>
-    <member-uid>__glyph__</member-uid>
-    <member-uid>__exarkun__</member-uid>
-    <member-uid>__dreid__</member-uid>
-    <member-uid>__dre__</member-uid>
-  </record>
+    @inlineCallbacks
+    def test_recordsWithRecordType(self):
+        service = self.service()
 
-  <record type="group">
-    <uid>__developers__</uid>
-    <short-name>developers</short-name>
-    <full-name>All Developers</full-name>
-    <member-uid>__calendar-dev__</member-uid>
-    <member-uid>__twisted__</member-uid>
-    <member-uid>__alyssa__</member-uid>
-  </record>
+        records = (yield service.recordsWithRecordType(object()))
+        self.assertEquals(set(records), set())
 
-</directory>
-"""
+        records = (yield service.recordsWithRecordType(service.recordType.user))
+        self.assertRecords(records,
+            (
+                "__wsanchez__",
+                "__glyph__",
+                "__sagen__",
+                "__cdaboo__",
+                "__dre__",
+                "__exarkun__",
+                "__dreid__",
+                "__alyssa__",
+                "__joe__",
+            ),
+        )
 
+        records = (yield service.recordsWithRecordType(service.recordType.group))
+        self.assertRecords(records,
+            (
+                "__calendar-dev__",
+                "__twisted__",
+                "__developers__",
+            ),
+        )
 
 
-class BaseTest(object):
-    def _testService(self, xmlData=None):
-        if xmlData is None:
-            xmlData = testXMLConfig
+    @inlineCallbacks
+    def test_recordWithShortName(self):
+        service = self.service()
 
-        filePath = FilePath(self.mktemp())
-        filePath.setContent(xmlData)
+        record = (yield service.recordWithShortName(service.recordType.user, "null"))
+        self.assertEquals(record, None)
 
-        class TestService(DirectoryService):
-            def query(self, field, value, matchType=MatchType.equals, flags=None):
-                name = getattr(self.fieldName, field)
-                assert name is not None
-                return DirectoryQueryMatchExpression(
-                    name, value,
-                    matchType = matchType,
-                    flags = flags,
-                )
+        record = (yield service.recordWithShortName(service.recordType.user, "wsanchez"))
+        self.assertEquals(record.uid, "__wsanchez__")
 
-        return TestService(filePath)
+        record = (yield service.recordWithShortName(service.recordType.user, "wilfredo_sanchez"))
+        self.assertEquals(record.uid, "__wsanchez__")
 
 
+    @inlineCallbacks
+    def test_recordsWithEmailAddress(self):
+        service = self.service()
 
-class DirectoryServiceTest(BaseTest, test_directory.DirectoryServiceTest):
-    def test_repr(self):
-        service = self._testService()
+        records = (yield service.recordsWithEmailAddress("wsanchez at bitbucket.calendarserver.org"))
+        self.assertRecords(records, ("__wsanchez__",))
 
-        self.assertEquals(repr(service), "<TestService (not loaded)>")
-        service.loadRecords()
-        self.assertEquals(repr(service), "<TestService 'xyzzy'>")
+        records = (yield service.recordsWithEmailAddress("wsanchez at devnull.twistedmatrix.com"))
+        self.assertRecords(records, ("__wsanchez__",))
 
+        records = (yield service.recordsWithEmailAddress("shared at example.com"))
+        self.assertRecords(records, ("__sagen__", "__dre__"))
 
-    def assertRecords(self, records, uids):
-        self.assertEquals(
-            frozenset((record.uid for record in records)),
-            frozenset((uids)),
-        )
 
 
+class DirectoryServiceRealmTest(BaseTest):
     def test_realmNameImmutable(self):
         def setRealmName():
-            service = self._testService()
+            service = self.service()
             service.realmName = "foo"
 
         self.assertRaises(AssertionError, setRealmName)
 
 
+
+class DirectoryServiceParsingTest(BaseTest):
     def test_reloadInterval(self):
-        service = self._testService()
+        service = self.service()
 
         service.loadRecords(stat=False)
         lastRefresh = service._lastRefresh
@@ -213,7 +158,7 @@
 
 
     def test_reloadStat(self):
-        service = self._testService()
+        service = self.service()
 
         service.loadRecords(loadNow=True)
         lastRefresh = service._lastRefresh
@@ -225,13 +170,13 @@
 
 
     def test_badXML(self):
-        service = self._testService(xmlData="Hello")
+        service = self.service(xmlData="Hello")
 
         self.assertRaises(ParseError, service.loadRecords)
 
 
     def test_badRootElement(self):
-        service = self._testService(xmlData=
+        service = self.service(xmlData=
 """<?xml version="1.0" encoding="utf-8"?>
 
 <frobnitz />
@@ -248,7 +193,7 @@
 
 
     def test_noRealmName(self):
-        service = self._testService(xmlData=
+        service = self.service(xmlData=
 """<?xml version="1.0" encoding="utf-8"?>
 
 <directory />
@@ -264,86 +209,53 @@
             raise AssertionError
 
 
-    @inlineCallbacks
-    def test_recordWithUID(self):
-        service = self._testService()
+    def test_unknownFieldElementsClean(self):
+        service = self.service()
+        self.assertEquals(set(service.unknownFieldElements), set())
 
-        record = (yield service.recordWithUID("__null__"))
-        self.assertEquals(record, None)
 
-        record = (yield service.recordWithUID("__wsanchez__"))
-        self.assertEquals(record.uid, "__wsanchez__")
+    def test_unknownFieldElementsDirty(self):
+        service = self.service(xmlData=
+"""<?xml version="1.0" encoding="utf-8"?>
 
+<directory realm="Unknown Record Types">
+  <record type="user">
+    <uid>__wsanchez__</uid>
+    <short-name>wsanchez</short-name>
+    <political-affiliation>Community and Freedom Party</political-affiliation>
+  </record>
+</directory>
+"""
+        )
+        self.assertEquals(set(service.unknownFieldElements), set(("political-affiliation",)))
 
-    @inlineCallbacks
-    def test_recordWithGUID(self):
-        service = self._testService()
-        record = (yield service.recordWithGUID("6C495FCD-7E78-4D5C-AA66-BC890AD04C9D"))
-        self.assertEquals(record, None)
 
-    @inlineCallbacks
-    def test_recordsWithRecordType(self):
-        service = self._testService()
+    def test_unknownRecordTypesClean(self):
+        service = self.service()
+        self.assertEquals(set(service.unknownRecordTypes), set())
 
-        records = (yield service.recordsWithRecordType(object()))
-        self.assertEquals(set(records), set())
 
-        records = (yield service.recordsWithRecordType(service.recordType.user))
-        self.assertRecords(records,
-            (
-                "__wsanchez__",
-                "__glyph__",
-                "__sagen__",
-                "__cdaboo__",
-                "__dre__",
-                "__exarkun__",
-                "__dreid__",
-                "__alyssa__",
-                "__joe__",
-            ),
-        )
+    def test_unknownRecordTypesDirty(self):
+        service = self.service(xmlData=
+"""<?xml version="1.0" encoding="utf-8"?>
 
-        records = (yield service.recordsWithRecordType(service.recordType.group))
-        self.assertRecords(records,
-            (
-                "__calendar-dev__",
-                "__twisted__",
-                "__developers__",
-            ),
+<directory realm="Unknown Record Types">
+  <record type="camera">
+    <uid>__d600__</uid>
+    <short-name>d600</short-name>
+    <full-name>Nikon D600</full-name>
+  </record>
+</directory>
+"""
         )
+        self.assertEquals(set(service.unknownRecordTypes), set(("camera",)))
 
 
-    @inlineCallbacks
-    def test_recordWithShortName(self):
-        service = self._testService()
 
-        record = (yield service.recordWithShortName(service.recordType.user, "null"))
-        self.assertEquals(record, None)
-
-        record = (yield service.recordWithShortName(service.recordType.user, "wsanchez"))
-        self.assertEquals(record.uid, "__wsanchez__")
-
-        record = (yield service.recordWithShortName(service.recordType.user, "wilfredo_sanchez"))
-        self.assertEquals(record.uid, "__wsanchez__")
-
-
+class DirectoryServiceQueryTest(BaseTest):
     @inlineCallbacks
-    def test_recordsWithEmailAddress(self):
-        service = self._testService()
-
-        records = (yield service.recordsWithEmailAddress("wsanchez at bitbucket.calendarserver.org"))
-        self.assertRecords(records, ("__wsanchez__",))
-
-        records = (yield service.recordsWithEmailAddress("wsanchez at devnull.twistedmatrix.com"))
-        self.assertRecords(records, ("__wsanchez__",))
-
-        records = (yield service.recordsWithEmailAddress("shared at example.com"))
-        self.assertRecords(records, ("__sagen__", "__dre__"))
-
-
-    @inlineCallbacks
     def test_queryAnd(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery(
             (
                 service.query("emailAddresses", "shared at example.com"),
@@ -355,8 +267,24 @@
 
 
     @inlineCallbacks
+    def test_queryAndNoneFirst(self):
+        """
+        Test optimized case, where first expression yields no results.
+        """
+        service = self.service()
+        records = yield service.recordsFromQuery(
+            (
+                service.query("emailAddresses", "nobody at example.com"),
+                service.query("shortNames", "sagen"),
+            ),
+            operand=Operand.AND
+        )
+        self.assertRecords(records, ())
+
+
+    @inlineCallbacks
     def test_queryOr(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery(
             (
                 service.query("emailAddresses", "shared at example.com"),
@@ -369,11 +297,11 @@
 
     @inlineCallbacks
     def test_queryNot(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery(
             (
                 service.query("emailAddresses", "shared at example.com"),
-                service.query("shortNames", "sagen", flags=QueryFlags.NOT),
+                service.query("shortNames", "sagen", flags=MatchFlags.NOT),
             ),
             operand=Operand.AND
         )
@@ -382,11 +310,11 @@
 
     @inlineCallbacks
     def test_queryNotNoIndex(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery(
             (
                 service.query("emailAddresses", "shared at example.com"),
-                service.query("fullNames", "Andre LaBranche", flags=QueryFlags.NOT),
+                service.query("fullNames", "Andre LaBranche", flags=MatchFlags.NOT),
             ),
             operand=Operand.AND
         )
@@ -395,25 +323,25 @@
 
     @inlineCallbacks
     def test_queryCaseInsensitive(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
-            service.query("shortNames", "SagEn", flags=QueryFlags.caseInsensitive),
+            service.query("shortNames", "SagEn", flags=MatchFlags.caseInsensitive),
         ))
         self.assertRecords(records, ("__sagen__",))
 
 
     @inlineCallbacks
     def test_queryCaseInsensitiveNoIndex(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
-            service.query("fullNames", "moRGen SAGen", flags=QueryFlags.caseInsensitive),
+            service.query("fullNames", "moRGen SAGen", flags=MatchFlags.caseInsensitive),
         ))
         self.assertRecords(records, ("__sagen__",))
 
 
     @inlineCallbacks
     def test_queryStartsWith(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query("shortNames", "wil", matchType=MatchType.startsWith),
         ))
@@ -422,7 +350,7 @@
 
     @inlineCallbacks
     def test_queryStartsWithNoIndex(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query("fullNames", "Wilfredo", matchType=MatchType.startsWith),
         ))
@@ -431,12 +359,12 @@
 
     @inlineCallbacks
     def test_queryStartsWithNot(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query(
                 "shortNames", "w",
                 matchType = MatchType.startsWith,
-                flags = QueryFlags.NOT,
+                flags = MatchFlags.NOT,
             ),
         ))
         self.assertRecords(
@@ -465,12 +393,12 @@
         included or not?  It is, because one matches the query, but
         should NOT require that all match?
         """
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query(
                 "shortNames", "wil",
                 matchType = MatchType.startsWith,
-                flags = QueryFlags.NOT,
+                flags = MatchFlags.NOT,
             ),
         ))
         self.assertRecords(
@@ -494,12 +422,12 @@
 
     @inlineCallbacks
     def test_queryStartsWithNotNoIndex(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query(
                 "fullNames", "Wilfredo",
                 matchType = MatchType.startsWith,
-                flags = QueryFlags.NOT,
+                flags = MatchFlags.NOT,
             ),
         ))
         self.assertRecords(
@@ -522,12 +450,12 @@
 
     @inlineCallbacks
     def test_queryStartsWithCaseInsensitive(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query(
                 "shortNames", "WIL",
                 matchType = MatchType.startsWith,
-                flags = QueryFlags.caseInsensitive,
+                flags = MatchFlags.caseInsensitive,
             ),
         ))
         self.assertRecords(records, ("__wsanchez__",))
@@ -535,12 +463,12 @@
 
     @inlineCallbacks
     def test_queryStartsWithCaseInsensitiveNoIndex(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query(
                 "fullNames", "wilfrEdo",
                 matchType = MatchType.startsWith,
-                flags = QueryFlags.caseInsensitive,
+                flags = MatchFlags.caseInsensitive,
             ),
         ))
         self.assertRecords(records, ("__wsanchez__",))
@@ -548,7 +476,7 @@
 
     @inlineCallbacks
     def test_queryContains(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query("shortNames", "sanchez", matchType=MatchType.contains),
         ))
@@ -557,7 +485,7 @@
 
     @inlineCallbacks
     def test_queryContainsNoIndex(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query("fullNames", "fred", matchType=MatchType.contains),
         ))
@@ -566,12 +494,12 @@
 
     @inlineCallbacks
     def test_queryContainsNot(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query(
                 "shortNames", "sanchez",
                 matchType = MatchType.contains,
-                flags = QueryFlags.NOT,
+                flags = MatchFlags.NOT,
             ),
         ))
         self.assertRecords(
@@ -594,12 +522,12 @@
 
     @inlineCallbacks
     def test_queryContainsNotNoIndex(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query(
                 "fullNames", "fred",
                 matchType = MatchType.contains,
-                flags = QueryFlags.NOT,
+                flags = MatchFlags.NOT,
             ),
         ))
         self.assertRecords(
@@ -622,12 +550,12 @@
 
     @inlineCallbacks
     def test_queryContainsCaseInsensitive(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query(
                 "shortNames", "Sanchez",
                 matchType=MatchType.contains,
-                flags=QueryFlags.caseInsensitive,
+                flags=MatchFlags.caseInsensitive,
             ),
         ))
         self.assertRecords(records, ("__wsanchez__",))
@@ -635,62 +563,22 @@
 
     @inlineCallbacks
     def test_queryContainsCaseInsensitiveNoIndex(self):
-        service = self._testService()
+        service = self.service()
         records = yield service.recordsFromQuery((
             service.query(
                 "fullNames", "frEdo",
                 matchType=MatchType.contains,
-                flags=QueryFlags.caseInsensitive,
+                flags=MatchFlags.caseInsensitive,
             ),
         ))
         self.assertRecords(records, ("__wsanchez__",))
 
 
-    def test_unknownRecordTypesClean(self):
-        service = self._testService()
-        self.assertEquals(set(service.unknownRecordTypes), set())
 
-
-    def test_unknownRecordTypesDirty(self):
-        service = self._testService(xmlData=
-"""<?xml version="1.0" encoding="utf-8"?>
-
-<directory realm="Unknown Record Types">
-  <record type="camera">
-    <uid>__d600__</uid>
-    <short-name>d600</short-name>
-    <full-name>Nikon D600</full-name>
-  </record>
-</directory>
-"""
-        )
-        self.assertEquals(set(service.unknownRecordTypes), set(("camera",)))
-
-
-    def test_unknownFieldElementsClean(self):
-        service = self._testService()
-        self.assertEquals(set(service.unknownFieldElements), set())
-
-
-    def test_unknownFieldElementsDirty(self):
-        service = self._testService(xmlData=
-"""<?xml version="1.0" encoding="utf-8"?>
-
-<directory realm="Unknown Record Types">
-  <record type="user">
-    <uid>__wsanchez__</uid>
-    <short-name>wsanchez</short-name>
-    <political-affiliation>Community and Freedom Party</political-affiliation>
-  </record>
-</directory>
-"""
-        )
-        self.assertEquals(set(service.unknownFieldElements), set(("political-affiliation",)))
-
-
+class DirectoryServiceMutableTest(BaseTest):
     @inlineCallbacks
     def test_updateRecord(self):
-        service = self._testService()
+        service = self.service()
 
         record = (yield service.recordWithUID("__wsanchez__"))
 
@@ -712,7 +600,7 @@
 
     @inlineCallbacks
     def test_addRecord(self):
-        service = self._testService()
+        service = self.service()
 
         newRecord = DirectoryRecord(
             service,
@@ -736,7 +624,7 @@
 
 
     def test_addRecordNoCreate(self):
-        service = self._testService()
+        service = self.service()
 
         newRecord = DirectoryRecord(
             service,
@@ -752,7 +640,7 @@
 
     @inlineCallbacks
     def test_removeRecord(self):
-        service = self._testService()
+        service = self.service()
 
         yield service.removeRecords(("__wsanchez__",))
 
@@ -765,7 +653,7 @@
 
 
     def test_removeRecordNoExist(self):
-        service = self._testService()
+        service = self.service()
 
         return service.removeRecords(("__plugh__",))
 
@@ -774,7 +662,7 @@
 class DirectoryRecordTest(BaseTest, test_directory.DirectoryRecordTest):
     @inlineCallbacks
     def test_members(self):
-        service = self._testService()
+        service = self.service()
 
         record = (yield service.recordWithUID("__wsanchez__"))
         members = (yield record.members())
@@ -806,7 +694,7 @@
 
     @inlineCallbacks
     def test_groups(self):
-        service = self._testService()
+        service = self.service()
 
         record = (yield service.recordWithUID("__wsanchez__"))
         groups = (yield record.groups())
@@ -817,3 +705,153 @@
                 "__twisted__",
             ))
         )
+
+
+
+class QueryMixIn(object):
+    def query(self, field, value, matchType=MatchType.equals, flags=None):
+        name = getattr(self.fieldName, field)
+        assert name is not None
+        return MatchExpression(
+            name, value,
+            matchType = matchType,
+            flags = flags,
+        )
+
+
+
+class TestService(DirectoryService, QueryMixIn):
+    pass
+
+
+
+def xmlService(tmp, xmlData=None, serviceClass=None):
+    if xmlData is None:
+        xmlData = testXMLConfig
+
+    if serviceClass is None:
+        serviceClass = TestService
+
+    filePath = FilePath(tmp)
+    filePath.setContent(xmlData)
+
+    return serviceClass(filePath)
+
+
+
+testXMLConfig = """<?xml version="1.0" encoding="utf-8"?>
+
+<directory realm="xyzzy">
+
+  <record type="user">
+    <uid>__wsanchez__</uid>
+    <short-name>wsanchez</short-name>
+    <short-name>wilfredo_sanchez</short-name>
+    <full-name>Wilfredo Sanchez</full-name>
+    <password>zehcnasw</password>
+    <email>wsanchez at bitbucket.calendarserver.org</email>
+    <email>wsanchez at devnull.twistedmatrix.com</email>
+  </record>
+
+  <record type="user">
+    <uid>__glyph__</uid>
+    <short-name>glyph</short-name>
+    <full-name>Glyph Lefkowitz</full-name>
+    <password>hpylg</password>
+    <email>glyph at bitbucket.calendarserver.org</email>
+    <email>glyph at devnull.twistedmatrix.com</email>
+  </record>
+
+  <record type="user">
+    <uid>__sagen__</uid>
+    <short-name>sagen</short-name>
+    <full-name>Morgen Sagen</full-name>
+    <password>negas</password>
+    <email>sagen at bitbucket.calendarserver.org</email>
+    <email>shared at example.com</email>
+  </record>
+
+  <record type="user">
+    <uid>__cdaboo__</uid>
+    <short-name>cdaboo</short-name>
+    <full-name>Cyrus Daboo</full-name>
+    <password>suryc</password>
+    <email>cdaboo at bitbucket.calendarserver.org</email>
+  </record>
+
+  <record type="user">
+    <uid>__dre__</uid>
+    <short-name>dre</short-name>
+    <full-name>Andre LaBranche</full-name>
+    <password>erd</password>
+    <email>dre at bitbucket.calendarserver.org</email>
+    <email>shared at example.com</email>
+  </record>
+
+  <record type="user">
+    <uid>__exarkun__</uid>
+    <short-name>exarkun</short-name>
+    <full-name>Jean-Paul Calderone</full-name>
+    <password>nucraxe</password>
+    <email>exarkun at devnull.twistedmatrix.com</email>
+  </record>
+
+  <record type="user">
+    <uid>__dreid__</uid>
+    <short-name>dreid</short-name>
+    <full-name>David Reid</full-name>
+    <password>dierd</password>
+    <email>dreid at devnull.twistedmatrix.com</email>
+  </record>
+
+  <record> <!-- type defaults to "user" -->
+    <uid>__joe__</uid>
+    <short-name>joe</short-name>
+    <full-name>Joe Schmoe</full-name>
+    <password>eoj</password>
+    <email>joe at example.com</email>
+  </record>
+
+  <record> <!-- type defaults to "user" -->
+    <uid>__alyssa__</uid>
+    <short-name>alyssa</short-name>
+    <full-name>Alyssa P. Hacker</full-name>
+    <password>assyla</password>
+    <email>alyssa at example.com</email>
+  </record>
+
+  <record type="group">
+    <uid>__calendar-dev__</uid>
+    <short-name>calendar-dev</short-name>
+    <full-name>Calendar Server developers</full-name>
+    <email>dev at bitbucket.calendarserver.org</email>
+    <member-uid>__wsanchez__</member-uid>
+    <member-uid>__glyph__</member-uid>
+    <member-uid>__sagen__</member-uid>
+    <member-uid>__cdaboo__</member-uid>
+    <member-uid>__dre__</member-uid>
+  </record>
+
+  <record type="group">
+    <uid>__twisted__</uid>
+    <short-name>twisted</short-name>
+    <full-name>Twisted Matrix Laboratories</full-name>
+    <email>hack at devnull.twistedmatrix.com</email>
+    <member-uid>__wsanchez__</member-uid>
+    <member-uid>__glyph__</member-uid>
+    <member-uid>__exarkun__</member-uid>
+    <member-uid>__dreid__</member-uid>
+    <member-uid>__dre__</member-uid>
+  </record>
+
+  <record type="group">
+    <uid>__developers__</uid>
+    <short-name>developers</short-name>
+    <full-name>All Developers</full-name>
+    <member-uid>__calendar-dev__</member-uid>
+    <member-uid>__twisted__</member-uid>
+    <member-uid>__alyssa__</member-uid>
+  </record>
+
+</directory>
+"""

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/who/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/util.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/util.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,3 +1,4 @@
+# -*- test-case-name: twext.who.test.test_util -*-
 ##
 # Copyright (c) 2013 Apple Inc. All rights reserved.
 #
@@ -19,71 +20,47 @@
 """
 
 __all__ = [
-    "MergedConstants",
+    "ConstantsContainer",
     "uniqueResult",
     "describe",
     "iterFlags",
 ]
 
-from types import FunctionType
+from twisted.python.constants import FlagConstant
 
-from twisted.python.constants import NamedConstant
-
 from twext.who.idirectory import DirectoryServiceError
 
 
 
-class MergedConstants(object):
+class ConstantsContainer(object):
     """
-    Work-around for the fact that Names is apparently not subclassable
-    and doesn't provide a way to merge multiple Names classes.
+    A container for constants.
     """
-    def __init__(self, *containers):
-        seenNames = set()
-        myContainers = set()
-        for container in containers:
-            for constant in container.iterconstants():
-                if constant.name in seenNames:
-                    raise ValueError(
-                        "Multiple constants with the same name may not be merged: %s"
-                        % (constant.name,)
-                    )
-                seenNames.add(constant.name)
+    def __init__(self, constants):
+        myConstants = {}
+        for constant in constants:
+            if constant.name in myConstants:
+                raise ValueError("Name conflict: %r" % (constant.name,))
+            myConstants[constant.name] = constant
 
-            if isinstance(container, MergedConstants):
-                # Avoid nesting
-                myContainers |= container._containers
-            else:
-                myContainers.add(container)
+        self._constants = myConstants
 
-        self._containers = myContainers
-
     def __getattr__(self, name):
-        for container in self._containers:
-            attr = getattr(container, name, None)
-            if attr is not None:
-                # Named constant or static method
-                if isinstance(attr, (NamedConstant, FunctionType)):
-                    return attr
+        try:
+            return self._constants[name]
+        except KeyError:
+            raise AttributeError(name)
 
-        raise AttributeError(name)
-
     def iterconstants(self):
-        for container in self._containers:
-            for constant in container.iterconstants():
-                yield constant
+        return self._constants.itervalues()
 
     def lookupByName(self, name):
-        for container in self._containers:
-            try:
-                return container.lookupByName(name)
-            except ValueError:
-                pass
+        try:
+            return self._constants[name]
+        except KeyError:
+            raise ValueError(name)
 
-        raise ValueError(name)
 
-
-
 def uniqueResult(values):
     result = None
     for value in values:
@@ -95,7 +72,13 @@
 
 
 def describe(constant):
-    return getattr(constant, "description", str(constant))
+    if isinstance(constant, FlagConstant):
+        parts = []
+        for flag in iterFlags(constant):
+            parts.append(getattr(flag, "description", flag.name))
+        return "|".join(parts)
+    else:
+        return getattr(constant, "description", constant.name)
 
 
 def iterFlags(flags):

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/who/xml.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/who/xml.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/who/xml.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,3 +1,4 @@
+# -*- test-case-name: twext.who.test.test_xml -*-
 ##
 # Copyright (c) 2006-2013 Apple Inc. All rights reserved.
 #
@@ -127,12 +128,13 @@
     attribute = Attribute
     value     = Value
 
+    refreshInterval = 4
 
-    def __init__(self, filePath, refreshInterval=4):
+
+    def __init__(self, filePath):
         BaseDirectoryService.__init__(self, realmName=noRealmName)
 
         self.filePath = filePath
-        self.refreshInterval = refreshInterval
 
 
     def __repr__(self):
@@ -255,7 +257,7 @@
                 values = record.fields.get(fieldName, None)
 
                 if values is not None:
-                    if not self.fieldName.isMultiValue(fieldName):
+                    if not BaseFieldName.isMultiValue(fieldName):
                         values = (values,)
 
                     for value in values:
@@ -302,7 +304,7 @@
 
             value = fieldNode.text.encode("utf-8")
 
-            if self.fieldName.isMultiValue(fieldName):
+            if BaseFieldName.isMultiValue(fieldName):
                 values = fields.setdefault(fieldName, [])
                 values.append(value)
             else:
@@ -363,7 +365,7 @@
                     if name in fieldNames:
                         tag = fieldNames[name]
 
-                        if self.fieldName.isMultiValue(name):
+                        if BaseFieldName.isMultiValue(name):
                             values = value
                         else:
                             values = (value,)

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/backup.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/backup.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/backup.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 Utility code for backup and restore
@@ -42,12 +43,12 @@
 
 def debug(string):
     if VERBOSE:
-        print "DEBUG:", string
+        print("DEBUG:", string)
 
 
 def funclog(string):
     if FUNCLOG:
-        print "FUNCLOG:", string
+        print("FUNCLOG:", string)
 
 
 def logFuncCall(func):

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/datafilters/hiddeninstance.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/datafilters/hiddeninstance.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/datafilters/hiddeninstance.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -33,13 +33,11 @@
 
         @param ical: iCalendar object
         @type ical: L{Component} or C{str}
-        
+
         @return: L{Component} for the filtered calendar data
         """
-        
+
         master = ical.masterComponent()
-        if master is None:
-            return ical
         for component in tuple(ical.subcomponents()):
             if component.name() in ignoredComponents:
                 continue
@@ -49,15 +47,17 @@
             if component.hasProperty(Component.HIDDEN_INSTANCE_PROPERTY):
                 rid = component.getRecurrenceIDUTC()
                 ical.removeComponent(component)
-                
+
                 # Add EXDATE and try to preserve same timezone as DTSTART
-                dtstart = master.getProperty("DTSTART")
-                if dtstart is not None and not dtstart.value().isDateOnly() and dtstart.value().local():
-                    rid.adjustTimezone(dtstart.value().getTimezone())
-                master.addProperty(Property("EXDATE", [rid,]))
-        
+                if master is not None:
+                    dtstart = master.getProperty("DTSTART")
+                    if dtstart is not None and not dtstart.value().isDateOnly() and dtstart.value().local():
+                        rid.adjustTimezone(dtstart.value().getTimezone())
+                    master.addProperty(Property("EXDATE", [rid, ]))
+
         return ical
-   
+
+
     def merge(self, icalnew, icalold):
         """
         Private event merging does not happen

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/datafilters/test/test_hiddeninstances.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/datafilters/test/test_hiddeninstances.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/datafilters/test/test_hiddeninstances.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -21,7 +21,7 @@
 class HiddenInstanceFilterTest (twistedcaldav.test.util.TestCase):
 
     def test_public_default(self):
-        
+
         data = (
             (
                 "Nothing hidden, no recurrence",
@@ -378,7 +378,7 @@
 """,
             ),
             (
-                "No master, one hidden - not really",
+                "No master, one hidden",
                 """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
@@ -415,21 +415,11 @@
 ATTENDEE:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
-BEGIN:VEVENT
-UID:12345-67890
-RECURRENCE-ID:20080603T120000Z
-DTSTART:20080603T123000Z
-DTEND:20080601T133000Z
-ATTENDEE:mailto:user1 at example.com
-ATTENDEE:mailto:user2 at example.com
-ORGANIZER;CN=User 01:mailto:user1 at example.com
-X-CALENDARSERVER-HIDDEN-INSTANCE:T
-END:VEVENT
 END:VCALENDAR
 """,
             ),
         )
-        
+
         for title, test, result in data:
             ics = Component.fromString(test.replace("\n", "\r\n"))
             self.assertEqual(str(HiddenInstanceFilter().filter(ics)), result.replace("\n", "\r\n"), msg="Failed: %s" % (title,))

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_guidchange.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_guidchange.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_guidchange.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
+
 from twistedcaldav.directory.directory import DirectoryService
 
 from txdav.xml import element as davxml
@@ -93,14 +95,14 @@
             if allowed:
                 def onError(f):
                     f.trap(AccessDeniedError)
-                    #print resource.readDeadProperty(davxml.ACL).toxml()
+                    #print(resource.readDeadProperty(davxml.ACL).toxml())
                     self.fail("%s should have %s privilege on %r" % (principal, privilege.sname(), resource))
                 d.addErrback(onError)
             else:
                 def onError(f):
                     f.trap(AccessDeniedError)
                 def onSuccess(_):
-                    #print resource.readDeadProperty(davxml.ACL).toxml()
+                    #print(resource.readDeadProperty(davxml.ACL).toxml())
                     self.fail("%s should not have %s privilege on %r" % (principal, privilege.sname(), resource))
                 d.addCallback(onSuccess)
                 d.addErrback(onError)

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_ldapdirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_ldapdirectory.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_ldapdirectory.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 try:
     from twistedcaldav.directory.ldapdirectory import (
@@ -29,7 +30,7 @@
     from string import maketrans
     import ldap
 except ImportError:
-    print "Skipping because ldap module not installed"
+    print("Skipping because ldap module not installed")
 else:
     from twistedcaldav.test.util import TestCase
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_livedirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_livedirectory.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_livedirectory.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 runLDAPTests = False
 runODTests = False
@@ -33,7 +34,7 @@
         pass # Don't run live tests
 
 except ImportError:
-    print "Could not import ldap module (skipping LDAP tests)"
+    print("Could not import ldap module (skipping LDAP tests)")
 
 try:
     from calendarserver.platform.darwin.od import opendirectory, dsattributes
@@ -54,10 +55,10 @@
     if "odtestamanda" in recordNames:
         runODTests = True
     else:
-        print "Test OD records not found (skipping OD tests)"
+        print("Test OD records not found (skipping OD tests)")
 
 except ImportError:
-    print "Could not import OpenDirectory framework (skipping OD tests)"
+    print("Could not import OpenDirectory framework (skipping OD tests)")
 
 
 if runLDAPTests or runODTests:
@@ -144,7 +145,7 @@
     if runLDAPTests:
 
         from twistedcaldav.directory.ldapdirectory import LdapDirectoryService
-        print "Running live LDAP tests against %s" % (testServer,)
+        print("Running live LDAP tests against %s" % (testServer,))
 
         class LiveLDAPDirectoryServiceCase(LiveDirectoryTests, TestCase):
 
@@ -181,7 +182,7 @@
     if runODTests:
 
         from twistedcaldav.directory.appleopendirectory import OpenDirectoryService
-        print "Running live OD tests"
+        print("Running live OD tests")
 
         class LiveODDirectoryServiceCase(LiveDirectoryTests, TestCase):
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_principal.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/directory/test/test_principal.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 import os
 
@@ -94,7 +95,7 @@
         DirectoryPrincipalResource.principalURL(),
         """
         for directory in self.directoryServices:
-            #print "\n -> %s" % (directory.__class__.__name__,)
+            #print("\n -> %s" % (directory.__class__.__name__,))
             provisioningResource = self.principalRootResources[directory.__class__.__name__]
 
             provisioningURL = "/" + directory.__class__.__name__ + "/"
@@ -107,7 +108,7 @@
             self.assertEquals(recordTypes, set(directory.recordTypes()))
 
             for recordType in recordTypes:
-                #print "   -> %s" % (recordType,)
+                #print("   -> %s" % (recordType,))
                 typeResource = provisioningResource.getChild(recordType)
                 self.failUnless(isinstance(typeResource, DirectoryPrincipalTypeProvisioningResource))
 
@@ -126,7 +127,7 @@
                 self.assertEquals(shortNames, set(expected))
 
                 for shortName in shortNames:
-                    #print "     -> %s" % (shortName,)
+                    #print("     -> %s" % (shortName,))
                     recordResource = typeResource.getChild(shortName)
                     self.failUnless(isinstance(recordResource, DirectoryPrincipalResource))
 
@@ -627,14 +628,14 @@
         Default access controls for principal provisioning resources.
         """
         for directory in self.directoryServices:
-            #print "\n -> %s" % (directory.__class__.__name__,)
+            #print("\n -> %s" % (directory.__class__.__name__,))
             provisioningResource = self.principalRootResources[directory.__class__.__name__]
 
             for args in _authReadOnlyPrivileges(self, provisioningResource, provisioningResource.principalCollectionURL()):
                 yield self._checkPrivileges(*args)
 
             for recordType in (yield provisioningResource.listChildren()):
-                #print "   -> %s" % (recordType,)
+                #print("   -> %s" % (recordType,))
                 typeResource = provisioningResource.getChild(recordType)
 
                 for args in _authReadOnlyPrivileges(self, typeResource, typeResource.principalCollectionURL()):
@@ -703,14 +704,14 @@
             if allowed:
                 def onError(f):
                     f.trap(AccessDeniedError)
-                    #print resource.readDeadProperty(davxml.ACL)
+                    #print(resource.readDeadProperty(davxml.ACL))
                     self.fail("%s should have %s privilege on %r" % (principal.sname(), privilege.sname(), resource))
                 d.addErrback(onError)
             else:
                 def expectAccessDenied(f):
                     f.trap(AccessDeniedError)
                 def onSuccess(_):
-                    #print resource.readDeadProperty(davxml.ACL)
+                    #print(resource.readDeadProperty(davxml.ACL))
                     self.fail("%s should not have %s privilege on %r" % (principal.sname(), privilege.sname(), resource))
                 d.addCallbacks(onSuccess, expectAccessDenied)
             return d

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/extensions.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/extensions.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 Extensions to web2.dav
@@ -502,7 +503,7 @@
             else:
                 mimeType = child.contentType()
                 if mimeType is None:
-                    print 'BAD contentType() IMPLEMENTATION', child
+                    print('BAD contentType() IMPLEMENTATION', child)
                     contentType = 'application/octet-stream'
                 else:
                     contentType = "%s/%s" % (mimeType.mediaType, mimeType.mediaSubtype)

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/ical.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/ical.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/ical.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1281,7 +1281,7 @@
         is added as STATUS:CANCELLED and the EXDATE removed.
 
         @param rid: recurrence-id value
-        @type rid: L{PyCalendarDateTime}
+        @type rid: L{PyCalendarDateTime} or C{str}
         @param allowCancelled: whether to allow a STATUS:CANCELLED override
         @type allowCancelled: C{bool}
 
@@ -1296,6 +1296,9 @@
         if master is None:
             return None
 
+        if isinstance(rid, str):
+            rid = PyCalendarDateTime.parseText(rid) if rid else None
+
         # TODO: Check that the recurrence-id is a valid instance
         # For now we just check that there is no matching EXDATE
         didCancel = False

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/localization.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/localization.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/localization.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,8 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
+from __future__ import with_statement
 
-from __future__ import with_statement
 import gettext
 import inspect
 import os
@@ -46,8 +47,8 @@
     from localization import translationTo
 
     with translationTo('de'):
-        print _("Hello")
-        print _("The event will last %(days)d days") % { 'days' : 4 }
+        print(_("Hello"))
+        print(_("The event will last %(days)d days") % { 'days' : 4 })
 
     ... Hallo
     ... Die Veranstaltung dauert 4 Tage
@@ -74,12 +75,12 @@
 nesting of "with" contexts, as in:
 
     with translationTo('de'):
-        print _("Hello") # in German
+        print(_("Hello") # in German)
 
         with translationTo('fr'):
-            print _("Hello") # in French
+            print(_("Hello") # in French)
 
-        print _("Hello") # in German
+        print(_("Hello") # in German)
 
 If a translation file cannot be found for the specified language, it will fall
 back to 'en'.  If 'en' can't be found, gettext will raise IOError.
@@ -88,12 +89,12 @@
 helper methods for date formatting:
 
     with translationTo('en') as trans:
-        print trans.dtDate(PyCalendarDateTime.getToday())
+        print(trans.dtDate(PyCalendarDateTime.getToday()))
 
     ... Thursday, October 23, 2008
 
     with translationTo('fr') as trans:
-        print trans.dtDate(PyCalendarDateTime.getToday())
+        print(trans.dtDate(PyCalendarDateTime.getToday()))
 
     ... Jeudi, Octobre 23, 2008
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/method/put.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/method/put.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/method/put.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -31,8 +31,7 @@
 from twistedcaldav.caldavxml import caldav_namespace
 
 from twistedcaldav.method.put_common import StoreCalendarObjectResource
-from twistedcaldav.resource import isPseudoCalendarCollectionResource, \
-    CalDAVResource
+from twistedcaldav.resource import isPseudoCalendarCollectionResource
 
 log = Logger()
 
@@ -158,13 +157,6 @@
             raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, str(e)))
 
     else:
-        result = (yield super(CalDAVResource, self).http_PUT(request))
-
-        if not hasattr(request, "extendedLogItems"):
-            request.extendedLogItems = {}
-        clength = request.headers.getHeader("content-length", 0)
-        if clength == 0:
-            clength = self.contentLength()
-        request.extendedLogItems["cl"] = str(clength)
-
-        returnValue(result)
+        # No longer support arbitrary PUTs to resource. Instead we are going to require all the
+        # resource classes we care about to explicitly define their own http_PUT.
+        raise HTTPError(StatusResponse(responsecode.FORBIDDEN, "PUTs not allowed here"))

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/query/expression.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/query/expression.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/query/expression.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,10 +13,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
-Query Expression Elements. These are used to build a 'generic' query expression tree that can then
-be used by different query language generators to produce the actual query syntax required (SQL, xpath eyc).
+Query Expression Elements. These are used to build a 'generic' query
+expression tree that can then be used by different query language
+generators to produce the actual query syntax required (SQL, xpath
+eyc).
 """
 
 __version__ = "0.0"
@@ -329,9 +332,9 @@
     e3 = containsExpression("summary", "help", True)
     e4 = notExpression(e3)
     e5 = andExpression([e1, e2, e4])
-    print e5
+    print(e5)
     e6 = inExpression("type", ("vevent", "vtodo",), False)
-    print e6
+    print(e6)
     e7 = notinExpression("type", ("vevent", "vtodo",), False)
-    print e7
+    print(e7)
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/query/sqlgenerator.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/query/sqlgenerator.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/query/sqlgenerator.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 """
 SQL statement generator from query expressions.
@@ -320,14 +321,14 @@
     e2 = expression.timerangeExpression("20060101T120000Z", "20060101T130000Z", "20060101T080000Z", "20060101T090000Z")
     e3 = expression.notcontainsExpression("SUMMARY", "help", True)
     e5 = expression.andExpression([e1, e2, e3])
-    print e5
+    print(e5)
     sql = sqlgenerator(e5, 'dummy-cal', 'dummy-user')
-    print sql.generate()
+    print(sql.generate())
     e6 = expression.inExpression("TYPE", ("VEVENT", "VTODO",), False)
-    print e6
+    print(e6)
     sql = sqlgenerator(e6, 'dummy-cal', 'dummy-user')
-    print sql.generate()
+    print(sql.generate())
     e7 = expression.notinExpression("TYPE", ("VEVENT", "VTODO",), False)
-    print e7
+    print(e7)
     sql = sqlgenerator(e7, 'dummy-cal', 'dummy-user')
-    print sql.generate()
+    print(sql.generate())

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/resource.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/resource.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -2320,7 +2320,7 @@
 
         elif qname == (customxml.calendarserver_namespace, "push-transports"):
 
-            if config.Notifications.Services.ApplePushNotifier.Enabled:
+            if config.Notifications.Services.APNS.Enabled:
 
                 nodeName = (yield self._newStoreHome.nodeName())
                 if nodeName:
@@ -2355,8 +2355,8 @@
             returnValue(None)
 
         elif qname == (customxml.calendarserver_namespace, "pushkey"):
-            if (config.Notifications.Services.AMPNotifier.Enabled or
-                config.Notifications.Services.ApplePushNotifier.Enabled):
+            if (config.Notifications.Services.AMP.Enabled or
+                config.Notifications.Services.APNS.Enabled):
                 nodeName = (yield self._newStoreHome.nodeName())
                 if nodeName:
                     returnValue(customxml.PubSubXMPPPushKeyProperty(nodeName))

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/icaldiff.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/icaldiff.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/icaldiff.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -339,11 +339,9 @@
                         changedRids.append(rid.getText() if rid else "")
 
                     # When a master component is present we keep the missing override in place but mark it as hidden.
-                    # When no master is present we remove the override,
-                    if exdatesnew is not None:
-                        overridden.replaceProperty(Property(Component.HIDDEN_INSTANCE_PROPERTY, "T"))
-                    else:
-                        returnCalendar.removeComponent(overridden)
+                    # When no master is present we now do the same so we can track updates to the override correctly.
+                    overridden.replaceProperty(Property(Component.HIDDEN_INSTANCE_PROPERTY, "T"))
+
                 else:
                     # We used to generate a 403 here - but instead we now ignore this error and let the server data
                     # override the client

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/outbound.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/outbound.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/outbound.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -23,7 +23,6 @@
 from cStringIO import StringIO
 import os
 
-from email.mime.image import MIMEImage
 from email.mime.multipart import MIMEMultipart
 from email.mime.text import MIMEText
 import email.utils
@@ -39,7 +38,7 @@
 from twisted.web.template import XMLString, TEMPLATE_NAMESPACE, Element, renderer, flattenString, tags
 from twistedcaldav.config import config
 from twistedcaldav.ical import Component
-from twistedcaldav.localization import translationTo, _
+from twistedcaldav.localization import translationTo, _, getLanguage
 from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
 from twistedcaldav.scheduling.imip.smtpsender import SMTPSender
 from txdav.common.datastore.sql_tables import schema
@@ -81,7 +80,7 @@
                 smtpSender = SMTPSender(settings.Username, settings.Password,
                     settings.UseSSL, settings.Server, settings.Port)
                 cls.mailSender = MailSender(settings.Address,
-                    settings.SuppressionDays, smtpSender=smtpSender)
+                    settings.SuppressionDays, smtpSender, getLanguage(config))
         return cls.mailSender
 
     @inlineCallbacks
@@ -302,15 +301,15 @@
     Generates outbound IMIP messages and sends them.
     """
 
-    def __init__(self, address, suppressionDays, smtpSender):
+    def __init__(self, address, suppressionDays, smtpSender, language):
         self.address = address
         self.suppressionDays = suppressionDays
         self.smtpSender = smtpSender
+        self.language = language
 
 
     @inlineCallbacks
-    def outbound(self, txn, originator, recipient, calendar, language='en',
-        onlyAfter=None):
+    def outbound(self, txn, originator, recipient, calendar, onlyAfter=None):
         """
         Generates and sends an outbound IMIP message.
 
@@ -473,7 +472,7 @@
 
         msgId, message = self.generateEmail(inviteState, calendar, orgEmail,
             orgCN, attendees, formattedFrom, addressWithToken, recipient,
-            language=language)
+            language=self.language)
 
         try:
             success = (yield self.smtpSender.sendMessage(fromAddr, toAddr,
@@ -484,32 +483,6 @@
             returnValue(False)
 
 
-    def getIconPath(self, details, canceled, language='en'):
-        iconDir = config.Scheduling.iMIP.MailIconsDirectory.rstrip("/")
-
-        if canceled:
-            iconName = "canceled.png"
-            iconPath = os.path.join(iconDir, iconName)
-            if os.path.exists(iconPath):
-                return iconPath
-            else:
-                return None
-
-        else:
-            month = int(details['month'])
-            day = int(details['day'])
-            with translationTo(language) as trans:
-                monthName = trans.monthAbbreviation(month)
-            iconName = "%02d.png" % (day,)
-            iconPath = os.path.join(iconDir, monthName.encode("utf-8"), iconName)
-            if not os.path.exists(iconPath):
-                # Try the generic (numeric) version
-                iconPath = os.path.join(iconDir, "%02d" % (month,), iconName)
-                if not os.path.exists(iconPath):
-                    return None
-            return iconPath
-
-
     def generateEmail(self, inviteState, calendar, orgEmail, orgCN,
                       attendees, fromAddress, replyToAddress, toAddress,
                       language='en'):
@@ -562,18 +535,16 @@
 
         details = self.getEventDetails(calendar, language=language)
         canceled = (calendar.propertyValue("METHOD") == "CANCEL")
-        iconPath = self.getIconPath(details, canceled, language=language)
 
         subjectFormat, labels = localizedLabels(language, canceled, inviteState)
         details.update(labels)
 
         details['subject'] = subjectFormat % {'summary' : details['summary']}
-        details['iconName'] = iconName = "calicon.png"
 
         plainText = self.renderPlainText(details, (orgCN, orgEmail),
                                          attendees, canceled)
 
-        [addIcon, htmlText] = self.renderHTML(details, (orgCN, orgEmail),
+        htmlText = self.renderHTML(details, (orgCN, orgEmail),
                                               attendees, canceled)
 
         msg = MIMEMultipart()
@@ -599,19 +570,6 @@
         msgHtml = MIMEText(htmlText, "html", "UTF-8")
         msgHtmlRelated.attach(msgHtml)
 
-        # an image for html version
-        if addIcon and iconPath != None and os.path.exists(iconPath):
-
-            with open(iconPath) as iconFile:
-                msgIcon = MIMEImage(iconFile.read(),
-                    _subtype='png;x-apple-mail-type=stationery;name="%s"' %
-                    (iconName,))
-
-            msgIcon.add_header("Content-ID", "<%s>" % (iconName,))
-            msgIcon.add_header("Content-Disposition", "inline;filename=%s" %
-                (iconName,))
-            msgHtmlRelated.attach(msgIcon)
-
         calendarText = str(calendar)
         # the icalendar attachment
         self.log_debug("Mail gateway sending calendar body: %s"
@@ -663,10 +621,7 @@
         Render HTML message part based on invitation details and a flag
         indicating whether the message is a cancellation.
 
-        @return: a 2-tuple of (should add icon (C{bool}), html text (C{str},
-            representing utf-8 encoded bytes)).  The first element indicates
-            whether the MIME generator needs to add a C{cid:} icon image part to
-            satisfy the HTML links.
+        @return: html text (C{str}, representing utf-8 encoded bytes)).
         """
         orgCN, orgEmail = organizer
 
@@ -727,13 +682,9 @@
         textCollector = []
         flattenString(None, EmailElement()).addCallback(textCollector.append)
         htmlText = textCollector[0]
+        return htmlText
 
-        # If the template refers to an icon in a cid: link, it needs to be added
-        # in the MIME.
-        addIcon = (htmlTemplate.find("cid:%(iconName)s") != -1)
-        return (addIcon, htmlText)
 
-
     def getEventDetails(self, calendar, language='en'):
         """
         Create a dictionary mapping slot names - specifically: summary,

Deleted: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/resource.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/resource.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -1,223 +0,0 @@
-##
-# Copyright (c) 2005-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 twext.python.log import Logger
-from twext.web2 import responsecode
-from twext.web2.dav.noneprops import NonePropertyStore
-from twext.web2.http import Response, HTTPError
-from twext.web2.http_headers import MimeType
-from twisted.internet.defer import succeed, inlineCallbacks, returnValue
-from twistedcaldav import caldavxml
-from twistedcaldav.config import config
-from twistedcaldav.directory.util import transactionFromRequest
-from twistedcaldav.ical import Component
-from twistedcaldav.localization import getLanguage
-from twistedcaldav.resource import CalDAVResource
-from twistedcaldav.scheduling.caldav.resource import deliverSchedulePrivilegeSet
-from twistedcaldav.scheduling.imip.scheduler import IMIPScheduler
-from txdav.xml import element as davxml
-
-__all__ = [
-    "IMIPInboxResource",
-    "IMIPReplyInboxResource",
-    "IMIPInvitationInboxResource",
-]
-
-log = Logger()
-
-class IMIPInboxResource(CalDAVResource):
-    """
-    IMIP-delivery Inbox resource.
-
-    Extends L{DAVResource} to provide IMIP delivery functionality.
-    """
-
-    def __init__(self, parent, store):
-        """
-        @param parent: the parent resource of this one.
-        @param store: the store to use for transactions.
-        """
-        assert parent is not None
-
-        CalDAVResource.__init__(
-            self, principalCollections=parent.principalCollections()
-        )
-
-        self.parent = parent
-        self._newStore = store
-
-
-    def accessControlList(self, request, inheritance=True,
-        expanding=False, inherited_aces=None):
-
-        if not hasattr(self, "iMIPACL"):
-            guid = config.Scheduling.iMIP.GUID
-            self.iMIPACL = davxml.ACL(
-                davxml.ACE(
-                    davxml.Principal(
-                        davxml.HRef.fromString("/principals/__uids__/%s/"
-                                               % (guid,))
-                    ),
-                    davxml.Grant(
-                        davxml.Privilege(caldavxml.ScheduleDeliver()),
-                    ),
-                ),
-            )
-
-        return succeed(self.iMIPACL)
-
-
-    def resourceType(self):
-        return davxml.ResourceType.ischeduleinbox
-
-
-    def contentType(self):
-        return MimeType.fromString("text/html; charset=utf-8")
-
-
-    def isCollection(self):
-        return False
-
-
-    def isCalendarCollection(self):
-        return False
-
-
-    def isPseudoCalendarCollection(self):
-        return False
-
-
-    def deadProperties(self):
-        if not hasattr(self, "_dead_properties"):
-            self._dead_properties = NonePropertyStore(self)
-        return self._dead_properties
-
-
-    def etag(self):
-        return succeed(None)
-
-
-    def checkPreconditions(self, request):
-        return None
-
-
-    def render(self, request):
-        output = """<html>
-<head>
-<title>IMIP Delivery Resource</title>
-</head>
-<body>
-<h1>IMIP Delivery Resource.</h1>
-</body
-</html>"""
-
-        response = Response(200, {}, output)
-        response.headers.setHeader("content-type", MimeType("text", "html"))
-        return response
-
-    ##
-    # File
-    ##
-
-
-    def createSimilarFile(self, path):
-        log.err("Attempt to create clone %r of resource %r" % (path, self))
-        raise HTTPError(responsecode.NOT_FOUND)
-
-    ##
-    # ACL
-    ##
-
-
-    def defaultAccessControlList(self):
-        privs = (
-            davxml.Privilege(davxml.Read()),
-            davxml.Privilege(caldavxml.ScheduleDeliver()),
-        )
-        if config.Scheduling.CalDAV.OldDraftCompatibility:
-            privs += (davxml.Privilege(caldavxml.Schedule()),)
-        return davxml.ACL(
-            # DAV:Read, CalDAV:schedule-deliver for all principals (includes
-            # anonymous)
-            davxml.ACE(
-                davxml.Principal(davxml.All()),
-                davxml.Grant(*privs),
-                davxml.Protected(),
-            ),
-        )
-
-
-    def supportedPrivileges(self, request):
-        return succeed(deliverSchedulePrivilegeSet)
-
-
-
-class IMIPReplyInboxResource(IMIPInboxResource):
-
-    def renderHTTP(self, request):
-        """
-        Set up a transaction which will be used and committed by implicit
-        scheduling.
-        """
-        self.transaction = transactionFromRequest(request, self._newStore)
-        return super(IMIPReplyInboxResource, self).renderHTTP(request, self.transaction)
-
-
-    @inlineCallbacks
-    def http_POST(self, request):
-        """
-        The IMIP reply POST method (inbound)
-        """
-
-        # Check authentication and access controls
-        yield self.authorize(request, (caldavxml.ScheduleDeliver(),))
-
-        # Inject using the IMIPScheduler.
-        scheduler = IMIPScheduler(request, self)
-
-        # Do the POST processing treating this as a non-local schedule
-        result = (yield scheduler.doSchedulingViaPOST(self.transaction, use_request_headers=True))
-        returnValue(result.response())
-
-
-
-class IMIPInvitationInboxResource(IMIPInboxResource):
-
-    def __init__(self, parent, store, mailer):
-        super(IMIPInvitationInboxResource, self).__init__(parent, store)
-        self.mailer = mailer
-
-
-    @inlineCallbacks
-    def http_POST(self, request):
-        """
-        The IMIP invitation POST method (outbound)
-        """
-
-        # Check authentication and access controls
-        yield self.authorize(request, (caldavxml.ScheduleDeliver(),))
-
-        # Compute token, add to db, generate email and send it
-        calendar = (yield Component.fromIStream(request.stream))
-        originator = request.headers.getRawHeaders("originator")[0]
-        recipient = request.headers.getRawHeaders("recipient")[0]
-        language = getLanguage(config)
-
-        if not (yield self.mailer.outbound(originator,
-            recipient, calendar, language=language)):
-            returnValue(Response(code=responsecode.BAD_REQUEST))
-
-        returnValue(Response(code=responsecode.OK))

Added: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/test/test_inbound.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/test/test_inbound.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/test/test_inbound.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,362 @@
+##
+# Copyright (c) 2008-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 email
+from twisted.internet.defer import inlineCallbacks
+from twisted.python.modules import getModule
+from twistedcaldav.ical import Component
+from twistedcaldav.scheduling.imip.inbound import MailReceiver
+from twistedcaldav.scheduling.imip.inbound import MailRetriever
+from twistedcaldav.scheduling.imip.inbound import injectMessage
+from twistedcaldav.scheduling.imip.inbound import IMIPReplyWork
+from twistedcaldav.scheduling.itip import iTIPRequestStatus
+from twistedcaldav.test.util import TestCase
+from twistedcaldav.test.util import xmlFile
+from txdav.common.datastore.test.util import buildStore
+from calendarserver.tap.util import getRootResource
+from twistedcaldav.config import config, ConfigDict
+
+
+class InboundTests(TestCase):
+
+    @inlineCallbacks
+    def setUp(self):
+        super(InboundTests, self).setUp()
+
+        self.store = yield buildStore(self, None)
+        self.patch(config.DirectoryService.params, "xmlFile", xmlFile)
+        self.root = getRootResource(config, self.store)
+        self.directory = self.root.getDirectory()
+        self.receiver = MailReceiver(self.store, self.directory)
+        self.retriever = MailRetriever(self.store, self.directory,
+            ConfigDict({
+                "Type" : "pop",
+                "UseSSL" : False,
+                "Server" : "example.com",
+                "Port" : 123,
+            })
+        )
+
+        def decorateTransaction(txn):
+            txn._rootResource = self.root
+            txn._mailRetriever = self.retriever
+
+        self.store.callWithNewTransactions(decorateTransaction)
+        module = getModule(__name__)
+        self.dataPath = module.filePath.sibling("data")
+
+    def dataFile(self, name):
+        """
+        Get the contents of a given data file from the 'data/mail' test
+        fixtures directory.
+        """
+        return self.dataPath.child(name).getContent()
+
+
+    def test_checkDSNFailure(self):
+
+        data = {
+            'good_reply' : (False, None, None),
+            'dsn_failure_no_original' : (True, 'failed', None),
+            'dsn_failure_no_ics' : (True, 'failed', None),
+            'dsn_failure_with_ics' : (True, 'failed', '''BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+METHOD:REQUEST
+PRODID:-//example Inc.//iCal 3.0//EN
+BEGIN:VTIMEZONE
+TZID:US/Pacific
+BEGIN:STANDARD
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+TZNAME:PST
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0800
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+TZNAME:PDT
+TZOFFSETFROM:-0800
+TZOFFSETTO:-0700
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:1E71F9C8-AEDA-48EB-98D0-76E898F6BB5C
+DTSTART;TZID=US/Pacific:20080812T094500
+DTEND;TZID=US/Pacific:20080812T104500
+ATTENDEE;CUTYPE=INDIVIDUAL;CN=User 01;PARTSTAT=ACCEPTED:mailto:user01 at exam
+ ple.com
+ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-A
+ CTION;CN=nonexistant at example.com:mailto:nonexistant at example.com
+CREATED:20080812T191857Z
+DTSTAMP:20080812T191932Z
+ORGANIZER;CN=User 01:mailto:xyzzy+8e16b897-d544-4217-88e9-a363d08
+ 46f6c at example.com
+SEQUENCE:2
+SUMMARY:New Event
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+'''),
+        }
+
+        for filename, expected in data.iteritems():
+            msg = email.message_from_string(self.dataFile(filename))
+            self.assertEquals(self.receiver.checkDSN(msg), expected)
+
+
+    @inlineCallbacks
+    def test_processDSN(self):
+
+        template = """BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+METHOD:REQUEST
+PRODID:-//example Inc.//iCal 3.0//EN
+BEGIN:VTIMEZONE
+TZID:US/Pacific
+BEGIN:DAYLIGHT
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+TZNAME:PDT
+TZOFFSETFROM:-0800
+TZOFFSETTO:-0700
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+TZNAME:PST
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0800
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:1E71F9C8-AEDA-48EB-98D0-76E898F6BB5C
+DTSTART;TZID=US/Pacific:20080812T094500
+DTEND;TZID=US/Pacific:20080812T104500
+ATTENDEE;CUTYPE=INDIVIDUAL;CN=User 01;PARTSTAT=ACCEPTED:mailto:user01 at exam
+ ple.com
+ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-A
+ CTION;CN=nonexistant at example.com:mailto:nonexistant at example.com
+CREATED:20080812T191857Z
+DTSTAMP:20080812T191932Z
+ORGANIZER;CN=User 01:mailto:xyzzy+%s at example.com
+SEQUENCE:2
+SUMMARY:New Event
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+"""
+
+        # Make sure an unknown token is not processed
+        calBody = template % "bogus_token"
+        self.assertEquals(
+            (yield self.receiver.processDSN(calBody, "xyzzy")),
+            MailReceiver.UNKNOWN_TOKEN
+        )
+
+        # Make sure a known token *is* processed
+        txn = self.store.newTransaction()
+        token = (yield txn.imipCreateToken(
+            "urn:uuid:5A985493-EE2C-4665-94CF-4DFEA3A89500",
+            "mailto:user02 at example.com",
+            "1E71F9C8-AEDA-48EB-98D0-76E898F6BB5C"
+        ))
+        yield txn.commit()
+        calBody = template % token
+        result = (yield self.receiver.processDSN(calBody, "xyzzy"))
+        self.assertEquals(result, MailReceiver.INJECTION_SUBMITTED)
+
+
+    @inlineCallbacks
+    def test_processReply(self):
+        msg = email.message_from_string(self.dataFile('good_reply'))
+
+        # Make sure an unknown token is not processed
+        result = (yield self.receiver.processReply(msg))
+        self.assertEquals(result, MailReceiver.UNKNOWN_TOKEN)
+
+        # Make sure a known token *is* processed
+        txn = self.store.newTransaction()
+        yield txn.imipCreateToken(
+            "urn:uuid:5A985493-EE2C-4665-94CF-4DFEA3A89500",
+            "mailto:xyzzy at example.com",
+            "1E71F9C8-AEDA-48EB-98D0-76E898F6BB5C",
+            token="d7cdf68d-8b73-4df1-ad3b-f08002fb285f"
+        )
+        yield txn.commit()
+
+        result = (yield self.receiver.processReply(msg))
+        self.assertEquals(result, MailReceiver.INJECTION_SUBMITTED)
+
+
+    def test_processReplyMissingOrganizer(self):
+        msg = email.message_from_string(self.dataFile('reply_missing_organizer'))
+
+        # stick the token in the database first
+        txn = self.store.newTransaction()
+        yield txn.imipCreateToken(
+            "urn:uuid:5A985493-EE2C-4665-94CF-4DFEA3A89500",
+            "mailto:xyzzy at example.com",
+            "1E71F9C8-AEDA-48EB-98D0-76E898F6BB5C",
+            token="d7cdf68d-8b73-4df1-ad3b-f08002fb285f"
+        )
+        yield txn.commit()
+
+        result = (yield self.receiver.processReply(msg))
+        organizer, _ignore_attendee, calendar = result
+        organizerProp = calendar.mainComponent().getOrganizerProperty()
+        self.assertTrue(organizerProp is not None)
+        self.assertEquals(organizer,
+                          "urn:uuid:5A985493-EE2C-4665-94CF-4DFEA3A89500")
+
+
+    def test_processReplyMissingAttendee(self):
+        msg = email.message_from_string(self.dataFile('reply_missing_attendee'))
+
+        txn = self.store.newTransaction()
+        yield txn.imipCreateToken(
+            "urn:uuid:5A985493-EE2C-4665-94CF-4DFEA3A89500",
+            "mailto:xyzzy at example.com",
+            "1E71F9C8-AEDA-48EB-98D0-76E898F6BB5C",
+            token="d7cdf68d-8b73-4df1-ad3b-f08002fb285f"
+        )
+        yield txn.commit()
+
+        result = (yield self.receiver.processReply(msg))
+        _ignore_organizer, attendee, calendar = result
+
+        # Since the expected attendee was missing, the reply processor should
+        # have added an attendee back in with a "5.1;Service unavailable"
+        # schedule-status
+        attendeeProp = calendar.mainComponent().getAttendeeProperty([attendee])
+        self.assertEquals(attendeeProp.parameterValue("SCHEDULE-STATUS"),
+                          iTIPRequestStatus.SERVICE_UNAVAILABLE)
+
+
+    def test_processReplyMissingAttachment(self):
+
+        msg = email.message_from_string(
+            self.dataFile('reply_missing_attachment')
+        )
+
+        # stick the token in the database first
+        txn = self.store.newTransaction()
+        yield txn.imipCreateToken(
+            "urn:uuid:5A985493-EE2C-4665-94CF-4DFEA3A89500",
+            "mailto:xyzzy at example.com",
+            "1E71F9C8-AEDA-48EB-98D0-76E898F6BB5C",
+            token="d7cdf68d-8b73-4df1-ad3b-f08002fb285f"
+        )
+        yield txn.commit()
+
+        result = (yield self.receiver.processReply(msg))
+        self.assertEquals(result, MailReceiver.REPLY_FORWARDED_TO_ORGANIZER)        
+
+    @inlineCallbacks
+    def test_injectMessage(self):
+
+        calendar = Component.fromString("""BEGIN:VCALENDAR
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+VERSION:2.0
+METHOD:REPLY
+BEGIN:VEVENT
+UID:12345-67890
+DTSTAMP:20130208T120000Z
+DTSTART:20180601T120000Z
+DTEND:20180601T130000Z
+ORGANIZER:urn:uuid:user01
+ATTENDEE:mailto:xyzzy at example.com;PARTSTAT=ACCEPTED
+END:VEVENT
+END:VCALENDAR
+""")
+
+        txn = self.store.newTransaction()
+        result = (yield injectMessage(
+                txn,
+                self.root,
+                "urn:uuid:user01",
+                "mailto:xyzzy at example.com",
+                calendar
+            )
+        )
+        yield txn.commit()
+        self.assertEquals(
+            "1.2;Scheduling message has been delivered",
+            result.responses[0].children[1].toString()
+        )
+
+    @inlineCallbacks
+    def test_injectMessageWithError(self):
+
+        calendar = Component.fromString("""BEGIN:VCALENDAR
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+VERSION:2.0
+METHOD:REPLY
+BEGIN:VEVENT
+UID:12345-67890
+DTSTAMP:20130208T120000Z
+DTSTART:20180601T120000Z
+DTEND:20180601T130000Z
+ORGANIZER:urn:uuid:unknown_user
+ATTENDEE:mailto:xyzzy at example.com;PARTSTAT=ACCEPTED
+END:VEVENT
+END:VCALENDAR
+""")
+
+        txn = self.store.newTransaction()
+        result = (yield injectMessage(
+                txn,
+                self.root,
+                "urn:uuid:unknown_user",
+                "mailto:xyzzy at example.com",
+                calendar
+            )
+        )
+        yield txn.commit()
+        self.assertEquals(
+            "3.7;Invalid Calendar User",
+            result.responses[0].children[1].toString()
+        )
+
+
+    @inlineCallbacks
+    def test_work(self):
+
+        calendar = """BEGIN:VCALENDAR
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+VERSION:2.0
+METHOD:REPLY
+BEGIN:VEVENT
+UID:12345-67890
+DTSTAMP:20130208T120000Z
+DTSTART:20180601T120000Z
+DTEND:20180601T130000Z
+ORGANIZER:urn:uuid:user01
+ATTENDEE:mailto:xyzzy at example.com;PARTSTAT=ACCEPTED
+END:VEVENT
+END:VCALENDAR
+"""
+        txn = self.store.newTransaction()
+        wp = (yield txn.enqueue(IMIPReplyWork,
+            organizer="urn:uuid:user01",
+            attendee="mailto:xyzzy at example.com",
+            icalendarText=calendar
+        ))
+        yield txn.commit()
+        yield wp.whenExecuted()

Added: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/test/test_outbound.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/test/test_outbound.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/imip/test/test_outbound.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,556 @@
+##
+# Copyright (c) 2008-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 __future__ import print_function
+
+from cStringIO import StringIO
+import os
+
+import email
+from pycalendar.datetime import PyCalendarDateTime
+from twisted.internet.defer import inlineCallbacks, succeed
+from twisted.web.template import Element, renderer, flattenString
+from twistedcaldav.config import config
+from twistedcaldav.directory import augment
+from twistedcaldav.directory.xmlfile import XMLDirectoryService
+from twistedcaldav.ical import Component
+from twistedcaldav.scheduling.imip.outbound import IMIPInvitationWork
+from twistedcaldav.scheduling.imip.outbound import MailSender
+from twistedcaldav.scheduling.imip.outbound import StringFormatTemplateLoader
+from twistedcaldav.test.util import TestCase, xmlFile, augmentsFile
+from txdav.common.datastore.test.util import buildStore
+
+initialInviteText = u"""BEGIN:VCALENDAR
+VERSION:2.0
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:CFDD5E46-4F74-478A-9311-B3FF905449C3
+DTSTART:20200325T154500Z
+DTEND:20200325T164500Z
+ATTENDEE;CN=Th\xe9 Attendee;CUTYPE=INDIVIDUAL;PARTSTAT=NEEDS-ACTION;RSVP=TRU
+ E:mailto:attendee at example.com
+ATTENDEE;CN=Th\xe9 Organizer;CUTYPE=INDIVIDUAL;EMAIL=organizer at example.com;P
+ ARTSTAT=ACCEPTED:urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A
+ATTENDEE;CN=An Attendee without CUTYPE;EMAIL=nocutype at example.com;PARTSTAT=A
+ CCEPTED:urn:uuid:4DB528DC-3E60-44FA-9546-2A00FCDCFFAB
+ATTENDEE;EMAIL=nocn at example.com;PARTSTAT=ACCEPTED:urn:uuid:A592CF8B-4FC8-4E4
+ F-B543-B2F29A7EEB0B
+ORGANIZER;CN=Th\xe9 Organizer;EMAIL=organizer at example.com:urn:uuid:C3B38B00-
+ 4166-11DD-B22C-A07C87E02F6A
+SUMMARY:t\xe9sting outbound( )
+DESCRIPTION:awesome description with "<" and "&"
+END:VEVENT
+END:VCALENDAR
+"""
+
+ORGANIZER = "urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A"
+ATTENDEE = "mailto:attendee at example.com"
+ICALUID = "CFDD5E46-4F74-478A-9311-B3FF905449C3"
+
+class DummySMTPSender(object):
+
+    def __init__(self):
+        self.reset()
+        self.shouldSucceed = True
+
+    def reset(self):
+        self.sendMessageCalled = False
+        self.fromAddr = None
+        self.toAddr = None
+        self.msgId = None
+        self.message = None
+
+    def sendMessage(self, fromAddr, toAddr, msgId, message):
+        self.sendMessageCalled = True
+        self.fromAddr = fromAddr
+        self.toAddr = toAddr
+        self.msgId = msgId
+        self.message = message
+        return succeed(self.shouldSucceed)
+
+
+class OutboundTests(TestCase):
+
+    @inlineCallbacks
+    def setUp(self):
+        self.store = yield buildStore(self, None)
+        self.directory = XMLDirectoryService(
+            {
+                'xmlFile' : xmlFile,
+                'augmentService' :
+                    augment.AugmentXMLDB(xmlFiles=(augmentsFile.path,)),
+            }
+        )
+        self.sender = MailSender("server at example.com", 7, DummySMTPSender(),
+            language="en")
+
+        def _getSender(ignored):
+            return self.sender
+        self.patch(IMIPInvitationWork, "getMailSender", _getSender)
+
+        self.wp = None
+        self.store.queuer.callWithNewProposals(self._proposalCallback)
+
+    def _proposalCallback(self, wp):
+        self.wp = wp
+
+    @inlineCallbacks
+    def test_work(self):
+        txn = self.store.newTransaction()
+        wp = (yield txn.enqueue(IMIPInvitationWork,
+            fromAddr=ORGANIZER,
+            toAddr=ATTENDEE,
+            icalendarText=initialInviteText.replace("\n", "\r\n"),
+        ))
+        self.assertEquals(wp, self.wp)
+        yield txn.commit()
+        yield wp.whenExecuted()
+
+        txn = self.store.newTransaction()
+        token = (yield txn.imipGetToken(
+            ORGANIZER,
+            ATTENDEE,
+            ICALUID
+        ))
+        self.assertTrue(token)
+        organizer, attendee, icaluid = (yield txn.imipLookupByToken(token))[0]
+        yield txn.commit()
+        self.assertEquals(organizer, ORGANIZER)
+        self.assertEquals(attendee, ATTENDEE)
+        self.assertEquals(icaluid, ICALUID)
+
+    @inlineCallbacks
+    def test_workFailure(self):
+        self.sender.smtpSender.shouldSucceed = False
+
+        txn = self.store.newTransaction()
+        wp = (yield txn.enqueue(IMIPInvitationWork,
+            fromAddr=ORGANIZER,
+            toAddr=ATTENDEE,
+            icalendarText=initialInviteText.replace("\n", "\r\n"),
+        ))
+        yield txn.commit()
+        yield wp.whenExecuted()
+        # Verify a new work proposal was not created
+        self.assertEquals(wp, self.wp)
+
+
+    def _interceptEmail(self, inviteState, calendar, orgEmail, orgCn,
+        attendees, fromAddress, replyToAddress, toAddress, language="en"):
+        self.inviteState = inviteState
+        self.calendar = calendar
+        self.orgEmail = orgEmail
+        self.orgCn = orgCn
+        self.attendees = attendees
+        self.fromAddress = fromAddress
+        self.replyToAddress = replyToAddress
+        self.toAddress = toAddress
+        self.language = language
+        self.results = self._actualGenerateEmail(inviteState, calendar,
+            orgEmail, orgCn, attendees, fromAddress, replyToAddress, toAddress,
+            language=language)
+        return self.results
+
+    @inlineCallbacks
+    def test_outbound(self):
+        """
+        Make sure outbound( ) stores tokens properly so they can be looked up
+        """
+
+        config.Scheduling.iMIP.Sending.Address = "server at example.com"
+        self.patch(config.Localization, "LocalesDirectory", os.path.join(os.path.dirname(__file__), "locales"))
+        self._actualGenerateEmail = self.sender.generateEmail
+        self.patch(self.sender, "generateEmail", self._interceptEmail)
+
+        data = (
+            # Initial invite
+            (
+                initialInviteText,
+                "CFDD5E46-4F74-478A-9311-B3FF905449C3",
+                "urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A",
+                "mailto:attendee at example.com",
+                "new",
+                "organizer at example.com",
+                u"Th\xe9 Organizer",
+                [
+                    (u'Th\xe9 Attendee', u'attendee at example.com'),
+                    (u'Th\xe9 Organizer', u'organizer at example.com'),
+                    (u'An Attendee without CUTYPE', u'nocutype at example.com'),
+                    (None, u'nocn at example.com'),
+                ],
+                u"Th\xe9 Organizer <organizer at example.com>",
+                "=?utf-8?q?Th=C3=A9_Organizer_=3Corganizer=40example=2Ecom=3E?=",
+                "attendee at example.com",
+            ),
+
+            # Update
+            (
+                """BEGIN:VCALENDAR
+VERSION:2.0
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:CFDD5E46-4F74-478A-9311-B3FF905449C3
+DTSTART:20100325T154500Z
+DTEND:20100325T164500Z
+ATTENDEE;CN=The Attendee;CUTYPE=INDIVIDUAL;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:
+ mailto:attendee at example.com
+ATTENDEE;CN=The Organizer;CUTYPE=INDIVIDUAL;EMAIL=organizer at example.com;PAR
+ TSTAT=ACCEPTED:urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A
+ORGANIZER;CN=The Organizer;EMAIL=organizer at example.com:urn:uuid:C3B38B00-41
+ 66-11DD-B22C-A07C87E02F6A
+SUMMARY:testing outbound( ) *update*
+END:VEVENT
+END:VCALENDAR
+""",
+                "CFDD5E46-4F74-478A-9311-B3FF905449C3",
+                "urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A",
+                "mailto:attendee at example.com",
+                "update",
+                "organizer at example.com",
+                "The Organizer",
+                [
+                    (u'The Attendee', u'attendee at example.com'),
+                    (u'The Organizer', u'organizer at example.com')
+                ],
+                "The Organizer <organizer at example.com>",
+                "The Organizer <organizer at example.com>",
+                "attendee at example.com",
+            ),
+
+            # Reply
+            (
+                """BEGIN:VCALENDAR
+VERSION:2.0
+METHOD:REPLY
+BEGIN:VEVENT
+UID:DFDD5E46-4F74-478A-9311-B3FF905449C4
+DTSTART:20100325T154500Z
+DTEND:20100325T164500Z
+ATTENDEE;CN=The Attendee;CUTYPE=INDIVIDUAL;EMAIL=attendee at example.com;PARTST
+ AT=ACCEPTED:urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A
+ORGANIZER;CN=The Organizer;EMAIL=organizer at example.com:mailto:organizer at exam
+ ple.com
+SUMMARY:testing outbound( ) *reply*
+END:VEVENT
+END:VCALENDAR
+""",
+                None,
+                "urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A",
+                "mailto:organizer at example.com",
+                "reply",
+                "organizer at example.com",
+                "The Organizer",
+                [
+                    (u'The Attendee', u'attendee at example.com'),
+                ],
+                "attendee at example.com",
+                "attendee at example.com",
+                "organizer at example.com",
+            ),
+
+        )
+        for (inputCalendar, UID, inputOriginator, inputRecipient, inviteState,
+            outputOrganizerEmail, outputOrganizerName, outputAttendeeList,
+            outputFrom, encodedFrom, outputRecipient) in data:
+
+            txn = self.store.newTransaction()
+            yield self.sender.outbound(
+                txn,
+                inputOriginator,
+                inputRecipient,
+                Component.fromString(inputCalendar.replace("\n", "\r\n")),
+                onlyAfter=PyCalendarDateTime(2010, 1, 1, 0, 0, 0)
+            )
+            yield txn.commit()
+
+            msg = email.message_from_string(self.sender.smtpSender.message)
+            self.assertEquals(msg["From"], encodedFrom)
+            self.assertEquals(self.inviteState, inviteState)
+            self.assertEquals(self.orgEmail, outputOrganizerEmail)
+            self.assertEquals(self.orgCn, outputOrganizerName)
+            self.assertEquals(self.attendees, outputAttendeeList)
+            self.assertEquals(self.fromAddress, outputFrom)
+            self.assertEquals(self.toAddress, outputRecipient)
+
+            if UID: # The organizer is local, and server is sending to remote
+                    # attendee
+                txn = self.store.newTransaction()
+                token = (yield txn.imipGetToken(inputOriginator, inputRecipient,
+                    UID))
+                yield txn.commit()
+                self.assertNotEquals(token, None)
+                self.assertEquals(msg["Reply-To"],
+                    "server+%s at example.com" % (token,))
+
+                # Make sure attendee property for organizer exists and matches
+                # the CUA of the organizer property
+                orgValue = self.calendar.getOrganizerProperty().value()
+                self.assertEquals(
+                    orgValue,
+                    self.calendar.getAttendeeProperty([orgValue]).value()
+                )
+
+            else: # Reply only -- the attendee is local, and server is sending reply to remote organizer
+
+                self.assertEquals(msg["Reply-To"], self.fromAddress)
+
+            # Check that we don't send any messages for events completely in
+            # the past.
+            self.sender.smtpSender.reset()
+            txn = self.store.newTransaction()
+            yield self.sender.outbound(
+                txn,
+                inputOriginator,
+                inputRecipient,
+                Component.fromString(inputCalendar.replace("\n", "\r\n")),
+                onlyAfter=PyCalendarDateTime(2021, 1, 1, 0, 0, 0)
+            )
+            yield txn.commit()
+            self.assertFalse(self.sender.smtpSender.sendMessageCalled)
+
+
+    @inlineCallbacks
+    def test_tokens(self):
+        txn = self.store.newTransaction()
+        token = (yield txn.imipLookupByToken("xyzzy"))
+        yield txn.commit()
+        self.assertEquals(token, [])
+
+        txn = self.store.newTransaction()
+        token1 = (yield txn.imipCreateToken("organizer", "attendee", "icaluid"))
+        yield txn.commit()
+
+        txn = self.store.newTransaction()
+        token2 = (yield txn.imipGetToken("organizer", "attendee", "icaluid"))
+        yield txn.commit()
+        self.assertEquals(token1, token2)
+
+        txn = self.store.newTransaction()
+        self.assertEquals((yield txn.imipLookupByToken(token1)),
+            [["organizer", "attendee", "icaluid"]])
+        yield txn.commit()
+
+        txn = self.store.newTransaction()
+        yield txn.imipRemoveToken(token1)
+        yield txn.commit()
+
+        txn = self.store.newTransaction()
+        self.assertEquals((yield txn.imipLookupByToken(token1)), [])
+        yield txn.commit()
+        
+ 
+    @inlineCallbacks
+    def test_mailtoTokens(self):
+        """
+        Make sure old mailto tokens are still honored
+        """
+
+        organizerEmail = "mailto:organizer at example.com"
+
+        # Explictly store a token with mailto: CUA for organizer
+        # (something that doesn't happen any more, but did in the past)
+        txn = self.store.newTransaction()
+        origToken = (yield txn.imipCreateToken(organizerEmail,
+            "mailto:attendee at example.com",
+            "CFDD5E46-4F74-478A-9311-B3FF905449C3"
+            )
+        )
+        yield txn.commit()
+
+        inputCalendar = initialInviteText
+        UID = "CFDD5E46-4F74-478A-9311-B3FF905449C3"
+        inputOriginator = "urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A"
+        inputRecipient = "mailto:attendee at example.com"
+
+        txn = self.store.newTransaction()
+        yield self.sender.outbound(txn, inputOriginator, inputRecipient,
+            Component.fromString(inputCalendar.replace("\n", "\r\n")),
+            onlyAfter=PyCalendarDateTime(2010, 1, 1, 0, 0, 0))
+
+        # Verify we didn't create a new token...
+        txn = self.store.newTransaction()
+        token = (yield txn.imipGetToken(inputOriginator, inputRecipient, UID))
+        yield txn.commit()
+        self.assertEquals(token, None)
+
+        # But instead kept the old one...
+        txn = self.store.newTransaction()
+        token = (yield txn.imipGetToken(organizerEmail, inputRecipient, UID))
+        yield txn.commit()
+        self.assertEquals(token, origToken)
+
+
+    def generateSampleEmail(self):
+        """
+        Invoke L{MailHandler.generateEmail} and parse the result.
+        """
+        calendar = Component.fromString(initialInviteText)
+        msgID, msgTxt = self.sender.generateEmail(
+            inviteState='new',
+            calendar=calendar,
+            orgEmail=u"user01 at localhost",
+            orgCN=u"User Z\xe9ro One",
+            attendees=[(u"Us\xe9r One", "user01 at localhost"),
+                       (u"User 2", "user02 at localhost")],
+            fromAddress="user01 at localhost",
+            replyToAddress="imip-system at localhost",
+            toAddress="user03 at localhost",
+        )
+        message = email.message_from_string(msgTxt)
+        return msgID, message
+
+
+    def test_generateEmail(self):
+        """
+        L{MailHandler.generateEmail} generates a MIME-formatted email with a
+        text/plain part, a text/html part, and a text/calendar part.
+        """
+        msgID, message = self.generateSampleEmail()
+        self.assertEquals(message['Message-ID'], msgID)
+        expectedTypes = set(["text/plain", "text/html", "text/calendar"])
+        actualTypes = set([
+            part.get_content_type() for part in message.walk()
+            if part.get_content_type().startswith("text/")
+        ])
+        self.assertEquals(actualTypes, expectedTypes)
+
+
+    def test_emailEncoding(self):
+        """
+        L{MailHandler.generateEmail} will preserve any non-ASCII characters
+        present in the fields that it formats in the message body.
+        """
+        _ignore_msgID, message = self.generateSampleEmail()
+        textPart = partByType(message, "text/plain")
+        htmlPart = partByType(message, "text/html")
+
+        plainText = textPart.get_payload(decode=True).decode(
+            textPart.get_content_charset()
+        )
+        htmlText = htmlPart.get_payload(decode=True).decode(
+            htmlPart.get_content_charset()
+        )
+
+        self.assertIn(u"Us\u00e9r One", plainText)
+        self.assertIn(u'<a href="mailto:user01 at localhost">Us\u00e9r One</a>',
+                      htmlText)
+
+        # The same assertion, but with the organizer's form.
+        self.assertIn(
+            u'<a href="mailto:user01 at localhost">User Z\u00e9ro One</a>',
+            htmlText)
+
+
+    def test_emailQuoting(self):
+        """
+        L{MailHandler.generateEmail} will HTML-quote all relevant fields in the
+        HTML part, but not the text/plain part.
+        """
+        _ignore_msgID, message = self.generateSampleEmail()
+        htmlPart = partByType(message, "text/html").get_payload(decode=True)
+        plainPart = partByType(message, "text/plain").get_payload(decode=True)
+        expectedPlain = 'awesome description with "<" and "&"'
+        expectedHTML = expectedPlain.replace("&", "&amp;").replace("<", "&lt;")
+
+        self.assertIn(expectedPlain, plainPart)
+        self.assertIn(expectedHTML, htmlPart)
+
+
+    def test_stringFormatTemplateLoader(self):
+        """
+        L{StringFormatTemplateLoader.load} will convert a template with
+        C{%(x)s}-format slots by converting it to a template with C{<t:slot
+        name="x" />} slots, and a renderer on the document element named
+        according to the constructor argument.
+        """
+        class StubElement(Element):
+            loader = StringFormatTemplateLoader(
+                lambda : StringIO(
+                    "<test><alpha>%(slot1)s</alpha>%(other)s</test>"
+                ),
+                "testRenderHere"
+            )
+
+            @renderer
+            def testRenderHere(self, request, tag):
+                return tag.fillSlots(slot1="hello",
+                                     other="world")
+        result = []
+        flattenString(None, StubElement()).addCallback(result.append)
+        self.assertEquals(result,
+                          ["<test><alpha>hello</alpha>world</test>"])
+
+
+    def test_templateLoaderWithAttributes(self):
+        """
+        L{StringFormatTemplateLoader.load} will convert a template with
+        C{%(x)s}-format slots inside attributes into t:attr elements containing
+        t:slot slots.
+        """
+        class StubElement(Element):
+            loader = StringFormatTemplateLoader(
+                lambda : StringIO(
+                    '<test><alpha beta="before %(slot1)s after">inner</alpha>'
+                    '%(other)s</test>'
+                ),
+                "testRenderHere"
+            )
+
+            @renderer
+            def testRenderHere(self, request, tag):
+                return tag.fillSlots(slot1="hello",
+                                     other="world")
+        result = []
+        flattenString(None, StubElement()).addCallback(result.append)
+        self.assertEquals(result,
+                          ['<test><alpha beta="before hello after">'
+                           'inner</alpha>world</test>'])
+
+
+    def test_templateLoaderTagSoup(self):
+        """
+        L{StringFormatTemplateLoader.load} will convert a template with
+        C{%(x)s}-format slots into t:slot slots, and render a well-formed output
+        document, even if the input is malformed (i.e. missing necessary closing
+        tags).
+        """
+        class StubElement(Element):
+            loader = StringFormatTemplateLoader(
+                lambda : StringIO(
+                    '<test><alpha beta="before %(slot1)s after">inner</alpha>'
+                    '%(other)s'
+                ),
+                "testRenderHere"
+            )
+
+            @renderer
+            def testRenderHere(self, request, tag):
+                return tag.fillSlots(slot1="hello",
+                                     other="world")
+        result = []
+        flattenString(None, StubElement()).addCallback(result.append)
+        self.assertEquals(result,
+                          ['<test><alpha beta="before hello after">'
+                           'inner</alpha>world</test>'])
+
+def partByType(message, contentType):
+    """
+    Retrieve a MIME part from an L{email.message.Message} based on a content
+    type.
+    """
+    for part in message.walk():
+        if part.get_content_type() == contentType:
+            return part
+    raise KeyError(contentType)

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/implicit.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/implicit.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/implicit.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -597,6 +597,9 @@
 
                 for rid in self.needs_action_rids:
                     comp = self.calendar.overriddenComponent(rid)
+                    if comp is None:
+                        comp = self.calendar.deriveInstance(rid)
+                        self.calendar.addComponent(comp)
 
                     for attendee in comp.getAllAttendeeProperties():
                         if attendee.hasParameter("PARTSTAT"):

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/itip.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/itip.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/itip.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -332,7 +332,7 @@
         new_master = itip_message.masterComponent()
         attendees = set()
         rids = set()
-        if new_master:
+        if new_master is not None and old_master is not None:
             attendee, partstat, private_comment = iTipProcessing.updateAttendeeData(new_master, old_master)
             if attendee:
                 attendees.add(attendee)

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/processing.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/processing.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/processing.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -560,8 +560,9 @@
                     send_reply = False
                     store_inbox = True
 
-                # Let the store know that no time-range info has changed for a refresh
-                if hasattr(self.request, "doing_attendee_refresh"):
+                # Let the store know that no time-range info has changed for a refresh (assuming that
+                # no auto-accept changes were made)
+                if hasattr(self.request, "doing_attendee_refresh") and not send_reply:
                     new_calendar.noInstanceIndexing = True
 
                 # Update the attendee's copy of the event
@@ -761,17 +762,32 @@
         cuas = self.recipient.principal.calendarUserAddresses()
 
         # First expand current one to get instances (only go 1 year into the future)
-        default_future_expansion_duration = PyCalendarDuration(days=365)
+        default_future_expansion_duration = PyCalendarDuration(days=config.Scheduling.Options.AutoSchedule.FutureFreeBusyDays)
         expand_max = PyCalendarDateTime.getToday() + default_future_expansion_duration
         instances = calendar.expandTimeRanges(expand_max, ignoreInvalidInstances=True)
 
+        # We are goin g to ignore auto-accept processing for anything more than a day old (actually use -2 days
+        # to add some slop to account for possible timezone offsets)
+        min_date = PyCalendarDateTime.getToday()
+        min_date.offsetDay(-2)
+        allOld = True
+
         # Cache the current attendee partstat on the instance object for later use, and
         # also mark whether the instance time slot would be free
         for instance in instances.instances.itervalues():
             attendee = instance.component.getAttendeeProperty(cuas)
             instance.partstat = attendee.parameterValue("PARTSTAT", "NEEDS-ACTION") if attendee else None
             instance.free = True
+            instance.active = (instance.end > min_date)
+            if instance.active:
+                allOld = False
 
+        # If every instance is in the past we punt right here so we don't waste time on freebusy lookups etc.
+        # There will be no auto-accept and no inbox item stored (so as not to waste storage on items that will
+        # never be processed).
+        if allOld:
+            returnValue((False, False, "",))
+
         # Extract UID from primary component as we want to ignore this one if we match it
         # in any calendars.
         comp = calendar.mainComponent(allow_multiple=True)
@@ -795,7 +811,7 @@
             # Now do search for overlapping time-range and set instance.free based
             # on whether there is an overlap or not
             for instance in instances.instances.itervalues():
-                if instance.partstat == "NEEDS-ACTION" and instance.free:
+                if instance.partstat == "NEEDS-ACTION" and instance.free and instance.active:
                     try:
                         # First list is BUSY, second BUSY-TENTATIVE, third BUSY-UNAVAILABLE
                         fbinfo = ([], [], [])
@@ -829,10 +845,11 @@
                 break
 
         # Now adjust the instance.partstat currently set to "NEEDS-ACTION" to the
-        # value determined by auto-accept logic based on instance.free state
+        # value determined by auto-accept logic based on instance.free state. However,
+        # ignore any instance in the past - leave them as NEEDS-ACTION.
         partstat_counts = collections.defaultdict(int)
         for instance in instances.instances.itervalues():
-            if instance.partstat == "NEEDS-ACTION":
+            if instance.partstat == "NEEDS-ACTION" and instance.active:
                 if automode == "accept-always":
                     freePartstat = busyPartstat = "ACCEPTED"
                 elif automode == "decline-always":
@@ -845,14 +862,14 @@
 
         if len(partstat_counts) == 0:
             # Nothing to do
-            returnValue((False, True, "",))
+            returnValue((False, False, "",))
 
         elif len(partstat_counts) == 1:
             # Do the simple case of all PARTSTATs the same separately
             # Extract the ATTENDEE property matching current recipient from the calendar data
             attendeeProps = calendar.getAttendeeProperties(cuas)
             if not attendeeProps:
-                returnValue((False, True, "",))
+                returnValue((False, False, "",))
 
             made_changes = False
             partstat = partstat_counts.keys()[0]
@@ -861,7 +878,7 @@
             store_inbox = partstat == "NEEDS-ACTION"
 
         else:
-            # Hard case: some accepted some declined
+            # Hard case: some accepted, some declined, some needs-action
             # What we will do is mark any master instance as accepted, then mark each existing
             # overridden instance as accepted or declined, and generate new overridden instances for
             # any other declines.
@@ -894,7 +911,7 @@
 
                 if overridden:
                     # Change ATTENDEE property to match new state
-                    if instance.partstat == "NEEDS-ACTION":
+                    if instance.partstat == "NEEDS-ACTION" and instance.active:
                         store_inbox = True
                     made_changes |= self.resetAttendeePartstat(overridden, cuas, instance.partstat)
                 else:
@@ -904,7 +921,7 @@
                     if derived:
                         attendee = derived.getAttendeeProperty(cuas)
                         if attendee:
-                            if instance.partstat == "NEEDS-ACTION":
+                            if instance.partstat == "NEEDS-ACTION" and instance.active:
                                 store_inbox = True
                             self.resetAttendeePartstat(derived, cuas, instance.partstat, hadMasterRsvp)
                             made_changes = True

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_icaldiff.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_icaldiff.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_icaldiff.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -2014,6 +2014,17 @@
 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
 BEGIN:VEVENT
 UID:12345-67890
+RECURRENCE-ID:20080601T120000Z
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1 at example.com
+ATTENDEE;PARTSTAT=DECLINED;RSVP=TRUE:mailto:user2 at example.com
+ORGANIZER;CN=User 01:mailto:user1 at example.com
+TRANSP:TRANSPARENT
+X-CALENDARSERVER-HIDDEN-INSTANCE:T
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
 RECURRENCE-ID:20080604T120000Z
 DTSTART:20080604T130000Z
 DTEND:20080604T140000Z

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_itip.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_itip.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_itip.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
 from pycalendar.datetime import PyCalendarDateTime
 from pycalendar.timezone import PyCalendarTimezone
@@ -26,6 +27,210 @@
     iCalendar support tests
     """
 
+    def test_processReply(self):
+        """
+        Test iTIPProcessing.processReply
+        """
+
+        data = (
+            (
+                "1.1 Simple Reply - non recurring",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071114T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:user02 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+METHOD:REPLY
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071115T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user02 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071114T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0:mailto:user02 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+            ),
+            (
+                "1.2 Simple Reply - recurring no overrides",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071114T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:user02 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+METHOD:REPLY
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071115T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user02 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071114T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0:mailto:user02 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+            ),
+            (
+                "1.3 Simple Reply - recurring with missing master",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1
+RECURRENCE-ID:20071114T000000Z
+DTSTART:20071114T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:user02 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+METHOD:REPLY
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071115T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user02 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890-1
+RECURRENCE-ID:20071114T000000Z
+DTSTART:20071115T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user02 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1
+RECURRENCE-ID:20071114T000000Z
+DTSTART:20071114T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0:mailto:user02 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                True,
+            ),
+            (
+                "1.4 Simple Reply - recurring with missing master, invalid override",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-1
+RECURRENCE-ID:20071114T000000Z
+DTSTART:20071114T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:user02 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+METHOD:REPLY
+BEGIN:VEVENT
+UID:12345-67890-1
+DTSTART:20071114T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user02 at example.com
+RRULE:FREQ=DAILY
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890-1
+RECURRENCE-ID:20071115T000000Z
+DTSTART:20071115T000000Z
+DTSTAMP:20071114T000000Z
+ORGANIZER:mailto:user01 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:user02 at example.com
+END:VEVENT
+END:VCALENDAR
+""",
+                None,
+                False,
+            ),
+        )
+
+        for title, calendar_txt, itip_txt, changed_txt, expected in data:
+            calendar = Component.fromString(calendar_txt)
+            itip = Component.fromString(itip_txt)
+            if expected:
+                changed = Component.fromString(changed_txt)
+
+            result, _ignore = iTipProcessing.processReply(itip, calendar)
+            self.assertEqual(result, expected, msg="Result mismatch: %s" % (title,))
+            if expected:
+                self.assertEqual(changed, calendar, msg="Calendar mismatch: %s" % (title,))
+
+
     def test_update_attendee_partstat(self):
 
         data = (
@@ -867,9 +1072,9 @@
             reply_success, reply_processed = iTipProcessing.processReply(itipmsg, calendar)
 #            if not description.startswith("#3.1"):
 #                continue
-#            print description
-#            print str(calendar)
-#            print str(result)
+#            print(description)
+#            print(str(calendar))
+#            print(str(result))
             self.assertEqual(
                 str(calendar).replace("\r", "").replace("\n ", ""),
                 str(result).replace("\n ", ""),

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_utils.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_utils.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_utils.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -97,7 +97,7 @@
             }
         },
         "user02" : {
-            "calendar1" : {
+            "calendar2" : {
                 "2.ics" : (ATTENDEE_ICS, metadata,),
             },
             "calendar3" : {
@@ -151,8 +151,8 @@
         request = FakeRequest(self.rootResource, "PUT", path='/user01/outbox')
         for uri in (
             "/calendars/__uids__/user01/calendar1/1.ics",
-            "/calendars/__uids__/user02/calendar1/2.ics",
-            "/calendars/__uids__/user02/calendar2/3.ics",
+            "/calendars/__uids__/user02/calendar2/2.ics",
+            "/calendars/__uids__/user02/calendar3/3.ics",
         ):
             resource = (yield request.locateResource(uri))
             self.assertNotEqual(resource, None)
@@ -171,8 +171,8 @@
         request = FakeRequest(self.rootResource, "PUT", path='/user01/outbox')
         for uri in (
             "/calendars/__uids__/user01/calendar1/1.ics",
-            "/calendars/__uids__/user02/calendar1/2.ics",
-            "/calendars/__uids__/user02/calendar2/3.ics",
+            "/calendars/__uids__/user02/calendar2/2.ics",
+            "/calendars/__uids__/user02/calendar3/3.ics",
         ):
             resource = (yield request.locateResource(uri))
             self.assertNotEqual(resource, None)

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/sharing.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -393,7 +393,8 @@
             returnValue(result)
 
         # Direct shares use underlying privileges of shared collection
-        userprivs = []
+        userprivs = [
+        ]
         if access in ("read-only", "read-write",):
             userprivs.append(element.Privilege(element.Read()))
             userprivs.append(element.Privilege(element.ReadACL()))
@@ -628,7 +629,7 @@
     @inlineCallbacks
     def _invitationForUID(self, uid):
         """
-        Get an invitation for an invitations uid 
+        Get an invitation for an invitations uid
         """
         invitations = yield self._allInvitations()
         for invitation in invitations:
@@ -1228,8 +1229,8 @@
 
         if sharedResource.isCalendarCollection():
             shareeHomeResource = yield sharee.calendarHome(request)
-            shareeCalenderURL = joinURL(shareeHomeResource.url(), share.name())
-            shareeCalender = yield request.locateResource(shareeCalenderURL)
+            sharedAsURL = joinURL(shareeHomeResource.url(), share.name())
+            shareeCalender = yield request.locateResource(sharedAsURL)
             shareeCalender.setShare(share)
 
             # For calendars only, per-user displayname and color
@@ -1255,27 +1256,19 @@
 
         elif sharedResource.isAddressBookCollection():
             shareeHomeResource = yield sharee.addressBookHome(request)
-            shareeAddressBookURL = joinURL(shareeHomeResource.url(), share.ownerUID())
-            shareeAddressBook = yield request.locateResource(shareeAddressBookURL)
+            sharedAsURL = joinURL(shareeHomeResource.url(), share.ownerUID())
+            shareeAddressBook = yield request.locateResource(sharedAsURL)
             shareeAddressBook.setShare(share)
 
         elif sharedResource.isGroup():
             shareeHomeResource = yield sharee.addressBookHome(request)
-            shareeGroupURL = joinURL(shareeHomeResource.url(), share.ownerUID(), share.name())
-            shareeGroup = yield request.locateResource(shareeGroupURL)
+            sharedAsURL = joinURL(shareeHomeResource.url(), share.ownerUID(), share.name())
+            shareeGroup = yield request.locateResource(sharedAsURL)
             shareeGroup.setShare(share)
 
         # Notify client of changes
         yield self.notifyChanged()
 
-        #FIXME: shouldn't sharedAsURLbe the same as shareeCollectionURL ?
-        if sharedResource.isCalendarCollection():
-            sharedAsURL = joinURL(self.url(), share.name())
-        elif sharedResource.isAddressBookCollection():
-            sharedAsURL = joinURL(self.url(), share.ownerUID())
-        elif sharedResource.isGroup():
-            sharedAsURL = joinURL(self.url(), share.ownerUID(), share.name())
-
         # Return the URL of the shared collection
         returnValue(XMLResponse(
             code=responsecode.OK,
@@ -1326,7 +1319,7 @@
         shared = (yield request.locateResource(shareURL))
         displayname = shared.displayName()
 
-        #FIXME: remove if not needed
+        #FIXME: Remove! Probably obsolete
         if self.isCalendarCollection():
             # For backwards compatibility we need to sync this up with the calendar-free-busy-set on the inbox
             principal = (yield self.resourceOwnerPrincipal(request))

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/stdconfig.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/stdconfig.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -302,6 +302,10 @@
                                     # the master process, rather than having
                                     # each client make its connections directly.
 
+    "FailIfUpgradeNeeded"  : True, # Set to True to prevent the server or utility tools
+                                   # tools from running if the database needs a schema
+                                   # upgrade.
+
     #
     # Types of service provided
     #
@@ -713,6 +717,7 @@
                                                                    # "accept-if-free"  - accept if free, do nothing if busy
                                                                    # "decline-if-busy" - decline if busy, do nothing if free
                                                                    # "automatic"       - accept if free, decline if busy
+                "FutureFreeBusyDays"              : 3 * 365,       # How far into the future to check for booking conflicts
             }
         }
     },
@@ -731,14 +736,12 @@
         "CoalesceSeconds" : 3,
 
         "Services" : {
-            "ApplePushNotifier" : {
-                "Service" : "calendarserver.push.applepush.ApplePushNotifierService",
+            "APNS" : {
                 "Enabled" : False,
                 "SubscriptionURL" : "apns",
                 "SubscriptionRefreshIntervalSeconds" : 2 * 24 * 60 * 60, # How often the client should re-register (2 days)
                 "SubscriptionPurgeIntervalSeconds" : 12 * 60 * 60, # How often a purge is done (12 hours)
                 "SubscriptionPurgeSeconds" : 14 * 24 * 60 * 60, # How old a subscription must be before it's purged (14 days)
-                "DataHost" : "",
                 "ProviderHost" : "gateway.push.apple.com",
                 "ProviderPort" : 2195,
                 "FeedbackHost" : "feedback.push.apple.com",
@@ -762,13 +765,11 @@
                     "Topic" : "",
                 },
             },
-            "AMPNotifier" : {
-                "Service" : "calendarserver.push.amppush.AMPPushNotifierService",
+            "AMP" : {
                 "Enabled" : False,
                 "Port" : 62311,
                 "EnableStaggering" : False,
                 "StaggerSeconds" : 3,
-                "DataHost" : "",
             },
         }
     },
@@ -1342,7 +1343,7 @@
     if reloading:
         return
 
-    for key, service in configDict.Notifications["Services"].iteritems():
+    for _ignore_key, service in configDict.Notifications["Services"].iteritems():
         if service["Enabled"]:
             configDict.Notifications["Enabled"] = True
             break
@@ -1351,14 +1352,7 @@
 
     for key, service in configDict.Notifications["Services"].iteritems():
 
-        if (
-            service["Service"] == "calendarserver.push.applepush.ApplePushNotifierService" and
-            service["Enabled"]
-        ):
-            # The default for apple push DataHost is ServerHostName
-            if service["DataHost"] == "":
-                service["DataHost"] = configDict.ServerHostName
-
+        if (key == "APNS" and service["Enabled"]):
             # Retrieve APN topics from certificates if not explicitly set
             for protocol, accountName in (
                 ("CalDAV", "apns:com.apple.calendar"),
@@ -1386,18 +1380,9 @@
                 except KeychainPasswordNotFound:
                     # The password doesn't exist in the keychain.
                     log.info("%s APN certificate passphrase not found in keychain" % (protocol,))
-                    
-        if (
-            service["Service"] == "calendarserver.push.amppush.AMPPushNotifierService" and
-            service["Enabled"]
-        ):
-            # The default for apple push DataHost is ServerHostName
-            if service["DataHost"] == "":
-                service["DataHost"] = configDict.ServerHostName
 
 
 
-
 def _updateScheduling(configDict, reloading=False):
     #
     # Scheduling

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/test/util.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/test/util.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
-
+from __future__ import print_function
 from __future__ import with_statement
 
 import os
@@ -340,7 +340,7 @@
                     if childStructure.has_key("@optional"):
                         return True
                     else:
-                        print "Missing:", childPath
+                        print("Missing:", childPath)
                         return False
 
                 if childStructure.has_key("@contents"):
@@ -354,15 +354,15 @@
                             contents = child.read()
                             for term in expectedContents:
                                 if term not in contents:
-                                    print "Contents mismatch:", childPath
-                                    print "Expecting match:\n%s\n\nActual:\n%s\n" % (term, contents)
+                                    print("Contents mismatch:", childPath)
+                                    print("Expecting match:\n%s\n\nActual:\n%s\n" % (term, contents))
                                     return False
                     else:
                         with open(childPath) as child:
                             contents = child.read()
                             if contents != childStructure["@contents"]:
-                                print "Contents mismatch:", childPath
-                                print "Expected:\n%s\n\nActual:\n%s\n" % (childStructure["@contents"], contents)
+                                print("Contents mismatch:", childPath)
+                                print("Expected:\n%s\n\nActual:\n%s\n" % (childStructure["@contents"], contents))
                                 return False
 
                 else:
@@ -382,8 +382,8 @@
                         for attr, value in xattrs.iteritems():
                             if isinstance(value, str):
                                 if xattr.getxattr(childPath, attr) != value:
-                                    print "Xattr mismatch:", childPath, attr
-                                    print (xattr.getxattr(childPath, attr), " != ", value)
+                                    print("Xattr mismatch:", childPath, attr)
+                                    print((xattr.getxattr(childPath, attr), " != ", value))
                                     return False
                             else: # method
                                 if not value(xattr.getxattr(childPath, attr)):
@@ -398,7 +398,7 @@
 
             if actual:
                 # There are unexpected children
-                print "Unexpected:", actual, 'in', parent
+                print("Unexpected:", actual, 'in', parent)
                 return False
 
             return True

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/base/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/base/datastore/file.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/base/datastore/file.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,24 +14,25 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from __future__ import print_function
 
-
 """
 Common utility functions for a file based datastore.
 """
 
+from zope.interface.declarations import implements
+
+from twisted.python import hashlib
+
 from twext.python.log import LoggingMixIn
 from twext.enterprise.ienterprise import AlreadyFinishedError
+from twext.web2.dav.resource import TwistedGETContentMD5
 from txdav.idav import IDataStoreObject
 from txdav.base.propertystore.base import PropertyName
+from txdav.xml.element import GETContentType
 
-from txdav.xml.rfc2518 import GETContentType
-from twext.web2.dav.resource import TwistedGETContentMD5
 
-from twisted.python import hashlib
 
-from zope.interface.declarations import implements
-
 def isValidName(name):
     """
     Determine if the given string is a valid name.  i.e. does it conflict with
@@ -102,12 +103,12 @@
 
     def __del__(self):
         if not self.done and self.info:
-            print '**** UNCOMMITTED TRANSACTION (%s) BEING GARBAGE COLLECTED ****' % (
+            print("**** UNCOMMITTED TRANSACTION (%s) BEING GARBAGE COLLECTED ****") % (
                 self.name,
             )
             for info in self.info:
-                print '   ', info
-            print '---- END OF OPERATIONS'
+                print("   "), info
+            print("---- END OF OPERATIONS")
 
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current-oracle-dialect.sql	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current-oracle-dialect.sql	2013-03-07 22:42:21 UTC (rev 10867)
@@ -95,7 +95,6 @@
     "ATTACHMENTS_MODE" integer default 0 not null,
     "DROPBOX_ID" nvarchar2(255),
     "ORGANIZER" nvarchar2(255),
-    "ORGANIZER_OBJECT" integer references CALENDAR_OBJECT,
     "RECURRANCE_MIN" date,
     "RECURRANCE_MAX" date,
     "ACCESS" integer default 0 not null,
@@ -306,7 +305,7 @@
     "VALUE" nvarchar2(255)
 );
 
-insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '16');
+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '17');
 insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '3');
 insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '1');
 create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
@@ -327,8 +326,8 @@
     RECURRANCE_MAX
 );
 
-create index CALENDAR_OBJECT_ORGAN_7ce24750 on CALENDAR_OBJECT (
-    ORGANIZER_OBJECT
+create index CALENDAR_OBJECT_ICALE_82e731d5 on CALENDAR_OBJECT (
+    ICALENDAR_UID
 );
 
 create index CALENDAR_OBJECT_DROPB_de041d80 on CALENDAR_OBJECT (

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql	2013-03-07 22:42:21 UTC (rev 10867)
@@ -176,7 +176,6 @@
   ATTACHMENTS_MODE     integer      default 0 not null, -- enum CALENDAR_OBJECT_ATTACHMENTS_MODE
   DROPBOX_ID           varchar(255),
   ORGANIZER            varchar(255),
-  ORGANIZER_OBJECT     integer      references CALENDAR_OBJECT,
   RECURRANCE_MIN       date,        -- minimum date that recurrences have been expanded to.
   RECURRANCE_MAX       date,        -- maximum date that recurrences have been expanded to.
   ACCESS               integer      default 0 not null,
@@ -203,8 +202,8 @@
 create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_RECURRANCE_MAX on
   CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, RECURRANCE_MAX);
 
-create index CALENDAR_OBJECT_ORGANIZER_OBJECT on
-  CALENDAR_OBJECT(ORGANIZER_OBJECT);
+create index CALENDAR_OBJECT_ICALENDAR_UID on
+  CALENDAR_OBJECT(ICALENDAR_UID);
 
 create index CALENDAR_OBJECT_DROPBOX_ID on
   CALENDAR_OBJECT(DROPBOX_ID);
@@ -342,10 +341,10 @@
 ----------------------
 
 create table ADDRESSBOOK_HOME (
-  RESOURCE_ID      	integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
-  HOME_RESOURCE_ID	integer      default nextval('RESOURCE_ID_SEQ') not null, 	 -- implicit index
-  OWNER_UID        	varchar(255) not null unique,                                -- implicit index
-  DATAVERSION      	integer      default 0 not null
+  RESOURCE_ID      integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  HOME_RESOURCE_ID integer      default nextval('RESOURCE_ID_SEQ') not null, 	-- implicit index
+  OWNER_UID        varchar(255) not null unique,                                -- implicit index
+  DATAVERSION      integer      default 0 not null
 );
 
 
@@ -393,7 +392,7 @@
   RESOURCE_NAME           varchar(255) not null,
   VCARD_TEXT              text         not null,
   VCARD_UID               varchar(255) not null,
-  KIND 			  		  integer      not null, -- enum OBJECT_KIND 
+  KIND 			  		  integer      not null, -- enum OBJECT_KIND
   MD5                     char(32)     not null,
   CREATED                 timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
   MODIFIED                timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
@@ -623,6 +622,6 @@
   VALUE                         varchar(255)
 );
 
-insert into CALENDARSERVER values ('VERSION', '16');
+insert into CALENDARSERVER values ('VERSION', '17');
 insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '3');
 insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '1');

Copied: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/old/oracle-dialect/v16.sql (from rev 10865, CalendarServer/trunk/txdav/common/datastore/sql_schema/old/oracle-dialect/v16.sql)
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/old/oracle-dialect/v16.sql	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/old/oracle-dialect/v16.sql	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,400 @@
+create sequence RESOURCE_ID_SEQ;
+create sequence INSTANCE_ID_SEQ;
+create sequence ATTACHMENT_ID_SEQ;
+create sequence REVISION_SEQ;
+create sequence WORKITEM_SEQ;
+create table NODE_INFO (
+    "HOSTNAME" nvarchar2(255),
+    "PID" integer not null,
+    "PORT" integer not null,
+    "TIME" timestamp default CURRENT_TIMESTAMP at time zone 'UTC' not null, 
+    primary key("HOSTNAME", "PORT")
+);
+
+create table NAMED_LOCK (
+    "LOCK_NAME" nvarchar2(255) primary key
+);
+
+create table CALENDAR_HOME (
+    "RESOURCE_ID" integer primary key,
+    "OWNER_UID" nvarchar2(255) unique,
+    "DATAVERSION" integer default 0 not null
+);
+
+create table CALENDAR_HOME_METADATA (
+    "RESOURCE_ID" integer primary key references CALENDAR_HOME on delete cascade,
+    "QUOTA_USED_BYTES" integer default 0 not null,
+    "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table CALENDAR (
+    "RESOURCE_ID" integer primary key
+);
+
+create table CALENDAR_METADATA (
+    "RESOURCE_ID" integer primary key references CALENDAR on delete cascade,
+    "SUPPORTED_COMPONENTS" nvarchar2(255) default null,
+    "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table NOTIFICATION_HOME (
+    "RESOURCE_ID" integer primary key,
+    "OWNER_UID" nvarchar2(255) unique
+);
+
+create table NOTIFICATION (
+    "RESOURCE_ID" integer primary key,
+    "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME,
+    "NOTIFICATION_UID" nvarchar2(255),
+    "XML_TYPE" nvarchar2(255),
+    "XML_DATA" nclob,
+    "MD5" nchar(32),
+    "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique("NOTIFICATION_UID", "NOTIFICATION_HOME_RESOURCE_ID")
+);
+
+create table CALENDAR_BIND (
+    "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+    "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+    "CALENDAR_RESOURCE_NAME" nvarchar2(255),
+    "BIND_MODE" integer not null,
+    "BIND_STATUS" integer not null,
+    "MESSAGE" nclob, 
+    primary key("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID"), 
+    unique("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_NAME")
+);
+
+create table CALENDAR_BIND_MODE (
+    "ID" integer primary key,
+    "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('own', 0);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('read', 1);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('write', 2);
+insert into CALENDAR_BIND_MODE (DESCRIPTION, ID) values ('direct', 3);
+create table CALENDAR_BIND_STATUS (
+    "ID" integer primary key,
+    "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invited', 0);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('accepted', 1);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('declined', 2);
+insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invalid', 3);
+create table CALENDAR_OBJECT (
+    "RESOURCE_ID" integer primary key,
+    "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+    "RESOURCE_NAME" nvarchar2(255),
+    "ICALENDAR_TEXT" nclob,
+    "ICALENDAR_UID" nvarchar2(255),
+    "ICALENDAR_TYPE" nvarchar2(255),
+    "ATTACHMENTS_MODE" integer default 0 not null,
+    "DROPBOX_ID" nvarchar2(255),
+    "ORGANIZER" nvarchar2(255),
+    "ORGANIZER_OBJECT" integer references CALENDAR_OBJECT,
+    "RECURRANCE_MIN" date,
+    "RECURRANCE_MAX" date,
+    "ACCESS" integer default 0 not null,
+    "SCHEDULE_OBJECT" integer default 0,
+    "SCHEDULE_TAG" nvarchar2(36) default null,
+    "SCHEDULE_ETAGS" nclob default null,
+    "PRIVATE_COMMENTS" integer default 0 not null,
+    "MD5" nchar(32),
+    "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique("CALENDAR_RESOURCE_ID", "RESOURCE_NAME")
+);
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MO (
+    "ID" integer primary key,
+    "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('none', 0);
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('read', 1);
+insert into CALENDAR_OBJECT_ATTACHMENTS_MO (DESCRIPTION, ID) values ('write', 2);
+create table CALENDAR_ACCESS_TYPE (
+    "ID" integer primary key,
+    "DESCRIPTION" nvarchar2(32) unique
+);
+
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('', 0);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('public', 1);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('private', 2);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('confidential', 3);
+insert into CALENDAR_ACCESS_TYPE (DESCRIPTION, ID) values ('restricted', 4);
+create table TIME_RANGE (
+    "INSTANCE_ID" integer primary key,
+    "CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
+    "CALENDAR_OBJECT_RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade,
+    "FLOATING" integer not null,
+    "START_DATE" timestamp not null,
+    "END_DATE" timestamp not null,
+    "FBTYPE" integer not null,
+    "TRANSPARENT" integer not null
+);
+
+create table FREE_BUSY_TYPE (
+    "ID" integer primary key,
+    "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('unknown', 0);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('free', 1);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy', 2);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-unavailable', 3);
+insert into FREE_BUSY_TYPE (DESCRIPTION, ID) values ('busy-tentative', 4);
+create table TRANSPARENCY (
+    "TIME_RANGE_INSTANCE_ID" integer not null references TIME_RANGE on delete cascade,
+    "USER_ID" nvarchar2(255),
+    "TRANSPARENT" integer not null
+);
+
+create table ATTACHMENT (
+    "ATTACHMENT_ID" integer primary key,
+    "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+    "DROPBOX_ID" nvarchar2(255),
+    "CONTENT_TYPE" nvarchar2(255),
+    "SIZE" integer not null,
+    "MD5" nchar(32),
+    "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "PATH" nvarchar2(1024)
+);
+
+create table ATTACHMENT_CALENDAR_OBJECT (
+    "ATTACHMENT_ID" integer not null references ATTACHMENT on delete cascade,
+    "MANAGED_ID" nvarchar2(255),
+    "CALENDAR_OBJECT_RESOURCE_ID" integer not null references CALENDAR_OBJECT on delete cascade, 
+    primary key("ATTACHMENT_ID", "CALENDAR_OBJECT_RESOURCE_ID"), 
+    unique("MANAGED_ID", "CALENDAR_OBJECT_RESOURCE_ID")
+);
+
+create table RESOURCE_PROPERTY (
+    "RESOURCE_ID" integer not null,
+    "NAME" nvarchar2(255),
+    "VALUE" nclob,
+    "VIEWER_UID" nvarchar2(255), 
+    primary key("RESOURCE_ID", "NAME", "VIEWER_UID")
+);
+
+create table ADDRESSBOOK_HOME (
+    "RESOURCE_ID" integer primary key,
+    "OWNER_UID" nvarchar2(255) unique,
+    "DATAVERSION" integer default 0 not null
+);
+
+create table ADDRESSBOOK_HOME_METADATA (
+    "RESOURCE_ID" integer primary key references ADDRESSBOOK_HOME on delete cascade,
+    "QUOTA_USED_BYTES" integer default 0 not null,
+    "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table ADDRESSBOOK (
+    "RESOURCE_ID" integer primary key
+);
+
+create table ADDRESSBOOK_METADATA (
+    "RESOURCE_ID" integer primary key references ADDRESSBOOK on delete cascade,
+    "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table ADDRESSBOOK_BIND (
+    "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME,
+    "ADDRESSBOOK_RESOURCE_ID" integer not null references ADDRESSBOOK on delete cascade,
+    "ADDRESSBOOK_RESOURCE_NAME" nvarchar2(255),
+    "BIND_MODE" integer not null,
+    "BIND_STATUS" integer not null,
+    "MESSAGE" nclob, 
+    primary key("ADDRESSBOOK_HOME_RESOURCE_ID", "ADDRESSBOOK_RESOURCE_ID"), 
+    unique("ADDRESSBOOK_HOME_RESOURCE_ID", "ADDRESSBOOK_RESOURCE_NAME")
+);
+
+create table ADDRESSBOOK_OBJECT (
+    "RESOURCE_ID" integer primary key,
+    "ADDRESSBOOK_RESOURCE_ID" integer not null references ADDRESSBOOK on delete cascade,
+    "RESOURCE_NAME" nvarchar2(255),
+    "VCARD_TEXT" nclob,
+    "VCARD_UID" nvarchar2(255),
+    "MD5" nchar(32),
+    "CREATED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "MODIFIED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    unique("ADDRESSBOOK_RESOURCE_ID", "RESOURCE_NAME"), 
+    unique("ADDRESSBOOK_RESOURCE_ID", "VCARD_UID")
+);
+
+create table CALENDAR_OBJECT_REVISIONS (
+    "CALENDAR_HOME_RESOURCE_ID" integer not null references CALENDAR_HOME,
+    "CALENDAR_RESOURCE_ID" integer references CALENDAR,
+    "CALENDAR_NAME" nvarchar2(255) default null,
+    "RESOURCE_NAME" nvarchar2(255),
+    "REVISION" integer not null,
+    "DELETED" integer not null
+);
+
+create table ADDRESSBOOK_OBJECT_REVISIONS (
+    "ADDRESSBOOK_HOME_RESOURCE_ID" integer not null references ADDRESSBOOK_HOME,
+    "ADDRESSBOOK_RESOURCE_ID" integer references ADDRESSBOOK,
+    "ADDRESSBOOK_NAME" nvarchar2(255) default null,
+    "RESOURCE_NAME" nvarchar2(255),
+    "REVISION" integer not null,
+    "DELETED" integer not null
+);
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+    "NOTIFICATION_HOME_RESOURCE_ID" integer not null references NOTIFICATION_HOME on delete cascade,
+    "RESOURCE_NAME" nvarchar2(255),
+    "REVISION" integer not null,
+    "DELETED" integer not null, 
+    unique("NOTIFICATION_HOME_RESOURCE_ID", "RESOURCE_NAME")
+);
+
+create table APN_SUBSCRIPTIONS (
+    "TOKEN" nvarchar2(255),
+    "RESOURCE_KEY" nvarchar2(255),
+    "MODIFIED" integer not null,
+    "SUBSCRIBER_GUID" nvarchar2(255),
+    "USER_AGENT" nvarchar2(255) default null,
+    "IP_ADDR" nvarchar2(255) default null, 
+    primary key("TOKEN", "RESOURCE_KEY")
+);
+
+create table IMIP_TOKENS (
+    "TOKEN" nvarchar2(255),
+    "ORGANIZER" nvarchar2(255),
+    "ATTENDEE" nvarchar2(255),
+    "ICALUID" nvarchar2(255),
+    "ACCESSED" timestamp default CURRENT_TIMESTAMP at time zone 'UTC', 
+    primary key("ORGANIZER", "ATTENDEE", "ICALUID")
+);
+
+create table IMIP_INVITATION_WORK (
+    "WORK_ID" integer primary key not null,
+    "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "FROM_ADDR" nvarchar2(255),
+    "TO_ADDR" nvarchar2(255),
+    "ICALENDAR_TEXT" nclob
+);
+
+create table IMIP_POLLING_WORK (
+    "WORK_ID" integer primary key not null,
+    "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC'
+);
+
+create table IMIP_REPLY_WORK (
+    "WORK_ID" integer primary key not null,
+    "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "ORGANIZER" nvarchar2(255),
+    "ATTENDEE" nvarchar2(255),
+    "ICALENDAR_TEXT" nclob
+);
+
+create table PUSH_NOTIFICATION_WORK (
+    "WORK_ID" integer primary key not null,
+    "NOT_BEFORE" timestamp default CURRENT_TIMESTAMP at time zone 'UTC',
+    "PUSH_ID" nvarchar2(255)
+);
+
+create table CALENDARSERVER (
+    "NAME" nvarchar2(255) primary key,
+    "VALUE" nvarchar2(255)
+);
+
+insert into CALENDARSERVER (NAME, VALUE) values ('VERSION', '16');
+insert into CALENDARSERVER (NAME, VALUE) values ('CALENDAR-DATAVERSION', '3');
+insert into CALENDARSERVER (NAME, VALUE) values ('ADDRESSBOOK-DATAVERSION', '1');
+create index NOTIFICATION_NOTIFICA_f891f5f9 on NOTIFICATION (
+    NOTIFICATION_HOME_RESOURCE_ID
+);
+
+create index CALENDAR_BIND_RESOURC_e57964d4 on CALENDAR_BIND (
+    CALENDAR_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_CALEN_a9a453a9 on CALENDAR_OBJECT (
+    CALENDAR_RESOURCE_ID,
+    ICALENDAR_UID
+);
+
+create index CALENDAR_OBJECT_CALEN_96e83b73 on CALENDAR_OBJECT (
+    CALENDAR_RESOURCE_ID,
+    RECURRANCE_MAX
+);
+
+create index CALENDAR_OBJECT_ORGAN_7ce24750 on CALENDAR_OBJECT (
+    ORGANIZER_OBJECT
+);
+
+create index CALENDAR_OBJECT_DROPB_de041d80 on CALENDAR_OBJECT (
+    DROPBOX_ID
+);
+
+create index TIME_RANGE_CALENDAR_R_beb6e7eb on TIME_RANGE (
+    CALENDAR_RESOURCE_ID
+);
+
+create index TIME_RANGE_CALENDAR_O_acf37bd1 on TIME_RANGE (
+    CALENDAR_OBJECT_RESOURCE_ID
+);
+
+create index TRANSPARENCY_TIME_RAN_5f34467f on TRANSPARENCY (
+    TIME_RANGE_INSTANCE_ID
+);
+
+create index ATTACHMENT_CALENDAR_H_0078845c on ATTACHMENT (
+    CALENDAR_HOME_RESOURCE_ID
+);
+
+create index ADDRESSBOOK_BIND_RESO_205aa75c on ADDRESSBOOK_BIND (
+    ADDRESSBOOK_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_REVIS_3a3956c4 on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_HOME_RESOURCE_ID,
+    CALENDAR_RESOURCE_ID
+);
+
+create index CALENDAR_OBJECT_REVIS_2643d556 on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_RESOURCE_ID,
+    RESOURCE_NAME
+);
+
+create index CALENDAR_OBJECT_REVIS_265c8acf on CALENDAR_OBJECT_REVISIONS (
+    CALENDAR_RESOURCE_ID,
+    REVISION
+);
+
+create index ADDRESSBOOK_OBJECT_RE_f460d62d on ADDRESSBOOK_OBJECT_REVISIONS (
+    ADDRESSBOOK_HOME_RESOURCE_ID,
+    ADDRESSBOOK_RESOURCE_ID
+);
+
+create index ADDRESSBOOK_OBJECT_RE_9a848f39 on ADDRESSBOOK_OBJECT_REVISIONS (
+    ADDRESSBOOK_RESOURCE_ID,
+    RESOURCE_NAME
+);
+
+create index ADDRESSBOOK_OBJECT_RE_cb101e6b on ADDRESSBOOK_OBJECT_REVISIONS (
+    ADDRESSBOOK_RESOURCE_ID,
+    REVISION
+);
+
+create index NOTIFICATION_OBJECT_R_036a9cee on NOTIFICATION_OBJECT_REVISIONS (
+    NOTIFICATION_HOME_RESOURCE_ID,
+    REVISION
+);
+
+create index APN_SUBSCRIPTIONS_RES_9610d78e on APN_SUBSCRIPTIONS (
+    RESOURCE_KEY
+);
+
+create index IMIP_TOKENS_TOKEN_e94b918f on IMIP_TOKENS (
+    TOKEN
+);
+

Copied: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/old/postgres-dialect/v16.sql (from rev 10865, CalendarServer/trunk/txdav/common/datastore/sql_schema/old/postgres-dialect/v16.sql)
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/old/postgres-dialect/v16.sql	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/old/postgres-dialect/v16.sql	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,573 @@
+-- -*- test-case-name: txdav.caldav.datastore.test.test_sql,txdav.carddav.datastore.test.test_sql -*-
+
+----
+-- 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.
+----
+
+-----------------
+-- Resource ID --
+-----------------
+
+create sequence RESOURCE_ID_SEQ;
+
+-------------------------
+-- Cluster Bookkeeping --
+-------------------------
+
+-- Information about a process connected to this database.
+
+-- Note that this must match the node info schema in twext.enterprise.queue.
+create table NODE_INFO (
+  HOSTNAME  varchar(255) not null,
+  PID       integer not null,
+  PORT      integer not null,
+  TIME      timestamp not null default timezone('UTC', CURRENT_TIMESTAMP),
+
+  primary key (HOSTNAME, PORT)
+);
+
+-- Unique named locks.  This table should always be empty, but rows are
+-- temporarily created in order to prevent undesirable concurrency.
+create table NAMED_LOCK (
+    LOCK_NAME varchar(255) primary key
+);
+
+
+-------------------
+-- Calendar Home --
+-------------------
+
+create table CALENDAR_HOME (
+  RESOURCE_ID      integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  OWNER_UID        varchar(255) not null unique,                                 -- implicit index
+  DATAVERSION      integer      default 0 not null
+);
+
+----------------------------
+-- Calendar Home Metadata --
+----------------------------
+
+create table CALENDAR_HOME_METADATA (
+  RESOURCE_ID      integer      primary key references CALENDAR_HOME on delete cascade, -- implicit index
+  QUOTA_USED_BYTES integer      default 0 not null,
+  CREATED          timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED         timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+--------------
+-- Calendar --
+--------------
+
+create table CALENDAR (
+  RESOURCE_ID integer   primary key default nextval('RESOURCE_ID_SEQ') -- implicit index
+);
+
+
+-----------------------
+-- Calendar Metadata --
+-----------------------
+
+create table CALENDAR_METADATA (
+  RESOURCE_ID           integer   primary key references CALENDAR on delete cascade, -- implicit index
+  SUPPORTED_COMPONENTS  varchar(255) default null,
+  CREATED               timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED              timestamp default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+---------------------------
+-- Sharing Notifications --
+---------------------------
+
+create table NOTIFICATION_HOME (
+  RESOURCE_ID integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  OWNER_UID   varchar(255) not null unique                                 -- implicit index
+);
+
+create table NOTIFICATION (
+  RESOURCE_ID                   integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME,
+  NOTIFICATION_UID              varchar(255) not null,
+  XML_TYPE                      varchar(255) not null,
+  XML_DATA                      text         not null,
+  MD5                           char(32)     not null,
+  CREATED                       timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                      timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+
+  unique(NOTIFICATION_UID, NOTIFICATION_HOME_RESOURCE_ID) -- implicit index
+);
+
+create index NOTIFICATION_NOTIFICATION_HOME_RESOURCE_ID on
+  NOTIFICATION(NOTIFICATION_HOME_RESOURCE_ID);
+
+-------------------
+-- Calendar Bind --
+-------------------
+
+-- Joins CALENDAR_HOME and CALENDAR
+
+create table CALENDAR_BIND (
+  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
+  CALENDAR_RESOURCE_ID      integer      not null references CALENDAR on delete cascade,
+  CALENDAR_RESOURCE_NAME    varchar(255) not null,
+  BIND_MODE                 integer      not null, -- enum CALENDAR_BIND_MODE
+  BIND_STATUS               integer      not null, -- enum CALENDAR_BIND_STATUS
+  MESSAGE                   text,
+
+  primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID), -- implicit index
+  unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME)     -- implicit index
+);
+
+create index CALENDAR_BIND_RESOURCE_ID on CALENDAR_BIND(CALENDAR_RESOURCE_ID);
+
+-- Enumeration of calendar bind modes
+
+create table CALENDAR_BIND_MODE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_BIND_MODE values (0, 'own'  );
+insert into CALENDAR_BIND_MODE values (1, 'read' );
+insert into CALENDAR_BIND_MODE values (2, 'write');
+insert into CALENDAR_BIND_MODE values (3, 'direct');
+
+-- Enumeration of statuses
+
+create table CALENDAR_BIND_STATUS (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_BIND_STATUS values (0, 'invited' );
+insert into CALENDAR_BIND_STATUS values (1, 'accepted');
+insert into CALENDAR_BIND_STATUS values (2, 'declined');
+insert into CALENDAR_BIND_STATUS values (3, 'invalid');
+
+
+---------------------
+-- Calendar Object --
+---------------------
+
+create table CALENDAR_OBJECT (
+  RESOURCE_ID          integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  CALENDAR_RESOURCE_ID integer      not null references CALENDAR on delete cascade,
+  RESOURCE_NAME        varchar(255) not null,
+  ICALENDAR_TEXT       text         not null,
+  ICALENDAR_UID        varchar(255) not null,
+  ICALENDAR_TYPE       varchar(255) not null,
+  ATTACHMENTS_MODE     integer      default 0 not null, -- enum CALENDAR_OBJECT_ATTACHMENTS_MODE
+  DROPBOX_ID           varchar(255),
+  ORGANIZER            varchar(255),
+  ORGANIZER_OBJECT     integer      references CALENDAR_OBJECT,
+  RECURRANCE_MIN       date,        -- minimum date that recurrences have been expanded to.
+  RECURRANCE_MAX       date,        -- maximum date that recurrences have been expanded to.
+  ACCESS               integer      default 0 not null,
+  SCHEDULE_OBJECT      boolean      default false,
+  SCHEDULE_TAG         varchar(36)  default null,
+  SCHEDULE_ETAGS       text         default null,
+  PRIVATE_COMMENTS     boolean      default false not null,
+  MD5                  char(32)     not null,
+  CREATED              timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED             timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+
+  unique (CALENDAR_RESOURCE_ID, RESOURCE_NAME) -- implicit index
+
+  -- since the 'inbox' is a 'calendar resource' for the purpose of storing
+  -- calendar objects, this constraint has to be selectively enforced by the
+  -- application layer.
+
+  -- unique(CALENDAR_RESOURCE_ID, ICALENDAR_UID)
+);
+
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_AND_ICALENDAR_UID on
+  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, ICALENDAR_UID);
+
+create index CALENDAR_OBJECT_CALENDAR_RESOURCE_ID_RECURRANCE_MAX on
+  CALENDAR_OBJECT(CALENDAR_RESOURCE_ID, RECURRANCE_MAX);
+
+create index CALENDAR_OBJECT_ORGANIZER_OBJECT on
+  CALENDAR_OBJECT(ORGANIZER_OBJECT);
+
+create index CALENDAR_OBJECT_DROPBOX_ID on
+  CALENDAR_OBJECT(DROPBOX_ID);
+
+-- Enumeration of attachment modes
+
+create table CALENDAR_OBJECT_ATTACHMENTS_MODE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (0, 'none' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (1, 'read' );
+insert into CALENDAR_OBJECT_ATTACHMENTS_MODE values (2, 'write');
+
+
+-- Enumeration of calendar access types
+
+create table CALENDAR_ACCESS_TYPE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(32) not null unique
+);
+
+insert into CALENDAR_ACCESS_TYPE values (0, ''             );
+insert into CALENDAR_ACCESS_TYPE values (1, 'public'       );
+insert into CALENDAR_ACCESS_TYPE values (2, 'private'      );
+insert into CALENDAR_ACCESS_TYPE values (3, 'confidential' );
+insert into CALENDAR_ACCESS_TYPE values (4, 'restricted'   );
+
+-----------------
+-- Instance ID --
+-----------------
+
+create sequence INSTANCE_ID_SEQ;
+
+
+----------------
+-- Time Range --
+----------------
+
+create table TIME_RANGE (
+  INSTANCE_ID                 integer        primary key default nextval('INSTANCE_ID_SEQ'), -- implicit index
+  CALENDAR_RESOURCE_ID        integer        not null references CALENDAR on delete cascade,
+  CALENDAR_OBJECT_RESOURCE_ID integer        not null references CALENDAR_OBJECT on delete cascade,
+  FLOATING                    boolean        not null,
+  START_DATE                  timestamp      not null,
+  END_DATE                    timestamp      not null,
+  FBTYPE                      integer        not null,
+  TRANSPARENT                 boolean        not null
+);
+
+create index TIME_RANGE_CALENDAR_RESOURCE_ID on
+  TIME_RANGE(CALENDAR_RESOURCE_ID);
+create index TIME_RANGE_CALENDAR_OBJECT_RESOURCE_ID on
+  TIME_RANGE(CALENDAR_OBJECT_RESOURCE_ID);
+
+
+-- Enumeration of free/busy types
+
+create table FREE_BUSY_TYPE (
+  ID          integer     primary key,
+  DESCRIPTION varchar(16) not null unique
+);
+
+insert into FREE_BUSY_TYPE values (0, 'unknown'         );
+insert into FREE_BUSY_TYPE values (1, 'free'            );
+insert into FREE_BUSY_TYPE values (2, 'busy'            );
+insert into FREE_BUSY_TYPE values (3, 'busy-unavailable');
+insert into FREE_BUSY_TYPE values (4, 'busy-tentative'  );
+
+
+------------------
+-- Transparency --
+------------------
+
+create table TRANSPARENCY (
+  TIME_RANGE_INSTANCE_ID      integer      not null references TIME_RANGE on delete cascade,
+  USER_ID                     varchar(255) not null,
+  TRANSPARENT                 boolean      not null
+);
+
+create index TRANSPARENCY_TIME_RANGE_INSTANCE_ID on
+  TRANSPARENCY(TIME_RANGE_INSTANCE_ID);
+
+
+----------------
+-- Attachment --
+----------------
+
+create sequence ATTACHMENT_ID_SEQ;
+
+create table ATTACHMENT (
+  ATTACHMENT_ID               integer           primary key default nextval('ATTACHMENT_ID_SEQ'), -- implicit index
+  CALENDAR_HOME_RESOURCE_ID   integer           not null references CALENDAR_HOME,
+  DROPBOX_ID                  varchar(255),
+  CONTENT_TYPE                varchar(255)      not null,
+  SIZE                        integer           not null,
+  MD5                         char(32)          not null,
+  CREATED                     timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                    timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  PATH                        varchar(1024)     not null
+);
+
+create index ATTACHMENT_CALENDAR_HOME_RESOURCE_ID on
+  ATTACHMENT(CALENDAR_HOME_RESOURCE_ID);
+
+-- Many-to-many relationship between attachments and calendar objects
+create table ATTACHMENT_CALENDAR_OBJECT (
+  ATTACHMENT_ID                  integer      not null references ATTACHMENT on delete cascade,
+  MANAGED_ID                     varchar(255) not null,
+  CALENDAR_OBJECT_RESOURCE_ID    integer      not null references CALENDAR_OBJECT on delete cascade,
+
+  primary key (ATTACHMENT_ID, CALENDAR_OBJECT_RESOURCE_ID), -- implicit index
+  unique (MANAGED_ID, CALENDAR_OBJECT_RESOURCE_ID) --implicit index
+);
+
+
+-----------------------
+-- Resource Property --
+-----------------------
+
+create table RESOURCE_PROPERTY (
+  RESOURCE_ID integer      not null, -- foreign key: *.RESOURCE_ID
+  NAME        varchar(255) not null,
+  VALUE       text         not null, -- FIXME: xml?
+  VIEWER_UID  varchar(255),
+
+  primary key (RESOURCE_ID, NAME, VIEWER_UID) -- implicit index
+);
+
+
+----------------------
+-- AddressBook Home --
+----------------------
+
+create table ADDRESSBOOK_HOME (
+  RESOURCE_ID      integer      primary key default nextval('RESOURCE_ID_SEQ'), -- implicit index
+  OWNER_UID        varchar(255) not null unique,                                -- implicit index
+  DATAVERSION      integer      default 0 not null
+);
+
+-------------------------------
+-- AddressBook Home Metadata --
+-------------------------------
+
+create table ADDRESSBOOK_HOME_METADATA (
+  RESOURCE_ID      integer      primary key references ADDRESSBOOK_HOME on delete cascade, -- implicit index
+  QUOTA_USED_BYTES integer      default 0 not null,
+  CREATED          timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED         timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+-----------------
+-- AddressBook --
+-----------------
+
+create table ADDRESSBOOK (
+  RESOURCE_ID integer   primary key default nextval('RESOURCE_ID_SEQ') -- implicit index
+);
+
+
+--------------------------
+-- AddressBook Metadata --
+--------------------------
+
+create table ADDRESSBOOK_METADATA (
+  RESOURCE_ID integer   primary key references ADDRESSBOOK on delete cascade, -- implicit index
+  CREATED     timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED    timestamp default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+
+----------------------
+-- AddressBook Bind --
+----------------------
+
+-- Joins ADDRESSBOOK_HOME and ADDRESSBOOK
+
+create table ADDRESSBOOK_BIND (
+  ADDRESSBOOK_HOME_RESOURCE_ID integer      not null references ADDRESSBOOK_HOME,
+  ADDRESSBOOK_RESOURCE_ID      integer      not null references ADDRESSBOOK on delete cascade,
+  ADDRESSBOOK_RESOURCE_NAME    varchar(255) not null,
+  BIND_MODE                    integer      not null, -- enum CALENDAR_BIND_MODE
+  BIND_STATUS                  integer      not null, -- enum CALENDAR_BIND_STATUS
+  MESSAGE                      text,                  -- FIXME: xml?
+
+  primary key (ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_ID), -- implicit index
+  unique (ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_NAME)     -- implicit index
+);
+
+create index ADDRESSBOOK_BIND_RESOURCE_ID on
+  ADDRESSBOOK_BIND(ADDRESSBOOK_RESOURCE_ID);
+
+create table ADDRESSBOOK_OBJECT (
+  RESOURCE_ID             integer      primary key default nextval('RESOURCE_ID_SEQ'),    -- implicit index
+  ADDRESSBOOK_RESOURCE_ID integer      not null references ADDRESSBOOK on delete cascade,
+  RESOURCE_NAME           varchar(255) not null,
+  VCARD_TEXT              text         not null,
+  VCARD_UID               varchar(255) not null,
+  MD5                     char(32)     not null,
+  CREATED                 timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  MODIFIED                timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+
+  unique (ADDRESSBOOK_RESOURCE_ID, RESOURCE_NAME), -- implicit index
+  unique (ADDRESSBOOK_RESOURCE_ID, VCARD_UID)      -- implicit index
+);
+
+---------------
+-- Revisions --
+---------------
+
+create sequence REVISION_SEQ;
+
+
+---------------
+-- Revisions --
+---------------
+
+create table CALENDAR_OBJECT_REVISIONS (
+  CALENDAR_HOME_RESOURCE_ID integer      not null references CALENDAR_HOME,
+  CALENDAR_RESOURCE_ID      integer      references CALENDAR,
+  CALENDAR_NAME             varchar(255) default null,
+  RESOURCE_NAME             varchar(255),
+  REVISION                  integer      default nextval('REVISION_SEQ') not null,
+  DELETED                   boolean      not null
+);
+
+create index CALENDAR_OBJECT_REVISIONS_HOME_RESOURCE_ID_CALENDAR_RESOURCE_ID
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID);
+
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, RESOURCE_NAME);
+
+create index CALENDAR_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+  on CALENDAR_OBJECT_REVISIONS(CALENDAR_RESOURCE_ID, REVISION);
+
+-------------------------------
+-- AddressBook Object Revisions --
+-------------------------------
+
+create table ADDRESSBOOK_OBJECT_REVISIONS (
+  ADDRESSBOOK_HOME_RESOURCE_ID integer      not null references ADDRESSBOOK_HOME,
+  ADDRESSBOOK_RESOURCE_ID      integer      references ADDRESSBOOK,
+  ADDRESSBOOK_NAME             varchar(255) default null,
+  RESOURCE_NAME                varchar(255),
+  REVISION                     integer      default nextval('REVISION_SEQ') not null,
+  DELETED                      boolean      not null
+);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_HOME_RESOURCE_ID_ADDRESSBOOK_RESOURCE_ID
+  on ADDRESSBOOK_OBJECT_REVISIONS(ADDRESSBOOK_HOME_RESOURCE_ID, ADDRESSBOOK_RESOURCE_ID);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_RESOURCE_ID_RESOURCE_NAME
+  on ADDRESSBOOK_OBJECT_REVISIONS(ADDRESSBOOK_RESOURCE_ID, RESOURCE_NAME);
+
+create index ADDRESSBOOK_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+  on ADDRESSBOOK_OBJECT_REVISIONS(ADDRESSBOOK_RESOURCE_ID, REVISION);
+
+-----------------------------------
+-- Notification Object Revisions --
+-----------------------------------
+
+create table NOTIFICATION_OBJECT_REVISIONS (
+  NOTIFICATION_HOME_RESOURCE_ID integer      not null references NOTIFICATION_HOME on delete cascade,
+  RESOURCE_NAME                 varchar(255),
+  REVISION                      integer      default nextval('REVISION_SEQ') not null,
+  DELETED                       boolean      not null,
+
+  unique(NOTIFICATION_HOME_RESOURCE_ID, RESOURCE_NAME) -- implicit index
+);
+
+create index NOTIFICATION_OBJECT_REVISIONS_RESOURCE_ID_REVISION
+  on NOTIFICATION_OBJECT_REVISIONS(NOTIFICATION_HOME_RESOURCE_ID, REVISION);
+
+-------------------------------------------
+-- Apple Push Notification Subscriptions --
+-------------------------------------------
+
+create table APN_SUBSCRIPTIONS (
+  TOKEN                         varchar(255) not null,
+  RESOURCE_KEY                  varchar(255) not null,
+  MODIFIED                      integer not null,
+  SUBSCRIBER_GUID               varchar(255) not null,
+  USER_AGENT                    varchar(255) default null,
+  IP_ADDR                       varchar(255) default null,
+
+  primary key (TOKEN, RESOURCE_KEY) -- implicit index
+);
+
+create index APN_SUBSCRIPTIONS_RESOURCE_KEY
+   on APN_SUBSCRIPTIONS(RESOURCE_KEY);
+
+-----------------
+-- IMIP Tokens --
+-----------------
+
+create table IMIP_TOKENS (
+  TOKEN                         varchar(255) not null,
+  ORGANIZER                     varchar(255) not null,
+  ATTENDEE                      varchar(255) not null,
+  ICALUID                       varchar(255) not null,
+  ACCESSED                      timestamp default timezone('UTC', CURRENT_TIMESTAMP),
+
+  primary key (ORGANIZER, ATTENDEE, ICALUID) -- implicit index
+);
+
+create index IMIP_TOKENS_TOKEN
+   on IMIP_TOKENS(TOKEN);
+
+----------------
+-- Work Items --
+----------------
+
+create sequence WORKITEM_SEQ;
+
+---------------------------
+-- IMIP Inivitation Work --
+---------------------------
+
+create table IMIP_INVITATION_WORK (
+  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  FROM_ADDR                     varchar(255) not null,
+  TO_ADDR                       varchar(255) not null,
+  ICALENDAR_TEXT                text         not null
+);
+
+-----------------------
+-- IMIP Polling Work --
+-----------------------
+
+create table IMIP_POLLING_WORK (
+  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
+);
+
+---------------------
+-- IMIP Reply Work --
+---------------------
+
+create table IMIP_REPLY_WORK (
+  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  ORGANIZER                     varchar(255) not null,
+  ATTENDEE                      varchar(255) not null,
+  ICALENDAR_TEXT                text         not null
+);
+
+------------------------
+-- Push Notifications --
+------------------------
+
+create table PUSH_NOTIFICATION_WORK (
+  WORK_ID                       integer primary key default nextval('WORKITEM_SEQ') not null,
+  NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP),
+  PUSH_ID                       varchar(255) not null
+);
+
+
+--------------------
+-- Schema Version --
+--------------------
+
+create table CALENDARSERVER (
+  NAME                          varchar(255) primary key, -- implicit index
+  VALUE                         varchar(255)
+);
+
+insert into CALENDARSERVER values ('VERSION', '16');
+insert into CALENDARSERVER values ('CALENDAR-DATAVERSION', '3');
+insert into CALENDARSERVER values ('ADDRESSBOOK-DATAVERSION', '1');

Copied: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_16_to_17.sql (from rev 10865, CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_16_to_17.sql)
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_16_to_17.sql	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_16_to_17.sql	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,35 @@
+----
+-- Copyright (c) 2011-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.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 16 to 17 --
+---------------------------------------------------
+
+
+------------------------------
+-- CALENDAR_OBJECT clean-up --
+------------------------------
+
+alter table CALENDAR_OBJECT
+ drop (ORGANIZER_OBJECT);
+
+create index CALENDAR_OBJECT_ICALE_82e731d5 on CALENDAR_OBJECT (
+    ICALENDAR_UID
+);
+
+
+-- Now update the version
+update CALENDARSERVER set VALUE = '17' where NAME = 'VERSION';

Copied: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_16_to_17.sql (from rev 10865, CalendarServer/trunk/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_16_to_17.sql)
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_16_to_17.sql	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_16_to_17.sql	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,34 @@
+----
+-- Copyright (c) 2011-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.
+----
+
+---------------------------------------------------
+-- Upgrade database schema from VERSION 16 to 17 --
+---------------------------------------------------
+
+
+------------------------------
+-- CALENDAR_OBJECT clean-up --
+------------------------------
+
+alter table CALENDAR_OBJECT
+ drop column ORGANIZER_OBJECT;
+
+create index CALENDAR_OBJECT_ICALENDAR_UID on
+  CALENDAR_OBJECT(ICALENDAR_UID);
+
+
+-- Now update the version
+update CALENDARSERVER set VALUE = '17' where NAME = 'VERSION';

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/test/util.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/test/util.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -14,44 +14,52 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+
 """
 Store test utility functions
 """
 
-import gc
+from __future__ import print_function
+
+from calendarserver.push.notifier import Notifier
+
 from hashlib import md5
+
+from pycalendar.datetime import PyCalendarDateTime
+
 from random import Random
-from zope.interface.verify import verifyObject
-from zope.interface.exceptions import BrokenMethodImplementation, \
-    DoesNotImplement
 
+from twext.enterprise.adbapi2 import ConnectionPool
+from twext.enterprise.ienterprise import AlreadyFinishedError
 from twext.python.filepath import CachingFilePath
 from twext.python.vcomponent import VComponent
 from twext.web2.dav.resource import TwistedGETContentMD5
 
+from twisted.application.service import Service
 from twisted.internet import reactor
 from twisted.internet.defer import Deferred, inlineCallbacks
+from twisted.internet.defer import returnValue
 from twisted.internet.task import deferLater
 from twisted.python import log
-from twisted.application.service import Service
+from twisted.trial.unittest import TestCase
 
 from twistedcaldav.config import config
+from twistedcaldav.stdconfig import DEFAULT_CONFIG
+from twistedcaldav.vcard import Component as ABComponent
 
-from txdav.common.datastore.sql import CommonDataStore, current_sql_schema
+from txdav.base.datastore.dbapiclient import DiagnosticConnectionWrapper
 from txdav.base.datastore.subpostgres import PostgresService
-from txdav.base.datastore.dbapiclient import DiagnosticConnectionWrapper
 from txdav.base.propertystore.base import PropertyName
+from txdav.common.datastore.sql import CommonDataStore, current_sql_schema
+from txdav.common.datastore.sql_tables import schema
 from txdav.common.icommondatastore import NoSuchHomeChildError
-from twext.enterprise.adbapi2 import ConnectionPool
-from twisted.trial.unittest import TestCase
-from twisted.internet.defer import returnValue
-from calendarserver.push.notifier import Notifier
-from twext.enterprise.ienterprise import AlreadyFinishedError
-from twistedcaldav.vcard import Component as ABComponent
 
-from pycalendar.datetime import PyCalendarDateTime
-from txdav.common.datastore.sql_tables import schema
+from zope.interface.exceptions import BrokenMethodImplementation, \
+    DoesNotImplement
+from zope.interface.verify import verifyObject
 
+import gc
+
 md5key = PropertyName.fromElement(TwistedGETContentMD5)
 
 def allInstancesOf(cls):
@@ -71,10 +79,10 @@
     between tests.  (It is currently not invoked anywhere, but may be useful if
     these types of bugs crop up in the future.)
     """
-    print '+++ ALL CONNECTIONS +++'
+    print("+++ ALL CONNECTIONS +++")
     for connection in allInstancesOf(DiagnosticConnectionWrapper):
-        print connection.label, connection.state
-    print '--- CONNECTIONS END ---'
+        print(connection.label, connection.state)
+    print("--- CONNECTIONS END ---")
 
 
 
@@ -646,7 +654,6 @@
 
 
 
-
 class StubNotifierFactory(object):
     """
     For testing push notifications without an XMPP server.
@@ -698,6 +705,8 @@
 
     from twistedcaldav.memcacher import Memcacher
 
+    if not hasattr(config, "Memcached"):
+        config.setDefaults(DEFAULT_CONFIG)
     aTest.patch(config.Memcached.Pools.Default, "ClientEnabled", False)
     aTest.patch(config.Memcached.Pools.Default, "ServerEnabled", False)
     aTest.patch(Memcacher, "allowTestCache", True)

Added: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/others/test/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/others/test/__init__.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/others/test/__init__.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,15 @@
+##
+# 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.
+##

Added: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/others/test/test_attachment_migration.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/others/test/test_attachment_migration.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/others/test/test_attachment_migration.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -0,0 +1,177 @@
+##
+# 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 twext.enterprise.dal.syntax import Delete
+
+from twisted.internet.defer import inlineCallbacks, succeed, returnValue
+from twisted.trial.unittest import TestCase
+
+from twistedcaldav.config import config
+
+from txdav.caldav.datastore.sql import CalendarStoreFeatures
+from txdav.common.datastore.sql_tables import schema
+from txdav.common.datastore.test.util import theStoreBuilder, \
+    StubNotifierFactory
+from txdav.common.datastore.upgrade.sql.others import attachment_migration
+from txdav.common.datastore.upgrade.sql.upgrade import UpgradeDatabaseOtherService
+
+"""
+Tests for L{txdav.common.datastore.upgrade.sql.upgrade}.
+"""
+
+
+class AttachmentMigrationTests(TestCase):
+    """
+    Tests for L{UpgradeDatabaseSchemaService}.
+    """
+
+    @inlineCallbacks
+    def _initStore(self, enableManagedAttachments=True):
+        """
+        Build a store with certain bits cleaned out.
+        """
+
+        self.patch(config, "EnableManagedAttachments", enableManagedAttachments)
+
+        store = yield theStoreBuilder.buildStore(
+            self, StubNotifierFactory()
+        )
+        store.enableManagedAttachments = enableManagedAttachments
+
+        txn = store.newTransaction()
+        cs = schema.CALENDARSERVER
+        yield Delete(
+            From=cs,
+            Where=cs.NAME == "MANAGED-ATTACHMENTS"
+        ).on(txn)
+        yield txn.commit()
+
+        returnValue(store)
+
+
+    @inlineCallbacks
+    def test_upgradeFromEmptyDropbox(self):
+        """
+        Test L{attachment_migration.doUpgrade} when managed attachments is enabled and dropbox items do not exist.
+        """
+
+        didUpgrade = [False, ]
+        def _hasDropboxAttachments(_self, txn):
+            return succeed(False)
+        self.patch(CalendarStoreFeatures, "hasDropboxAttachments", _hasDropboxAttachments)
+
+        def _upgradeToManagedAttachments(_self, batchSize=10):
+            didUpgrade[0] = True
+            return succeed(None)
+        self.patch(CalendarStoreFeatures, "upgradeToManagedAttachments", _upgradeToManagedAttachments)
+
+        store = (yield self._initStore())
+
+        upgrader = UpgradeDatabaseOtherService(store, None)
+        yield attachment_migration.doUpgrade(upgrader)
+        self.assertFalse(didUpgrade[0])
+
+        txn = upgrader.sqlStore.newTransaction()
+        managed = (yield txn.calendarserverValue("MANAGED-ATTACHMENTS", raiseIfMissing=False))
+        yield txn.commit()
+        self.assertNotEqual(managed, None)
+
+
+    @inlineCallbacks
+    def test_upgradeFromDropboxOK(self):
+        """
+        Test L{attachment_migration.doUpgrade} when managed attachments is enabled and dropbox items exist.
+        """
+
+        didUpgrade = [False, ]
+        def _hasDropboxAttachments(_self, txn):
+            return succeed(True)
+        self.patch(CalendarStoreFeatures, "hasDropboxAttachments", _hasDropboxAttachments)
+
+        def _upgradeToManagedAttachments(_self, batchSize=10):
+            didUpgrade[0] = True
+            return succeed(None)
+        self.patch(CalendarStoreFeatures, "upgradeToManagedAttachments", _upgradeToManagedAttachments)
+
+        store = (yield self._initStore())
+
+        upgrader = UpgradeDatabaseOtherService(store, None)
+        yield attachment_migration.doUpgrade(upgrader)
+        self.assertTrue(didUpgrade[0])
+
+        txn = upgrader.sqlStore.newTransaction()
+        managed = (yield txn.calendarserverValue("MANAGED-ATTACHMENTS", raiseIfMissing=False))
+        yield txn.commit()
+        self.assertNotEqual(managed, None)
+
+
+    @inlineCallbacks
+    def test_upgradeAlreadyDone(self):
+        """
+        Test L{attachment_migration.doUpgrade} when managed attachments is enabled and migration already done.
+        """
+
+        didUpgrade = [False, ]
+        def _hasDropboxAttachments(_self, txn):
+            return succeed(True)
+        self.patch(CalendarStoreFeatures, "hasDropboxAttachments", _hasDropboxAttachments)
+
+        def _upgradeToManagedAttachments(_self, batchSize=10):
+            didUpgrade[0] = True
+            return succeed(None)
+        self.patch(CalendarStoreFeatures, "upgradeToManagedAttachments", _upgradeToManagedAttachments)
+
+        store = (yield self._initStore())
+        txn = store.newTransaction()
+        yield txn.setCalendarserverValue("MANAGED-ATTACHMENTS", "1")
+        yield txn.commit()
+
+        upgrader = UpgradeDatabaseOtherService(store, None)
+        yield attachment_migration.doUpgrade(upgrader)
+        self.assertFalse(didUpgrade[0])
+
+        txn = upgrader.sqlStore.newTransaction()
+        managed = (yield txn.calendarserverValue("MANAGED-ATTACHMENTS", raiseIfMissing=False))
+        yield txn.commit()
+        self.assertNotEqual(managed, None)
+
+
+    @inlineCallbacks
+    def test_upgradeNotEnabled(self):
+        """
+        Test L{attachment_migration.doUpgrade} when managed attachments is disabled.
+        """
+
+        didUpgrade = [False, ]
+        def _hasDropboxAttachments(_self, txn):
+            return succeed(True)
+        self.patch(CalendarStoreFeatures, "hasDropboxAttachments", _hasDropboxAttachments)
+
+        def _upgradeToManagedAttachments(_self, batchSize=10):
+            didUpgrade[0] = True
+            return succeed(None)
+        self.patch(CalendarStoreFeatures, "upgradeToManagedAttachments", _upgradeToManagedAttachments)
+
+        store = (yield self._initStore(False))
+
+        upgrader = UpgradeDatabaseOtherService(store, None)
+        yield attachment_migration.doUpgrade(upgrader)
+        self.assertFalse(didUpgrade[0])
+
+        txn = upgrader.sqlStore.newTransaction()
+        managed = (yield txn.calendarserverValue("MANAGED-ATTACHMENTS", raiseIfMissing=False))
+        yield txn.commit()
+        self.assertEqual(managed, None)

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/test/test_upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/test/test_upgrade.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/test/test_upgrade.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -23,7 +23,7 @@
 from twisted.python.modules import getModule
 from twisted.trial.unittest import TestCase
 from txdav.common.datastore.test.util import theStoreBuilder, StubNotifierFactory
-from txdav.common.datastore.upgrade.sql.upgrade import UpgradeDatabaseSchemaService,\
+from txdav.common.datastore.upgrade.sql.upgrade import UpgradeDatabaseSchemaService, \
     UpgradeDatabaseDataService
 import re
 
@@ -42,19 +42,20 @@
                 return 1
         return int(found.group(2))
 
+
     def test_scanUpgradeFiles(self):
-        
+
         upgrader = UpgradeDatabaseSchemaService(None, None)
 
         upgrader.schemaLocation = getModule(__name__).filePath.sibling("fake_schema1")
         files = upgrader.scanForUpgradeFiles("fake_dialect")
-        self.assertEqual(files, 
+        self.assertEqual(files,
             [(3, 4, upgrader.schemaLocation.child("upgrades").child("fake_dialect").child("upgrade_from_3_to_4.sql"))],
         )
 
         upgrader.schemaLocation = getModule(__name__).filePath.sibling("fake_schema2")
         files = upgrader.scanForUpgradeFiles("fake_dialect")
-        self.assertEqual(files, 
+        self.assertEqual(files,
             [
                 (3, 4, upgrader.schemaLocation.child("upgrades").child("fake_dialect").child("upgrade_from_3_to_4.sql")),
                 (3, 5, upgrader.schemaLocation.child("upgrades").child("fake_dialect").child("upgrade_from_3_to_5.sql")),
@@ -62,14 +63,15 @@
             ]
         )
 
+
     def test_determineUpgradeSequence(self):
-        
+
         upgrader = UpgradeDatabaseSchemaService(None, None)
 
         upgrader.schemaLocation = getModule(__name__).filePath.sibling("fake_schema1")
         files = upgrader.scanForUpgradeFiles("fake_dialect")
         upgrades = upgrader.determineUpgradeSequence(3, 4, files, "fake_dialect")
-        self.assertEqual(upgrades, 
+        self.assertEqual(upgrades,
             [upgrader.schemaLocation.child("upgrades").child("fake_dialect").child("upgrade_from_3_to_4.sql")],
         )
         self.assertRaises(RuntimeError, upgrader.determineUpgradeSequence, 3, 5, files, "fake_dialect")
@@ -77,35 +79,36 @@
         upgrader.schemaLocation = getModule(__name__).filePath.sibling("fake_schema2")
         files = upgrader.scanForUpgradeFiles("fake_dialect")
         upgrades = upgrader.determineUpgradeSequence(3, 5, files, "fake_dialect")
-        self.assertEqual(upgrades, 
+        self.assertEqual(upgrades,
             [upgrader.schemaLocation.child("upgrades").child("fake_dialect").child("upgrade_from_3_to_5.sql")]
         )
         upgrades = upgrader.determineUpgradeSequence(4, 5, files, "fake_dialect")
-        self.assertEqual(upgrades, 
+        self.assertEqual(upgrades,
             [upgrader.schemaLocation.child("upgrades").child("fake_dialect").child("upgrade_from_4_to_5.sql")]
         )
 
         upgrader.schemaLocation = getModule(__name__).filePath.sibling("fake_schema3")
         files = upgrader.scanForUpgradeFiles("fake_dialect")
         upgrades = upgrader.determineUpgradeSequence(3, 5, files, "fake_dialect")
-        self.assertEqual(upgrades, 
+        self.assertEqual(upgrades,
             [
                 upgrader.schemaLocation.child("upgrades").child("fake_dialect").child("upgrade_from_3_to_4.sql"),
                 upgrader.schemaLocation.child("upgrades").child("fake_dialect").child("upgrade_from_4_to_5.sql"),
             ]
         )
 
+
     def test_upgradeAvailability(self):
         """
         Make sure that each old schema has a valid upgrade path to the current one.
         """
-        
+
         for dialect in (POSTGRES_DIALECT, ORACLE_DIALECT,):
             upgrader = UpgradeDatabaseSchemaService(None, None)
             files = upgrader.scanForUpgradeFiles(dialect)
 
             current_version = self._getSchemaVersion(upgrader.schemaLocation.child("current.sql"), "VERSION")
-            
+
             for child in upgrader.schemaLocation.child("old").child(dialect).globChildren("*.sql"):
                 old_version = self._getSchemaVersion(child, "VERSION")
                 upgrades = upgrader.determineUpgradeSequence(old_version, current_version, files, dialect)
@@ -115,7 +118,7 @@
 #        """
 #        Make sure that each upgrade file has a valid data upgrade file or None.
 #        """
-#        
+#
 #        for dialect in (POSTGRES_DIALECT, ORACLE_DIALECT,):
 #            upgrader = UpgradeDatabaseSchemaService(None, None)
 #            files = upgrader.scanForUpgradeFiles(dialect)
@@ -124,6 +127,7 @@
 #                if result is not None:
 #                    self.assertIsInstance(result, types.FunctionType)
 
+
     @inlineCallbacks
     def test_dbSchemaUpgrades(self):
         """
@@ -142,7 +146,7 @@
             Use the postgres schema mechanism to do tests under a separate "namespace"
             in postgres that we can quickly wipe clean afterwards.
             """
-            startTxn = store.newTransaction("test_dbUpgrades")        
+            startTxn = store.newTransaction("test_dbUpgrades")
             yield startTxn.execSQL("create schema test_dbUpgrades;")
             yield startTxn.execSQL("set search_path to test_dbUpgrades;")
             yield startTxn.execSQL(path.getContent())
@@ -150,21 +154,21 @@
 
         @inlineCallbacks
         def _loadVersion():
-            startTxn = store.newTransaction("test_dbUpgrades")        
+            startTxn = store.newTransaction("test_dbUpgrades")
             new_version = yield startTxn.execSQL("select value from calendarserver where name = 'VERSION';")
             yield startTxn.commit()
             returnValue(int(new_version[0][0]))
 
         @inlineCallbacks
         def _unloadOldSchema():
-            startTxn = store.newTransaction("test_dbUpgrades")        
+            startTxn = store.newTransaction("test_dbUpgrades")
             yield startTxn.execSQL("set search_path to public;")
             yield startTxn.execSQL("drop schema test_dbUpgrades cascade;")
             yield startTxn.commit()
 
         @inlineCallbacks
         def _cleanupOldSchema():
-            startTxn = store.newTransaction("test_dbUpgrades")        
+            startTxn = store.newTransaction("test_dbUpgrades")
             yield startTxn.execSQL("set search_path to public;")
             yield startTxn.execSQL("drop schema if exists test_dbUpgrades cascade;")
             yield startTxn.commit()
@@ -174,6 +178,8 @@
         test_upgrader = UpgradeDatabaseSchemaService(None, None)
         expected_version = self._getSchemaVersion(test_upgrader.schemaLocation.child("current.sql"), "VERSION")
         for child in test_upgrader.schemaLocation.child("old").child(POSTGRES_DIALECT).globChildren("*.sql"):
+
+            # Upgrade allowed
             upgrader = UpgradeDatabaseSchemaService(store, None)
             yield _loadOldSchema(child)
             yield upgrader.databaseUpgrade()
@@ -182,13 +188,31 @@
 
             self.assertEqual(new_version, expected_version)
 
+            # Upgrade disallowed
+            upgrader = UpgradeDatabaseSchemaService(store, None, failIfUpgradeNeeded=True, stopOnFail=False)
+            yield _loadOldSchema(child)
+            old_version = yield _loadVersion()
+            try:
+                yield upgrader.databaseUpgrade()
+            except RuntimeError:
+                pass
+            except Exception:
+                self.fail("RuntimeError not raised")
+            else:
+                self.fail("RuntimeError not raised")
+            new_version = yield _loadVersion()
+            yield _unloadOldSchema()
+
+            self.assertEqual(old_version, new_version)
+
+
     @inlineCallbacks
     def test_dbDataUpgrades(self):
         """
         This does a full DB test of all possible data upgrade paths. For each old schema, it loads it into the DB
         then runs the data upgrade service. This ensures all the upgrade_XX.py files work correctly - at least for
         postgres.
-        
+
         TODO: this currently does not create any calendar data to test with. It simply runs the upgrade on an empty
         store.
         """
@@ -203,7 +227,7 @@
             Use the postgres schema mechanism to do tests under a separate "namespace"
             in postgres that we can quickly wipe clean afterwards.
             """
-            startTxn = store.newTransaction("test_dbUpgrades")        
+            startTxn = store.newTransaction("test_dbUpgrades")
             yield startTxn.execSQL("create schema test_dbUpgrades;")
             yield startTxn.execSQL("set search_path to test_dbUpgrades;")
             yield startTxn.execSQL(path.getContent())
@@ -212,21 +236,21 @@
 
         @inlineCallbacks
         def _loadVersion():
-            startTxn = store.newTransaction("test_dbUpgrades")        
+            startTxn = store.newTransaction("test_dbUpgrades")
             new_version = yield startTxn.execSQL("select value from calendarserver where name = 'CALENDAR-DATAVERSION';")
             yield startTxn.commit()
             returnValue(int(new_version[0][0]))
 
         @inlineCallbacks
         def _unloadOldData():
-            startTxn = store.newTransaction("test_dbUpgrades")        
+            startTxn = store.newTransaction("test_dbUpgrades")
             yield startTxn.execSQL("set search_path to public;")
             yield startTxn.execSQL("drop schema test_dbUpgrades cascade;")
             yield startTxn.commit()
 
         @inlineCallbacks
         def _cleanupOldData():
-            startTxn = store.newTransaction("test_dbUpgrades")        
+            startTxn = store.newTransaction("test_dbUpgrades")
             yield startTxn.execSQL("set search_path to public;")
             yield startTxn.execSQL("drop schema if exists test_dbUpgrades cascade;")
             yield startTxn.commit()

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/upgrade.py	2013-03-07 21:36:39 UTC (rev 10866)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/sql/upgrade.py	2013-03-07 22:42:21 UTC (rev 10867)
@@ -52,7 +52,7 @@
     """
 
     @classmethod
-    def wrapService(cls, service, store, uid=None, gid=None):
+    def wrapService(cls, service, store, uid=None, gid=None, **kwargs):
         """
         Create an L{UpgradeDatabaseSchemaService} when starting the database
         so we can check the schema version and do any upgrades.
@@ -73,10 +73,10 @@
         @return: a service
         @rtype: L{IService}
         """
-        return cls(store, service, uid=uid, gid=gid,)
+        return cls(store, service, uid=uid, gid=gid, **kwargs)
 
 
-    def __init__(self, sqlStore, service, uid=None, gid=None):
+    def __init__(self, sqlStore, service, uid=None, gid=None, failIfUpgradeNeeded=False, stopOnFail=True):
         """
         Initialize the service.
         """
@@ -84,6 +84,8 @@
         self.sqlStore = sqlStore
         self.uid = uid
         self.gid = gid
+        self.failIfUpgradeNeeded = failIfUpgradeNeeded
+        self.stopOnFail = stopOnFail
         self.schemaLocation = getModule(__name__).filePath.parent().parent().sibling("sql_schema")
         self.pyLocation = getModule(__name__).filePath.parent()
 
@@ -118,6 +120,10 @@
             )
             self.log_error(msg)
             raise RuntimeError(msg)
+        elif self.failIfUpgradeNeeded:
+            if self.stopOnFail:
+                reactor.stop()
+            raise RuntimeError("Database upgrade is needed but not allowed.")
         else:
             self.sqlStore.setUpgrading(True)
             yield self.upgradeVersion(actual_version, required_version, dialect)
@@ -275,14 +281,14 @@
     @type wrappedService: L{IService} or C{NoneType}
     """
 
-    def __init__(self, sqlStore, service, uid=None, gid=None):
+    def __init__(self, sqlStore, service, **kwargs):
         """
         Initialize the service.
 
         @param sqlStore: The store to operate on. Can be C{None} when doing unit tests.
         @param service:  Wrapped service. Can be C{None} when doing unit tests.
         """
-        super(UpgradeDatabaseSchemaService, self).__init__(sqlStore, service, uid, gid)
+        super(UpgradeDatabaseSchemaService, self).__init__(sqlStore, service, **kwargs)
 
         self.versionKey = "VERSION"
         self.versionDescriptor = "schema"
@@ -328,14 +334,14 @@
     @type wrappedService: L{IService} or C{NoneType}
     """
 
-    def __init__(self, sqlStore, service, uid=None, gid=None):
+    def __init__(self, sqlStore, service, **kwargs):
         """
         Initialize the service.
 
         @param sqlStore: The store to operate on. Can be C{None} when doing unit tests.
         @param service:  Wrapped service. Can be C{None} when doing unit tests.
         """
-        super(UpgradeDatabaseDataService, self).__init__(sqlStore, service, uid, gid)
+        super(UpgradeDatabaseDataService, self).__init__(sqlStore, service, **kwargs)
 
         self.versionKey = "CALENDAR-DATAVERSION"
         self.versionDescriptor = "data"
@@ -380,14 +386,14 @@
     @type wrappedService: L{IService} or C{NoneType}
     """
 
-    def __init__(self, sqlStore, service, uid=None, gid=None):
+    def __init__(self, sqlStore, service, **kwargs):
         """
         Initialize the service.
 
         @param sqlStore: The store to operate on. Can be C{None} when doing unit tests.
         @param service:  Wrapped service. Can be C{None} when doing unit tests.
         """
-        super(UpgradeDatabaseOtherService, self).__init__(sqlStore, service, uid, gid)
+        super(UpgradeDatabaseOtherService, self).__init__(sqlStore, service, **kwargs)
 
         self.versionDescriptor = "other upgrades"
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130307/7bc9f484/attachment-0001.html>


More information about the calendarserver-changes mailing list