<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[14382] CalendarServer/branches/users/cdaboo/pod2pod-migration</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/14382">14382</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2015-02-06 11:17:54 -0800 (Fri, 06 Feb 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Merge from trunk.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationbin_buildsh">CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/_build.sh</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationbinpackage">CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/package</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationcalendarserverdashboard_servicepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/dashboard_service.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertapcaldavpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tap/caldav.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolsagentpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/agent.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolsdkimtoolpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/dkimtool.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolstesttest_calverifypy">CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/test/test_calverify.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationrequirementsdevtxt">CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-dev.txt</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationrequirementsstabletxt">CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-stable.txt</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationsupportApplemake">CalendarServer/branches/users/cdaboo/pod2pod-migration/support/Apple.make</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavresourcepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/resource.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavsharingpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/sharing.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavstdconfigpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/stdconfig.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavstorebridgepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/storebridge.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavtesttest_sharingpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/test/test_sharing.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavupgradepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/upgrade.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduledkimpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/dkim.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduleresourcepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/resource.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduletesttest_dkimpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingitippy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/itip.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingprocessingpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/processing.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingschedulerpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/scheduler.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingtesttest_itippy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/test/test_itip.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoresqlpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/sql.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoretesttest_sqlpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/test/test_sql.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxdavcommondatastoretestutilpy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/common/datastore/test/util.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigrationtxweb2davresourcepy">CalendarServer/branches/users/cdaboo/pod2pod-migration/txweb2/dav/resource.py</a></li>
</ul>
<h3>Property Changed</h3>
<ul>
<li><a href="#CalendarServerbranchesuserscdaboopod2podmigration">CalendarServer/branches/users/cdaboo/pod2pod-migration/</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserscdaboopod2podmigration"></a>
<div class="propset"><h4>Property changes: CalendarServer/branches/users/cdaboo/pod2pod-migration</h4>
<pre class="diff"><span>
</span></pre></div>
<a id="svnmergeinfo"></a>
<div class="modfile"><h4>Modified: svn:mergeinfo</h4></div>
<span class="cx">/CalendarServer/branches/config-separation:4379-4443
</span><span class="cx">/CalendarServer/branches/egg-info-351:4589-4625
</span><span class="cx">/CalendarServer/branches/generic-sqlstore:6167-6191
</span><span class="cx">/CalendarServer/branches/new-store:5594-5934
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile:5911-5935
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-5.2-dev:11972,12357-12358,12794,12814
</span><span class="cx">/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
</span><span class="cx">/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
</span><span class="cx">/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
</span><span class="cx">/CalendarServer/branches/users/cdaboo/cross-pod-sharing:12038-12191
</span><span class="cx">/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
</span><span class="cx">/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
</span><span class="cx">/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
</span><span class="cx">/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
</span><span class="cx">/CalendarServer/branches/users/cdaboo/json:11622-11912
</span><span class="cx">/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
</span><span class="cx">/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
</span><span class="cx">/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
</span><span class="cx">/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pods:7297-7377
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycard:7227-7237
</span><span class="cx">/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
</span><span class="cx">/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
</span><span class="cx">/CalendarServer/branches/users/cdaboo/reverse-proxy-pods:11875-11900
</span><span class="cx">/CalendarServer/branches/users/cdaboo/scheduling-queue-refresh:11783-12557
</span><span class="cx">/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
</span><span class="cx">/CalendarServer/branches/users/cdaboo/sharing-in-the-store:11935-12016
</span><span class="cx">/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
</span><span class="cx">/CalendarServer/branches/users/cdaboo/timezones:7443-7699
</span><span class="cx">/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
</span><span class="cx">/CalendarServer/branches/users/gaya/cleanrevisions:12152-12334
</span><span class="cx">/CalendarServer/branches/users/gaya/groupsharee2:13669-13773
</span><span class="cx">/CalendarServer/branches/users/gaya/sharedgroupfixes:12120-12142
</span><span class="cx">/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
</span><span class="cx">/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
</span><span class="cx">/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
</span><span class="cx">/CalendarServer/branches/users/glyph/conn-limit:6574-6577
</span><span class="cx">/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
</span><span class="cx">/CalendarServer/branches/users/glyph/dalify:6932-7023
</span><span class="cx">/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
</span><span class="cx">/CalendarServer/branches/users/glyph/deploybuild:7563-7572
</span><span class="cx">/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
</span><span class="cx">/CalendarServer/branches/users/glyph/disable-quota:7718-7727
</span><span class="cx">/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
</span><span class="cx">/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
</span><span class="cx">/CalendarServer/branches/users/glyph/hang-fix:11465-11491
</span><span class="cx">/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
</span><span class="cx">/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
</span><span class="cx">/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
</span><span class="cx">/CalendarServer/branches/users/glyph/linux-tests:6893-6900
</span><span class="cx">/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
</span><span class="cx">/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
</span><span class="cx">/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
</span><span class="cx">/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
</span><span class="cx">/CalendarServer/branches/users/glyph/new-export:7444-7485
</span><span class="cx">/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle:7106-7155
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
</span><span class="cx">/CalendarServer/branches/users/glyph/other-html:8062-8091
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
</span><span class="cx">/CalendarServer/branches/users/glyph/q:9560-9688
</span><span class="cx">/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
</span><span class="cx">/CalendarServer/branches/users/glyph/quota:7604-7637
</span><span class="cx">/CalendarServer/branches/users/glyph/sendfdport:5388-5424
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
</span><span class="cx">/CalendarServer/branches/users/glyph/sharedpool:6490-6550
</span><span class="cx">/CalendarServer/branches/users/glyph/sharing-api:9192-9205
</span><span class="cx">/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
</span><span class="cx">/CalendarServer/branches/users/glyph/sql-store:5929-6073
</span><span class="cx">/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
</span><span class="cx">/CalendarServer/branches/users/glyph/subtransactions:7248-7258
</span><span class="cx">/CalendarServer/branches/users/glyph/table-alias:8651-8664
</span><span class="cx">/CalendarServer/branches/users/glyph/uidexport:7673-7676
</span><span class="cx">/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
</span><span class="cx">/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
</span><span class="cx">/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
</span><span class="cx">/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
</span><span class="cx">/CalendarServer/branches/users/glyph/whenNotProposed:11881-11897
</span><span class="cx">/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
</span><span class="cx">/CalendarServer/branches/users/sagen/applepush:8126-8184
</span><span class="cx">/CalendarServer/branches/users/sagen/inboxitems:7380-7381
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources:5032-5051
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who:12819-12860
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-2:12861-12898
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-3:12899-12913
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-4:12914-13157
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-5:13158-13163
</span><span class="cx">/CalendarServer/branches/users/sagen/newcua:13309-13327
</span><span class="cx">/CalendarServer/branches/users/sagen/newcua-1:13328-13330
</span><span class="cx">/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
</span><span class="cx">/CalendarServer/branches/users/sagen/recordtypes:13648-13656
</span><span class="cx">/CalendarServer/branches/users/sagen/recordtypes-2:13657
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
</span><span class="cx">/CalendarServer/branches/users/sagen/resources-2:5084-5093
</span><span class="cx">/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
</span><span class="cx">/CalendarServer/branches/users/wsanchez/transations:5515-5593
</span><span class="cx"> + /CalDAVTester/trunk:11193-11198
</span><span class="cx">/CalendarServer/branches/config-separation:4379-4443
</span><span class="cx">/CalendarServer/branches/egg-info-351:4589-4625
</span><span class="cx">/CalendarServer/branches/generic-sqlstore:6167-6191
</span><span class="cx">/CalendarServer/branches/new-store:5594-5934
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile:5911-5935
</span><span class="cx">/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-5.1-dev:11846
</span><span class="cx">/CalendarServer/branches/release/CalendarServer-5.2-dev:11972,12357-12358,12794,12814
</span><span class="cx">/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
</span><span class="cx">/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
</span><span class="cx">/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
</span><span class="cx">/CalendarServer/branches/users/cdaboo/cross-pod-sharing:12038-12191
</span><span class="cx">/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
</span><span class="cx">/CalendarServer/branches/users/cdaboo/fix-no-ischedule:11607-11871
</span><span class="cx">/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
</span><span class="cx">/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
</span><span class="cx">/CalendarServer/branches/users/cdaboo/json:11622-11912
</span><span class="cx">/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
</span><span class="cx">/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
</span><span class="cx">/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
</span><span class="cx">/CalendarServer/branches/users/cdaboo/performance-tweaks:11824-11836
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pods:7297-7377
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
</span><span class="cx">/CalendarServer/branches/users/cdaboo/pycard:7227-7237
</span><span class="cx">/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
</span><span class="cx">/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
</span><span class="cx">/CalendarServer/branches/users/cdaboo/reverse-proxy-pods:11875-11900
</span><span class="cx">/CalendarServer/branches/users/cdaboo/scheduling-queue-refresh:11783-12557
</span><span class="cx">/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
</span><span class="cx">/CalendarServer/branches/users/cdaboo/sharing-in-the-store:11935-12016
</span><span class="cx">/CalendarServer/branches/users/cdaboo/store-scheduling:10876-11129
</span><span class="cx">/CalendarServer/branches/users/cdaboo/timezones:7443-7699
</span><span class="cx">/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
</span><span class="cx">/CalendarServer/branches/users/gaya/cleanrevisions:12152-12334
</span><span class="cx">/CalendarServer/branches/users/gaya/groupsharee2:13669-13773
</span><span class="cx">/CalendarServer/branches/users/gaya/sharedgroupfixes:12120-12142
</span><span class="cx">/CalendarServer/branches/users/gaya/sharedgroups-3:11088-11204
</span><span class="cx">/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
</span><span class="cx">/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
</span><span class="cx">/CalendarServer/branches/users/glyph/conn-limit:6574-6577
</span><span class="cx">/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
</span><span class="cx">/CalendarServer/branches/users/glyph/dalify:6932-7023
</span><span class="cx">/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
</span><span class="cx">/CalendarServer/branches/users/glyph/deploybuild:7563-7572
</span><span class="cx">/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
</span><span class="cx">/CalendarServer/branches/users/glyph/disable-quota:7718-7727
</span><span class="cx">/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
</span><span class="cx">/CalendarServer/branches/users/glyph/enforce-max-requests:11640-11643
</span><span class="cx">/CalendarServer/branches/users/glyph/hang-fix:11465-11491
</span><span class="cx">/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
</span><span class="cx">/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
</span><span class="cx">/CalendarServer/branches/users/glyph/launchd-wrapper-bis:11413-11436
</span><span class="cx">/CalendarServer/branches/users/glyph/linux-tests:6893-6900
</span><span class="cx">/CalendarServer/branches/users/glyph/log-cleanups:11691-11731
</span><span class="cx">/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
</span><span class="cx">/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
</span><span class="cx">/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
</span><span class="cx">/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
</span><span class="cx">/CalendarServer/branches/users/glyph/new-export:7444-7485
</span><span class="cx">/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle:7106-7155
</span><span class="cx">/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
</span><span class="cx">/CalendarServer/branches/users/glyph/other-html:8062-8091
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
</span><span class="cx">/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
</span><span class="cx">/CalendarServer/branches/users/glyph/q:9560-9688
</span><span class="cx">/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
</span><span class="cx">/CalendarServer/branches/users/glyph/quota:7604-7637
</span><span class="cx">/CalendarServer/branches/users/glyph/sendfdport:5388-5424
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
</span><span class="cx">/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
</span><span class="cx">/CalendarServer/branches/users/glyph/sharedpool:6490-6550
</span><span class="cx">/CalendarServer/branches/users/glyph/sharing-api:9192-9205
</span><span class="cx">/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
</span><span class="cx">/CalendarServer/branches/users/glyph/sql-store:5929-6073
</span><span class="cx">/CalendarServer/branches/users/glyph/start-service-start-loop:11060-11065
</span><span class="cx">/CalendarServer/branches/users/glyph/subtransactions:7248-7258
</span><span class="cx">/CalendarServer/branches/users/glyph/table-alias:8651-8664
</span><span class="cx">/CalendarServer/branches/users/glyph/uidexport:7673-7676
</span><span class="cx">/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
</span><span class="cx">/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
</span><span class="cx">/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
</span><span class="cx">/CalendarServer/branches/users/glyph/warning-cleanups:11347-11357
</span><span class="cx">/CalendarServer/branches/users/glyph/whenNotProposed:11881-11897
</span><span class="cx">/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
</span><span class="cx">/CalendarServer/branches/users/sagen/applepush:8126-8184
</span><span class="cx">/CalendarServer/branches/users/sagen/inboxitems:7380-7381
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources:5032-5051
</span><span class="cx">/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who:12819-12860
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-2:12861-12898
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-3:12899-12913
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-4:12914-13157
</span><span class="cx">/CalendarServer/branches/users/sagen/move2who-5:13158-13163
</span><span class="cx">/CalendarServer/branches/users/sagen/newcua:13309-13327
</span><span class="cx">/CalendarServer/branches/users/sagen/newcua-1:13328-13330
</span><span class="cx">/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
</span><span class="cx">/CalendarServer/branches/users/sagen/recordtypes:13648-13656
</span><span class="cx">/CalendarServer/branches/users/sagen/recordtypes-2:13657
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
</span><span class="cx">/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
</span><span class="cx">/CalendarServer/branches/users/sagen/resources-2:5084-5093
</span><span class="cx">/CalendarServer/branches/users/sagen/testing:10827-10851,10853-10855
</span><span class="cx">/CalendarServer/branches/users/wsanchez/transations:5515-5593
</span><span class="cx">/CalendarServer/trunk:14338-14381
</span><a id="CalendarServerbranchesuserscdaboopod2podmigrationbin_buildsh"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/_build.sh (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/_build.sh        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/_build.sh        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -516,7 +516,7 @@
</span><span class="cx"> local p="${n}-${v}";
</span><span class="cx">
</span><span class="cx"> c_dependency -m "a7f4e5e559a0e37b3ffc438c9456e425" \
</span><del>- "Cyrus SASL" "${p}" \
</del><ins>+ "CyrusSASL" "${p}" \
</ins><span class="cx"> "ftp://ftp.cyrusimap.org/cyrus-sasl/${p}.tar.gz" \
</span><span class="cx"> --disable-macos-framework;
</span><span class="cx"> fi;
</span><span class="lines">@@ -640,9 +640,9 @@
</span><span class="cx"> mkdir -p "${py_ve_tools}/junk";
</span><span class="cx">
</span><span class="cx"> for pkg in \
</span><del>- setuptools-5.4.1 \
- pip-6.0.6 \
- virtualenv-1.11.6 \
</del><ins>+ setuptools-12.0.5 \
+ pip-6.0.8 \
+ virtualenv-12.0.7 \
</ins><span class="cx"> ; do
</span><span class="cx"> local name="${pkg%-*}";
</span><span class="cx"> local version="${pkg#*-}";
</span><span class="lines">@@ -695,7 +695,6 @@
</span><span class="cx"> pip_download_and_install () {
</span><span class="cx"> "${python}" -m pip install \
</span><span class="cx"> --pre --allow-all-external \
</span><del>- --download-cache="${dev_home}/pip_cache" \
</del><span class="cx"> --log-file="${dev_home}/pip.log" \
</span><span class="cx"> "$@";
</span><span class="cx"> }
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationbinpackage"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/package (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/package        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/bin/package        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> parse_options () {
</span><del>- OPTIND=1;
</del><ins>+ local OPTIND=1;
</ins><span class="cx"> while getopts "hFfn" option; do
</span><span class="cx"> case "${option}" in
</span><span class="cx"> '?') usage; ;;
</span><span class="lines">@@ -93,37 +93,35 @@
</span><span class="cx">
</span><span class="cx"> parse_options "$@";
</span><span class="cx">
</span><del>- # Build the product
</del><ins>+ #
+ # Build everything
+ #
</ins><span class="cx">
</span><span class="cx"> if "${clean}"; then
</span><span class="cx"> develop_clean;
</span><span class="cx"> fi;
</span><span class="cx">
</span><del>- develop;
-
</del><span class="cx"> install -d "${destination}";
</span><ins>+ local destination="$(cd "${destination}" && pwd)";
</ins><span class="cx">
</span><del>- install -d "${destination}/virtualenv";
- cp -pR "${py_virtualenv}/" "${destination}/virtualenv";
</del><ins>+ init_build;
</ins><span class="cx">
</span><del>- # Make the python virtualenv relocatable
- "${bootstrap_python}" -m virtualenv --relocatable "${destination}/virtualenv";
</del><ins>+ dev_roots="${destination}/roots";
+ py_virtualenv="${destination}/virtualenv";
+ py_bindir="${py_virtualenv}/bin";
</ins><span class="cx">
</span><del>- cp -pR "${dev_roots}"/*/ "${destination}/virtualenv/";
</del><ins>+ c_dependencies;
+ py_dependencies;
</ins><span class="cx">
</span><span class="cx"> install -d "${destination}/bin";
</span><del>- install -m 555 "${wd}/support/_run_from_ve" "${destination}/bin";
- ln -fsv _run_from_ve "${destination}/bin/caldavd";
</del><span class="cx">
</span><del>- for script in $(
- python -c 'import setup; print "\n".join("calendarserver_{}".format(n) for n in setup.script_entry_points.keys())';
- ); do
- ln -fsv _run_from_ve "${destination}/bin/${script}";
- done;
</del><ins>+ (
+ cd "${destination}/bin" && \
+ find ../virtualenv/bin \
+ '(' -name 'caldavd' -o -name 'calendarserver_*' -o -name 'python' ')' \
+ -exec ln -fs '{}' . ';';
+ );
</ins><span class="cx">
</span><del>- # More here...
- # Looks like we need to install calendarserver.
- # Maybe should rebuild virtualenv insted of copying it.
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationcalendarserverdashboard_servicepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/dashboard_service.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/dashboard_service.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/dashboard_service.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -151,9 +151,9 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> if self.factory.store:
</span><del>- queuer = self.factory.store.queuer
- loads = queuer.workerPool.eachWorkerLoad()
- level = queuer.workerPool.loadLevel()
</del><ins>+ pool = self.factory.store.pool
+ loads = pool.workerPool.eachWorkerLoad()
+ level = pool.workerPool.loadLevel()
</ins><span class="cx"> else:
</span><span class="cx"> loads = []
</span><span class="cx"> level = 0
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertapcaldavpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tap/caldav.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tap/caldav.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tap/caldav.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -193,7 +193,9 @@
</span><span class="cx"> "PATH",
</span><span class="cx"> "PYTHONPATH",
</span><span class="cx"> "LD_LIBRARY_PATH",
</span><ins>+ "LD_PRELOAD",
</ins><span class="cx"> "DYLD_LIBRARY_PATH",
</span><ins>+ "DYLD_INSERT_LIBRARIES",
</ins><span class="cx"> ]
</span><span class="cx">
</span><span class="cx"> optionalVars = [
</span><span class="lines">@@ -1262,6 +1264,7 @@
</span><span class="cx"> )
</span><span class="cx"> self._initJobQueue(pool)
</span><span class="cx"> store.queuer = store.queuer.transferProposalCallbacks(pool)
</span><ins>+ store.pool = pool
</ins><span class="cx"> pool.setServiceParent(result)
</span><span class="cx">
</span><span class="cx"> # Optionally set up mail retrieval
</span><span class="lines">@@ -1856,6 +1859,7 @@
</span><span class="cx">
</span><span class="cx"> # The master should not perform queued work
</span><span class="cx"> store.queuer = NonPerformingQueuer()
</span><ins>+ store.pool = pool
</ins><span class="cx">
</span><span class="cx"> controlSocket.addFactory(
</span><span class="cx"> _QUEUE_ROUTE, pool.workerListenerFactory()
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolsagentpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/agent.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/agent.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/agent.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -34,7 +34,7 @@
</span><span class="cx"> from plistlib import readPlistFromString, writePlistToString
</span><span class="cx"> import socket
</span><span class="cx">
</span><del>-from twext.python.launchd import getLaunchDSocketFDs
</del><ins>+from twext.python.launchd import launchActivateSocket
</ins><span class="cx"> from twext.python.log import Logger
</span><span class="cx"> from twext.who.checker import HTTPDigestCredentialChecker
</span><span class="cx"> from twext.who.opendirectory import (
</span><span class="lines">@@ -153,8 +153,8 @@
</span><span class="cx"> """
</span><span class="cx"> from twisted.internet import reactor
</span><span class="cx">
</span><del>- sockets = getLaunchDSocketFDs()
- fd = sockets["AgentSocket"][0]
</del><ins>+ sockets = launchActivateSocket("AgentSocket")
+ fd = sockets[0]
</ins><span class="cx">
</span><span class="cx"> family = socket.AF_INET
</span><span class="cx"> endpoint = AdoptedStreamServerEndpoint(reactor, fd, family)
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolsdkimtoolpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/dkimtool.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/dkimtool.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/dkimtool.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -15,6 +15,7 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx">
</span><ins>+import os
</ins><span class="cx"> import sys
</span><span class="cx"> from Crypto.PublicKey import RSA
</span><span class="cx"> from StringIO import StringIO
</span><span class="lines">@@ -24,9 +25,7 @@
</span><span class="cx"> from twisted.python.usage import Options
</span><span class="cx">
</span><span class="cx"> from twext.python.log import Logger, LogLevel, StandardIOObserver
</span><del>-from txweb2.client.http import ClientRequest
</del><span class="cx"> from txweb2.http_headers import Headers
</span><del>-from txweb2.stream import MemoryStream
</del><span class="cx">
</span><span class="cx"> from txdav.caldav.datastore.scheduling.ischedule.dkim import RSA256, DKIMRequest, \
</span><span class="cx"> PublicKeyLookup, DKIMVerifier, DKIMVerificationError
</span><span class="lines">@@ -114,19 +113,17 @@
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def _doVerify(options):
</span><span class="cx"> # Parse the HTTP file
</span><del>- verify = open(options["verify"]).read()
- method, uri, headers, stream = _parseRequest(verify)
</del><ins>+ verify = open(os.path.expanduser(options["verify"])).read()
+ _method, _uri, headers, body = _parseRequest(verify)
</ins><span class="cx">
</span><del>- request = ClientRequest(method, uri, headers, stream)
-
</del><span class="cx"> # Check for local public key
</span><span class="cx"> if options["pub-key"]:
</span><del>- PublicKeyLookup_File.pubkeyfile = options["pub-key"]
</del><ins>+ PublicKeyLookup_File.pubkeyfile = os.path.expanduser(options["pub-key"])
</ins><span class="cx"> lookup = (PublicKeyLookup_File,)
</span><span class="cx"> else:
</span><span class="cx"> lookup = None
</span><span class="cx">
</span><del>- dkim = DKIMVerifier(request, lookup)
</del><ins>+ dkim = DKIMVerifier(headers, body, lookup)
</ins><span class="cx"> if options["fake-time"]:
</span><span class="cx"> dkim.time = 0
</span><span class="cx">
</span><span class="lines">@@ -162,7 +159,7 @@
</span><span class="cx"> name, value = hdr.split(':', 1)
</span><span class="cx"> headers.addRawHeader(name, value.strip())
</span><span class="cx">
</span><del>- stream = MemoryStream("".join(body))
</del><ins>+ stream = "".join(body)
</ins><span class="cx">
</span><span class="cx"> return method, uri, headers, stream
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationcalendarservertoolstesttest_calverifypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/test/test_calverify.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/test/test_calverify.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/calendarserver/tools/test/test_calverify.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -2507,8 +2507,8 @@
</span><span class="cx"> UID:INVITE_VALID_ORGANIZER_ICS
</span><span class="cx"> DTSTART:%(now)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> SUMMARY:INVITE_VALID_ORGANIZER_ICS
</span><span class="lines">@@ -2524,8 +2524,8 @@
</span><span class="cx"> UID:INVITE_VALID_ORGANIZER_ICS
</span><span class="cx"> DTSTART:%(now)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> SUMMARY:INVITE_VALID_ORGANIZER_ICS
</span><span class="lines">@@ -2541,8 +2541,8 @@
</span><span class="cx"> UID:INVITE_VALID_ORGANIZER_ICS
</span><span class="cx"> DTSTART:%(now_fwd11)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="lines">@@ -2560,8 +2560,8 @@
</span><span class="cx"> UID:INVITE_VALID_ORGANIZER_ICS
</span><span class="cx"> DTSTART:%(now_fwd11)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="lines">@@ -2579,8 +2579,8 @@
</span><span class="cx"> UID:%(uid)s
</span><span class="cx"> DTSTART:%(now)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
</span><span class="cx"> RRULE:FREQ=DAILY;UNTIL=%(now_fwd11_1)s
</span><span class="lines">@@ -2598,8 +2598,8 @@
</span><span class="cx"> UID:%(uid)s
</span><span class="cx"> DTSTART:%(now)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:%(relID)s
</span><span class="cx"> RRULE:FREQ=DAILY;UNTIL=%(now_fwd11_1)s
</span><span class="lines">@@ -2617,8 +2617,8 @@
</span><span class="cx"> UID:VALID_ORGANIZER_OVERRIDE_ICS
</span><span class="cx"> DTSTART:%(now)s
</span><span class="cx"> DURATION:PT1H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> SUMMARY:INVITE_VALID_ORGANIZER_ICS
</span><span class="lines">@@ -2628,8 +2628,8 @@
</span><span class="cx"> RECURRENCE-ID:%(now_fwd11)s
</span><span class="cx"> DTSTART:%(now_fwd11)s
</span><span class="cx"> DURATION:PT2H
</span><del>-ATTENDEE:urn:x-uid:%(uuid1)s
-ATTENDEE:urn:x-uid:%(uuid2)s
</del><ins>+ATTENDEE;PARTSTAT=ACCPETED:urn:x-uid:%(uuid1)s
+ATTENDEE;RSVP=TRUE:urn:x-uid:%(uuid2)s
</ins><span class="cx"> ORGANIZER:urn:x-uid:%(uuid1)s
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> SUMMARY:INVITE_VALID_ORGANIZER_ICS
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationrequirementsdevtxt"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-dev.txt (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-dev.txt        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-dev.txt        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -8,4 +8,4 @@
</span><span class="cx"> q
</span><span class="cx"> tl.eggdeps
</span><span class="cx"> --editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVClientLibrary/trunk@13420#egg=CalDAVClientLibrary
</span><del>---editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVTester/trunk@14306#egg=CalDAVTester
</del><ins>+--editable svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVTester/trunk@14377#egg=CalDAVTester
</ins></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationrequirementsstabletxt"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-stable.txt (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-stable.txt        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/requirements-stable.txt        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -20,7 +20,7 @@
</span><span class="cx">
</span><span class="cx"> --editable . # calendarserver
</span><span class="cx">
</span><del>- zope.interface==4.1.1
</del><ins>+ zope.interface==4.1.2
</ins><span class="cx">
</span><span class="cx"> Twisted==14.0.2
</span><span class="cx"> #zope.interface
</span><span class="lines">@@ -30,19 +30,19 @@
</span><span class="cx"> # added to calendarserver.
</span><span class="cx"> #pyOpenSSL
</span><span class="cx"> service_identity==14.0.0
</span><del>- characteristic==14.0.0
</del><ins>+ characteristic==14.3.0
</ins><span class="cx"> pyasn1==0.1.7
</span><span class="cx"> pyasn1-modules==0.0.5
</span><span class="cx"> #pyOpenSSL
</span><span class="cx"> pycrypto==2.6.1
</span><span class="cx">
</span><del>- --editable svn+http://svn.calendarserver.org/repository/calendarserver/twext/trunk@14327#egg=twextpy
</del><ins>+ --editable svn+http://svn.calendarserver.org/repository/calendarserver/twext/trunk@14351#egg=twextpy
</ins><span class="cx"> cffi==0.8.6
</span><span class="cx"> pycparser==2.10
</span><span class="cx"> #twisted
</span><span class="cx">
</span><span class="cx"> # [LDAP] extra
</span><del>- python-ldap==2.4.18
</del><ins>+ python-ldap==2.4.19
</ins><span class="cx"> #setuptools
</span><span class="cx">
</span><span class="cx"> # [DAL] extra
</span><span class="lines">@@ -55,14 +55,14 @@
</span><span class="cx"> PyGreSQL==4.1.1
</span><span class="cx">
</span><span class="cx"> # [Oracle] extra
</span><del>- #cx_Oracle # Not in PyPI
</del><ins>+ #cx_Oracle==5.1.3 # Not in PyPI
</ins><span class="cx">
</span><span class="cx"> pyOpenSSL==0.14
</span><del>- cryptography==0.7.1
</del><ins>+ cryptography==0.7.2
</ins><span class="cx"> #pyasn1
</span><span class="cx"> #cffi
</span><span class="cx"> enum34==1.0.4
</span><del>- setuptools==11.3.1
</del><ins>+ setuptools==12.0.5
</ins><span class="cx"> #six
</span><span class="cx"> six==1.9.0
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationsupportApplemake"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/support/Apple.make (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/support/Apple.make        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/support/Apple.make        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx">         @# Use --system-site-packages so that we use the packages provided by the
</span><span class="cx">         @# OS, such as PyObjC.
</span><span class="cx">         @# Use --always-copy because we want copies of, not links to, the system
</span><del>-        @# python, as Server.app is an indenpendant product train.
</del><ins>+        @# python, as Server.app is an independent product train.
</ins><span class="cx">         @#
</span><span class="cx">         @echo "Creating virtual environment...";
</span><span class="cx">         $(_v) $(RMDIR) "$(DSTROOT)$(CS_VIRTUALENV)";
</span><span class="lines">@@ -138,19 +138,6 @@
</span><span class="cx">         @echo "Putting comments into empty files...";
</span><span class="cx">         $(_v) find "$(DSTROOT)$(CS_VIRTUALENV)" -type f -size 0 -name "*.py" -exec sh -c 'printf "# empty\n" > {}' ";";
</span><span class="cx">         $(_v) find "$(DSTROOT)$(CS_VIRTUALENV)" -type f -size 0 -name "*.h" -exec sh -c 'printf "/* empty */\n" > {}' ";";
</span><del>-        @# This is obsoleted by using --always-copy when we create the virtualenv:
-        @# @echo "Replacing symbolic links...";
-        @# $(_v) find "$(DSTROOT)$(CS_VIRTUALENV)" -type l | \
-        @# while read link; do \
-        @# target="$$(readlink "$${link}")"; \
-        @# if [ "$$(echo $${target} | cut -f 1 -d /)" == "" ]; then \
-        @# rm -fv "$${link}"; \
-        @# cp -aLfv "$${target}" "$${link}" || { \
-        @# rm -rfv "$${link}"; \
-        @# ln -sfv "$${target}" "$${link}"; \
-        @# } \
-        @# fi; \
-        @# done;
</del><span class="cx">
</span><span class="cx"> install:: install-config
</span><span class="cx"> install-config::
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/resource.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/resource.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/resource.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -776,7 +776,7 @@
</span><span class="cx"> else:
</span><span class="cx"> home = self._newStoreObject.ownerHome()
</span><span class="cx"> principal = (yield self.principalForUID(home.uid()))
</span><del>- returnValue(element.HRef(principal.principalURL()))
</del><ins>+ returnValue(element.HRef(principal.principalURL()) if principal else None)
</ins><span class="cx"> else:
</span><span class="cx"> parent = (yield self.locateParent(request, request.urlForResource(self)))
</span><span class="cx"> if parent and isinstance(parent, CalDAVResource):
</span><span class="lines">@@ -1162,7 +1162,8 @@
</span><span class="cx"> sharedParent = None
</span><span class="cx"> if self.isShareeResource():
</span><span class="cx"> # A sharee collection's quota root is the resource owner's root
</span><del>- sharedParent = (yield request.locateResource(parentForURL(self._share_url)))
</del><ins>+ if self._share_url:
+ sharedParent = (yield request.locateResource(parentForURL(self._share_url)))
</ins><span class="cx"> else:
</span><span class="cx"> parent = (yield self.locateParent(request, request.urlForResource(self)))
</span><span class="cx"> if isCalendarCollectionResource(parent) or isAddressBookCollectionResource(parent):
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavsharingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/sharing.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/sharing.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/sharing.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -424,8 +424,7 @@
</span><span class="cx"> if principal:
</span><span class="cx"> if request:
</span><span class="cx"> ownerPrincipal = (yield self.ownerPrincipal(request))
</span><del>- owner = ownerPrincipal.principalURL()
- if owner == principal.principalURL():
</del><ins>+ if ownerPrincipal is None or ownerPrincipal.principalURL() == principal.principalURL():
</ins><span class="cx"> returnValue(None)
</span><span class="cx"> returnValue(principal.principalURL())
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavstdconfigpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/stdconfig.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/stdconfig.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/stdconfig.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -15,30 +15,27 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx">
</span><ins>+import copy
</ins><span class="cx"> import os
</span><del>-import copy
</del><ins>+from plistlib import PlistParser # @UnresolvedImport
</ins><span class="cx"> import re
</span><span class="cx"> from socket import getfqdn, gethostbyname
</span><span class="cx">
</span><ins>+from calendarserver.push.util import getAPNTopicFromCertificate
+from twext.python.log import Logger, InvalidLogLevelError, LogLevel
+from twisted.python.filepath import FilePath
</ins><span class="cx"> from twisted.python.runtime import platform
</span><del>-
-from plistlib import PlistParser # @UnresolvedImport
-from twext.python.log import Logger, InvalidLogLevelError, LogLevel
-from txweb2.dav.resource import TwistedACLInheritable
-
-from txdav.xml import element as davxml
-
</del><span class="cx"> from twistedcaldav import caldavxml, customxml, carddavxml, mkcolxml
</span><ins>+from twistedcaldav import ical
</ins><span class="cx"> from twistedcaldav.config import ConfigProvider, ConfigurationError, ConfigDict
</span><span class="cx"> from twistedcaldav.config import config, mergeData, fullServerPath
</span><del>-from twistedcaldav.util import getPasswordFromKeychain
</del><ins>+from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
</ins><span class="cx"> from twistedcaldav.util import KeychainAccessError, KeychainPasswordNotFound
</span><span class="cx"> from twistedcaldav.util import computeProcessCount
</span><del>-from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
</del><ins>+from twistedcaldav.util import getPasswordFromKeychain
+from txdav.xml import element as davxml
+from txweb2.dav.resource import TwistedACLInheritable
</ins><span class="cx">
</span><del>-from calendarserver.push.util import getAPNTopicFromCertificate
-from twistedcaldav import ical
-
</del><span class="cx"> log = Logger()
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1363,8 +1360,18 @@
</span><span class="cx"> if param not in DEFAULT_RESOURCE_PARAMS[configDict.ResourceService.type]:
</span><span class="cx"> del configDict.ResourceService.params[param]
</span><span class="cx">
</span><ins>+ # Upgrading resources.xml must be done prior to using the store/directory
+ if configDict.ResourceService.Enabled and configDict.ResourceService.type == "xml":
+ resourcesFileName = configDict.ResourceService.params.xmlFile
+ if resourcesFileName[0] not in ("/", "."):
+ resourcesFileName = os.path.join(configDict.DataRoot, resourcesFileName)
+ resourcesFilePath = FilePath(resourcesFileName)
+ if resourcesFilePath.exists():
+ from twistedcaldav.upgrade import upgradeResourcesXML
+ upgradeResourcesXML(resourcesFilePath)
</ins><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def _preUpdateDirectoryAddressBookBackingDirectoryService(configDict, items, reloading=False):
</span><span class="cx"> #
</span><span class="cx"> # Special handling for directory address book configs
</span><span class="lines">@@ -1402,8 +1409,18 @@
</span><span class="cx"> log.warn("Parameter %s is not supported by service %s" % (param, configDict.AugmentService.type))
</span><span class="cx"> del configDict.AugmentService.params[param]
</span><span class="cx">
</span><ins>+ # Upgrading augments.xml must be done prior to using the store/directory
+ if configDict.AugmentService.type == "twistedcaldav.directory.augment.AugmentXMLDB":
+ for fileName in configDict.AugmentService.params.xmlFiles:
+ if fileName[0] not in ("/", "."):
+ fileName = os.path.join(configDict.DataRoot, fileName)
+ filePath = FilePath(fileName)
+ if filePath.exists():
+ from twistedcaldav.upgrade import upgradeAugmentsXML
+ upgradeAugmentsXML(filePath)
</ins><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def _updateACLs(configDict, reloading=False):
</span><span class="cx"> #
</span><span class="cx"> # Base resource ACLs
</span><span class="lines">@@ -1714,6 +1731,7 @@
</span><span class="cx"> _updateCompliance,
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def _cleanup(configDict, defaultDict):
</span><span class="cx"> cleanDict = copy.deepcopy(configDict)
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavstorebridgepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/storebridge.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/storebridge.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/storebridge.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -301,7 +301,7 @@
</span><span class="cx">
</span><span class="cx"> def owner_url(self):
</span><span class="cx"> if self.isShareeResource():
</span><del>- return joinURL(self._share_url, "/")
</del><ins>+ return joinURL(self._share_url, "/") if self._share_url else ""
</ins><span class="cx"> else:
</span><span class="cx"> return self.url()
</span><span class="cx">
</span><span class="lines">@@ -2982,6 +2982,16 @@
</span><span class="cx"> if not self.exists():
</span><span class="cx"> raise HTTPError(NOT_FOUND)
</span><span class="cx">
</span><ins>+ # Do schedule tag check
+ try:
+ self.validIfScheduleMatch(request)
+ except HTTPError as e:
+ if e.response.code == responsecode.PRECONDITION_FAILED:
+ response = yield self._processPrefer(request, e.response)
+ raise HTTPError(response)
+ else:
+ raise
+
</ins><span class="cx"> # Split point is in the rid query parameter
</span><span class="cx"> rid = request.args.get("rid")
</span><span class="cx"> if rid is None:
</span><span class="lines">@@ -3007,11 +3017,11 @@
</span><span class="cx">
</span><span class="cx"> try:
</span><span class="cx"> otherStoreObject = yield self._newStoreObject.splitAt(rid, pastUID)
</span><del>- except InvalidSplit:
</del><ins>+ except InvalidSplit as e:
</ins><span class="cx"> raise HTTPError(ErrorResponse(
</span><span class="cx"> FORBIDDEN,
</span><del>- (calendarserver_namespace, "invalid-split",),
- "The rid parameter in the request-URI contains an invalid value",
</del><ins>+ (calendarserver_namespace, "valid-split",),
+ str(e),
</ins><span class="cx"> ))
</span><span class="cx">
</span><span class="cx"> other = yield request.locateChildResource(self._parentResource, otherStoreObject.name())
</span><span class="lines">@@ -3029,6 +3039,8 @@
</span><span class="cx"> raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, "Cannot generate requested data type"))
</span><span class="cx"> etag1 = yield self.etag()
</span><span class="cx"> etag2 = yield other.etag()
</span><ins>+ scheduletag1 = self.scheduleTag
+ scheduletag2 = otherStoreObject.scheduleTag
</ins><span class="cx"> cal1 = yield self.component()
</span><span class="cx"> cal2 = yield other.component()
</span><span class="cx">
</span><span class="lines">@@ -3038,6 +3050,7 @@
</span><span class="cx"> davxml.PropertyStatus(
</span><span class="cx"> davxml.PropertyContainer(
</span><span class="cx"> davxml.GETETag.fromString(etag1.generate()),
</span><ins>+ caldavxml.ScheduleTag.fromString(scheduletag1),
</ins><span class="cx"> caldavxml.CalendarData.fromComponent(cal1, accepted_type),
</span><span class="cx"> ),
</span><span class="cx"> davxml.Status.fromResponseCode(OK),
</span><span class="lines">@@ -3048,6 +3061,7 @@
</span><span class="cx"> davxml.PropertyStatus(
</span><span class="cx"> davxml.PropertyContainer(
</span><span class="cx"> davxml.GETETag.fromString(etag2.generate()),
</span><ins>+ caldavxml.ScheduleTag.fromString(scheduletag2),
</ins><span class="cx"> caldavxml.CalendarData.fromComponent(cal2, accepted_type),
</span><span class="cx"> ),
</span><span class="cx"> davxml.Status.fromResponseCode(OK),
</span><span class="lines">@@ -3920,15 +3934,21 @@
</span><span class="cx">
</span><span class="cx"> if jsondata["notification-type"] == "invite-notification":
</span><span class="cx"> ownerPrincipal = yield self.principalForUID(jsondata["owner"])
</span><del>- ownerCN = ownerPrincipal.displayName()
- ownerHomeURL = ownerPrincipal.calendarHomeURLs()[0] if jsondata["shared-type"] == "calendar" else ownerPrincipal.addressBookHomeURLs()[0]
-
- # FIXME: use urn:uuid always?
- if jsondata["shared-type"] == "calendar":
- owner = ownerPrincipal.principalURL()
</del><ins>+ if ownerPrincipal is None:
+ ownerCN = ""
+ ownerCollectionURL = ""
+ owner = "urn:x-uid:" + jsondata["owner"]
</ins><span class="cx"> else:
</span><del>- owner = "urn:x-uid:" + ownerPrincipal.principalUID()
</del><ins>+ ownerCN = ownerPrincipal.displayName()
+ ownerHomeURL = ownerPrincipal.calendarHomeURLs()[0] if jsondata["shared-type"] == "calendar" else ownerPrincipal.addressBookHomeURLs()[0]
+ ownerCollectionURL = urljoin(ownerHomeURL, jsondata["ownerName"])
</ins><span class="cx">
</span><ins>+ # FIXME: use urn:uuid always?
+ if jsondata["shared-type"] == "calendar":
+ owner = ownerPrincipal.principalURL()
+ else:
+ owner = "urn:x-uid:" + ownerPrincipal.principalUID()
+
</ins><span class="cx"> shareePrincipal = yield self.principalForUID(jsondata["sharee"])
</span><span class="cx">
</span><span class="cx"> if "supported-components" in jsondata:
</span><span class="lines">@@ -3952,7 +3972,7 @@
</span><span class="cx"> invitationBindStatusToXMLMap[jsondata["status"]](),
</span><span class="cx"> customxml.InviteAccess(invitationBindModeToXMLMap[jsondata["access"]]()),
</span><span class="cx"> customxml.HostURL(
</span><del>- element.HRef.fromString(urljoin(ownerHomeURL, jsondata["ownerName"])),
</del><ins>+ element.HRef.fromString(ownerCollectionURL),
</ins><span class="cx"> ),
</span><span class="cx"> customxml.Organizer(
</span><span class="cx"> element.HRef.fromString(owner),
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavtesttest_sharingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/test/test_sharing.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/test/test_sharing.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/test/test_sharing.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -102,6 +102,66 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><ins>+ def _doPROPFINDHome(self, resultcode=responsecode.MULTI_STATUS):
+ body = """<?xml version="1.0" encoding="UTF-8"?>
+<A:propfind xmlns:A="DAV:">
+ <A:prop>
+ <A:add-member/>
+ <C:allowed-sharing-modes xmlns:C="http://calendarserver.org/ns/"/>
+ <D:autoprovisioned xmlns:D="http://apple.com/ns/ical/"/>
+ <E:bulk-requests xmlns:E="http://me.com/_namespace/"/>
+ <D:calendar-color xmlns:D="http://apple.com/ns/ical/"/>
+ <B:calendar-description xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+ <B:calendar-free-busy-set xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+ <D:calendar-order xmlns:D="http://apple.com/ns/ical/"/>
+ <B:calendar-timezone xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+ <A:current-user-privilege-set/>
+ <B:default-alarm-vevent-date xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+ <B:default-alarm-vevent-datetime xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+ <A:displayname/>
+ <C:getctag xmlns:C="http://calendarserver.org/ns/"/>
+ <C:invite xmlns:C="http://calendarserver.org/ns/"/>
+ <D:language-code xmlns:D="http://apple.com/ns/ical/"/>
+ <D:location-code xmlns:D="http://apple.com/ns/ical/"/>
+ <A:owner/>
+ <C:pre-publish-url xmlns:C="http://calendarserver.org/ns/"/>
+ <C:publish-url xmlns:C="http://calendarserver.org/ns/"/>
+ <C:push-transports xmlns:C="http://calendarserver.org/ns/"/>
+ <C:pushkey xmlns:C="http://calendarserver.org/ns/"/>
+ <A:quota-available-bytes/>
+ <A:quota-used-bytes/>
+ <D:refreshrate xmlns:D="http://apple.com/ns/ical/"/>
+ <A:resource-id/>
+ <A:resourcetype/>
+ <B:schedule-calendar-transp xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+ <B:schedule-default-calendar-URL xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+ <C:source xmlns:C="http://calendarserver.org/ns/"/>
+ <C:subscribed-strip-alarms xmlns:C="http://calendarserver.org/ns/"/>
+ <C:subscribed-strip-attachments xmlns:C="http://calendarserver.org/ns/"/>
+ <C:subscribed-strip-todos xmlns:C="http://calendarserver.org/ns/"/>
+ <B:supported-calendar-component-set xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+ <B:supported-calendar-component-sets xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+ <A:supported-report-set/>
+ <A:sync-token/>
+ </A:prop>
+</A:propfind>
+"""
+ authPrincipal = yield self.actualRoot.findPrincipalForAuthID("user02")
+ request = SimpleStoreRequest(self, "PROPFIND", "/calendars/__uids__/user02/", content=body, authPrincipal=authPrincipal)
+ request.headers.setHeader("content-type", MimeType("text", "xml"))
+ request.headers.setHeader("depth", "1")
+ response = yield self.send(request)
+ response = IResponse(response)
+ self.assertEqual(response.code, resultcode)
+
+ if response.stream:
+ data = yield allDataFromStream(response.stream)
+ returnValue(data)
+ else:
+ returnValue(None)
+
+
+ @inlineCallbacks
</ins><span class="cx"> def _getResource(self):
</span><span class="cx"> request = SimpleStoreRequest(self, "GET", "/calendars/__uids__/user01/calendar/")
</span><span class="cx"> resource = yield request.locateResource("/calendars/__uids__/user01/calendar/")
</span><span class="lines">@@ -1234,6 +1294,9 @@
</span><span class="cx"> record = yield self.userRecordWithShortName("user01")
</span><span class="cx"> yield self.changeRecord(record, self.directory.fieldName.hasCalendars, False)
</span><span class="cx">
</span><ins>+ data = yield self._doPROPFINDHome()
+ self.assertTrue(data is not None)
+
</ins><span class="cx"> resource = (yield self._getResourceSharer(href))
</span><span class="cx"> propInvite = yield resource.inviteProperty(None)
</span><span class="cx"> self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite(
</span><span class="lines">@@ -1297,6 +1360,9 @@
</span><span class="cx"> yield self.directory.removeRecords(((yield self.userUIDFromShortName("user01")),))
</span><span class="cx"> self.assertTrue((yield self.userUIDFromShortName("user01")) is None)
</span><span class="cx">
</span><ins>+ data = yield self._doPROPFINDHome()
+ self.assertTrue(data is not None)
+
</ins><span class="cx"> resource = (yield self._getResourceSharer(href))
</span><span class="cx"> propInvite = yield resource.inviteProperty(None)
</span><span class="cx"> self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite(
</span><span class="lines">@@ -1314,6 +1380,33 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><ins>+ def test_shareeNotificationWithMissingSharer(self):
+
+ yield self.resource.upgradeToShare()
+
+ yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
+ <CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+ <CS:set>
+ <D:href>mailto:user02@example.com</D:href>
+ <CS:summary>My Shared Calendar</CS:summary>
+ <CS:read-write/>
+ </CS:set>
+ </CS:share>
+ """)
+
+ yield self.directory.removeRecords(((yield self.userUIDFromShortName("user01")),))
+ self.assertTrue((yield self.userUIDFromShortName("user01")) is None)
+
+ request = SimpleStoreRequest(self, "GET", "/calendars/__uids__/user02/notification/")
+ notification = yield request.locateResource("/calendars/__uids__/user02/notification/")
+ names = yield notification.listChildren()
+ self.assertEqual(len(names), 1)
+ note_child = yield notification.getChild(names[0])
+ note = yield note_child.text()
+ self.assertTrue(isinstance(note, str))
+
+
+ @inlineCallbacks
</ins><span class="cx"> def test_hideInvalidSharers(self):
</span><span class="cx">
</span><span class="cx"> yield self.resource.upgradeToShare()
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtwistedcaldavupgradepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/upgrade.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/upgrade.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/twistedcaldav/upgrade.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -758,22 +758,6 @@
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def upgradeData(config, directory):
</span><span class="cx">
</span><del>- if config.ResourceService.Enabled:
- resourcesFileName = config.ResourceService.params.xmlFile
- if resourcesFileName[0] not in ("/", "."):
- resourcesFileName = os.path.join(config.DataRoot, resourcesFileName)
- resourcesFilePath = FilePath(resourcesFileName)
- if resourcesFilePath.exists():
- upgradeResourcesXML(resourcesFilePath)
-
- if config.AugmentService.type == "twistedcaldav.directory.augment.AugmentXMLDB":
- for fileName in config.AugmentService.params.xmlFiles:
- if fileName[0] not in ("/", "."):
- fileName = os.path.join(config.DataRoot, fileName)
- filePath = FilePath(fileName)
- if filePath.exists():
- upgradeAugmentsXML(filePath)
-
</del><span class="cx"> triggerPath = os.path.join(config.ServerRoot, TRIGGER_FILE)
</span><span class="cx"> if os.path.exists(triggerPath):
</span><span class="cx"> try:
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduledkimpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/dkim.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/dkim.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/dkim.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -294,8 +294,16 @@
</span><span class="cx">
</span><span class="cx"> @staticmethod
</span><span class="cx"> def canonicalizeBody(data):
</span><del>- if not data.endswith("\r\n"):
- data += "\r\n"
</del><ins>+ """
+ DKIM simple body canonicalization: remove empty lines at the end
+ and ensure it ends with one \r\n.
+
+ @param data: data to canonicalize
+ @type data: L{str}
+ """
+ while data.endswith("\r\n"):
+ data = data[:-2]
+ data += "\r\n"
</ins><span class="cx"> return data
</span><span class="cx">
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduleresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/resource.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/resource.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/resource.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -179,31 +179,35 @@
</span><span class="cx"> "version": "2.0",
</span><span class="cx"> })
</span><span class="cx"> )
</span><del>- result = ischedulexml.QueryResult(
</del><span class="cx">
</span><del>- ischedulexml.Capabilities(
- ischedulexml.Version.fromString(config.Scheduling.iSchedule.SerialNumber),
- ischedulexml.Versions(
- ischedulexml.Version.fromString("1.0"),
- ),
- ischedulexml.SchedulingMessages(
</del><ins>+ componentTypes = []
+ from twistedcaldav.ical import allowedSchedulingComponents
+ for name in allowedSchedulingComponents:
+ if name == "VFREEBUSY":
+ componentTypes.append(
</ins><span class="cx"> ischedulexml.Component(
</span><span class="cx"> ischedulexml.Method(name="REQUEST"),
</span><del>- ischedulexml.Method(name="CANCEL"),
- ischedulexml.Method(name="REPLY"),
- name="VEVENT"
- ),
</del><ins>+ name=name
+ )
+ )
+ else:
+ componentTypes.append(
</ins><span class="cx"> ischedulexml.Component(
</span><span class="cx"> ischedulexml.Method(name="REQUEST"),
</span><span class="cx"> ischedulexml.Method(name="CANCEL"),
</span><span class="cx"> ischedulexml.Method(name="REPLY"),
</span><del>- name="VTODO"
- ),
- ischedulexml.Component(
- ischedulexml.Method(name="REQUEST"),
- name="VFREEBUSY"
- ),
</del><ins>+ name=name
+ )
+ )
+
+ result = ischedulexml.QueryResult(
+
+ ischedulexml.Capabilities(
+ ischedulexml.Version.fromString(config.Scheduling.iSchedule.SerialNumber),
+ ischedulexml.Versions(
+ ischedulexml.Version.fromString("1.0"),
</ins><span class="cx"> ),
</span><ins>+ ischedulexml.SchedulingMessages(*componentTypes),
</ins><span class="cx"> ischedulexml.CalendarDataTypes(*dataTypes),
</span><span class="cx"> ischedulexml.Attachments(
</span><span class="cx"> ischedulexml.External(),
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingischeduletesttest_dkimpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/ischedule/test/test_dkim.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -389,6 +389,33 @@
</span><span class="cx"> self.assertEqual(extracted, result.replace("\n", "\r\n"))
</span><span class="cx">
</span><span class="cx">
</span><ins>+ def test_canonicalize_body(self):
+ """
+ L{DKIMUtils.canonicalizeBody} correctly canonicalizes bodies.
+ """
+
+ data = (
+ (
+ """Simple""",
+ """Simple\n""",
+ ),
+ (
+ """Simple\n""",
+ """Simple\n""",
+ ),
+ (
+ """Simple\n\n""",
+ """Simple\n""",
+ ),
+ )
+
+ for text, result in data:
+ self.assertEqual(
+ DKIMUtils.canonicalizeBody(text.replace("\n", "\r\n")),
+ result.replace("\n", "\r\n"),
+ )
+
+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def test_locate_public_key(self):
</span><span class="cx"> """
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingitippy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/itip.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/itip.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/itip.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -358,6 +358,40 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @staticmethod
</span><ins>+ def processPollStatus(itip_message, calendar, recipient):
+ """
+ Process a METHOD=POLLSTATUS.
+
+ @param itip_message: the iTIP message to process.
+ @type itip_message: L{Component}
+ @param calendar: the calendar object to apply the POLLSTATUS to
+ @type calendar: L{Component}
+
+ @return: the update calendar component or C{None}
+ """
+
+ # Check sequencing
+ if not iTipProcessing.sequenceComparison(itip_message, calendar):
+ # Ignore out of sequence message
+ return None
+
+ calendar_master = calendar.masterComponent()
+ itip_master = itip_message.masterComponent()
+
+ # Remove each VVOTER in the original (except for the recipients)
+ for component in tuple(calendar_master.subcomponents()):
+ if component.name() == "VVOTER" and component.propertyValue("VOTER") != recipient:
+ calendar_master.removeComponent(component)
+
+ # Add each VVOTER in the iTip message
+ for component in itip_master.subcomponents():
+ if component.name() == "VVOTER" and component.propertyValue("VOTER") != recipient:
+ calendar_master.addComponent(component.duplicate())
+
+ return calendar
+
+
+ @staticmethod
</ins><span class="cx"> def processReply(itip_message, calendar):
</span><span class="cx"> """
</span><span class="cx"> Process a METHOD=REPLY.
</span><span class="lines">@@ -576,7 +610,7 @@
</span><span class="cx"> # Do VPOLL transfer
</span><span class="cx"> if reply_component.name() == "VPOLL":
</span><span class="cx"> # TODO: figure out how to report changes back
</span><del>- iTipProcessing.updateVPOLLDataFromReply(reply_component, organizer_component, attendee)
</del><ins>+ partstat_changed = iTipProcessing.updateVPOLLDataFromReply(reply_component, organizer_component, attendee)
</ins><span class="cx">
</span><span class="cx"> return attendee.value(), partstat_changed, private_comment_changed
</span><span class="cx">
</span><span class="lines">@@ -595,6 +629,8 @@
</span><span class="cx"> @type attendee: L{Property}
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+ partstat_changed = False
+
</ins><span class="cx"> # Get REQUEST-STATUS as we need to write that into the saved ATTENDEE property
</span><span class="cx"> reqstatus = tuple(reply_component.properties("REQUEST-STATUS"))
</span><span class="cx"> if reqstatus:
</span><span class="lines">@@ -607,12 +643,13 @@
</span><span class="cx"> organizerVoter = organizer_component.voterComponentForVoter(attendee.value())
</span><span class="cx">
</span><span class="cx"> if replyVoter is None:
</span><del>- return
</del><ins>+ return partstat_changed
</ins><span class="cx">
</span><span class="cx"> if organizerVoter is None:
</span><span class="cx"> # Add in the new one
</span><span class="cx"> organizerVoter = replyVoter.duplicate()
</span><span class="cx"> reply_component.addComponent(organizerVoter)
</span><ins>+ partstat_changed = True
</ins><span class="cx"> else:
</span><span class="cx"> # Merge each vote
</span><span class="cx"> replyMap = replyVoter.voteMap()
</span><span class="lines">@@ -621,9 +658,12 @@
</span><span class="cx"> # Add new ones
</span><span class="cx"> for vote in set(replyMap.keys()) - set(organizerMap.keys()):
</span><span class="cx"> organizerVoter.addComponent(replyMap[vote].duplicate())
</span><ins>+ partstat_changed = True
</ins><span class="cx">
</span><span class="cx"> # Replace existing ones
</span><span class="cx"> for vote in set(replyMap.keys()) & set(organizerMap.keys()):
</span><ins>+ if organizerMap[vote].propertyValue("RESPONSE") != replyMap[vote].propertyValue("RESPONSE"):
+ partstat_changed = True
</ins><span class="cx"> organizerVoter.removeComponent(organizerMap[vote])
</span><span class="cx"> organizerVoter.addComponent(replyMap[vote].duplicate())
</span><span class="cx">
</span><span class="lines">@@ -635,7 +675,9 @@
</span><span class="cx"> except KeyError:
</span><span class="cx"> pass
</span><span class="cx">
</span><ins>+ return partstat_changed
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> @staticmethod
</span><span class="cx"> def transferItems(from_calendar, to_component, needs_action_rids, reschedule, master_details, remove_matched=False):
</span><span class="cx"> """
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingprocessingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/processing.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/processing.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/processing.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -90,8 +90,9 @@
</span><span class="cx"> @param recipient: calendar user receiving the message
</span><span class="cx"> @type recipient: C{str}
</span><span class="cx">
</span><del>- @return: a C{tuple} of (C{bool}, C{bool}) indicating whether the message was processed, and if it was whether
- auto-processing has taken place.
</del><ins>+ @return: a C{tuple} of (C{bool}, C{bool}, C{bool}, C{bool}) indicating whether the message was processed,
+ and if it was whether auto-processing has taken place, whether it needs to be stored in the inbox, and
+ the changes property for the inbox item.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> self.txn = txn
</span><span class="lines">@@ -151,7 +152,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def isAttendeeReceivingMessage(self):
</span><del>- return self.method in ("REQUEST", "ADD", "CANCEL")
</del><ins>+ return self.method in ("REQUEST", "ADD", "CANCEL", "POLLSTATUS")
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><span class="lines">@@ -393,6 +394,8 @@
</span><span class="cx"> elif self.method == "ADD":
</span><span class="cx"> # TODO: implement ADD
</span><span class="cx"> result = (False, False, False, None)
</span><ins>+ elif self.method == "POLLSTATUS":
+ result = (yield self.doImplicitAttendeePollStatus())
</ins><span class="cx"> else:
</span><span class="cx"> # NB We should never get here as we will have rejected unsupported METHODs earlier.
</span><span class="cx"> result = (True, True, False, None,)
</span><span class="lines">@@ -552,7 +555,7 @@
</span><span class="cx"> else:
</span><span class="cx"> # Request needs to be ignored
</span><span class="cx"> log.debug("ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:REQUEST, UID: '%s' - ignoring" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
</span><del>- result = (True, True, False, None,)
</del><ins>+ result = (True, False, False, None,)
</ins><span class="cx">
</span><span class="cx"> returnValue(result)
</span><span class="cx">
</span><span class="lines">@@ -570,7 +573,7 @@
</span><span class="cx"> # If there is no existing copy, then ignore
</span><span class="cx"> if self.recipient_calendar is None:
</span><span class="cx"> log.debug("ImplicitProcessing - originator '%s' to recipient '%s' ignoring METHOD:CANCEL, UID: '%s' - attendee has no copy" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
</span><del>- result = (True, True, True, None)
</del><ins>+ result = (True, False, True, None)
</ins><span class="cx"> else:
</span><span class="cx"> # Need to check for auto-respond attendees. These need to suppress the inbox message
</span><span class="cx"> # if the cancel is processed. However, if the principal is a user we always force the
</span><span class="lines">@@ -631,12 +634,36 @@
</span><span class="cx"> result = (True, autoprocessed, store_inbox, changes)
</span><span class="cx"> else:
</span><span class="cx"> log.debug("ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:CANCEL, UID: '%s' - ignoring" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
</span><del>- result = (True, True, False, None)
</del><ins>+ result = (True, False, False, None)
</ins><span class="cx">
</span><span class="cx"> returnValue(result)
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><ins>+ def doImplicitAttendeePollStatus(self):
+ """
+ An iTIP message status update has been sent to an attendee by the organizer. We need to update the
+ attendee state based on the nature of the iTIP message.
+ """
+ # If there is no existing copy, then we must fail
+ if self.new_resource:
+ log.debug("ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:POLLSTATUS, UID: '%s' - attendee has no copy" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
+ returnValue((True, False, False, None,))
+
+ processed_message = iTipProcessing.processPollStatus(self.message, self.recipient_calendar)
+
+ # Let the store know that no time-range info has changed for a refresh (assuming that
+ # no auto-accept changes were made)
+ processed_message.noInstanceIndexing = True
+
+ # Update the attendee's copy of the event
+ log.debug("ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:POLLSTATUS, UID: '%s' - updating poll" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
+ yield self.writeCalendarResource(None, self.recipient_calendar_resource, processed_message)
+
+ returnValue((True, False, False, None,))
+
+
+ @inlineCallbacks
</ins><span class="cx"> def checkAttendeeAutoReply(self, calendar, automode):
</span><span class="cx"> """
</span><span class="cx"> Check whether a reply to the given iTIP message is needed and if so make the
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingschedulerpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/scheduler.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/scheduler.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/scheduler.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -515,7 +515,7 @@
</span><span class="cx"> yield self.generateRemoteSchedulingResponses(otherserver_recipients, responses, freebusy, getattr(self.txn, 'doing_attendee_refresh', False))
</span><span class="cx">
</span><span class="cx"> # To reduce chatter, we suppress certain messages
</span><del>- if not self.suppress_refresh:
</del><ins>+ if not self.suppress_refresh or self.calendar.mainType() == "VPOLL":
</ins><span class="cx">
</span><span class="cx"> # Now process remote recipients
</span><span class="cx"> if remote_recipients:
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoreschedulingtesttest_itippy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/test/test_itip.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/test/test_itip.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/scheduling/test/test_itip.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -21,7 +21,7 @@
</span><span class="cx"> from twisted.trial import unittest
</span><span class="cx">
</span><span class="cx"> from twistedcaldav.stdconfig import config
</span><del>-from twistedcaldav.ical import Component
</del><ins>+from twistedcaldav.ical import Component, normalize_iCalStr
</ins><span class="cx">
</span><span class="cx"> from txdav.caldav.datastore.scheduling.itip import iTipProcessing, iTipGenerator
</span><span class="cx">
</span><span class="lines">@@ -1289,6 +1289,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ None,
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "1.2 Simple Reply - recurring no overrides",
</span><span class="lines">@@ -1335,6 +1336,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ None,
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "1.3 Simple Reply - recurring with missing master",
</span><span class="lines">@@ -1389,6 +1391,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ None,
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "1.4 Simple Reply - recurring with overrides in master but not reply",
</span><span class="lines">@@ -1453,6 +1456,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ None,
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "1.5 Simple Reply - recurring with overrides in master invalid in reply",
</span><span class="lines">@@ -1517,6 +1521,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ None,
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "1.6 Simple Reply - recurring with overrides in master, invalid ones in reply",
</span><span class="lines">@@ -1590,6 +1595,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ None,
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "2.1 X-CALENDARSERVER-RESET-PARTSTAT Reply - non recurring",
</span><span class="lines">@@ -1636,6 +1642,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ None,
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "2.2 X-CALENDARSERVER-RESET-PARTSTAT Reply - non recurring",
</span><span class="lines">@@ -1682,6 +1689,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ None,
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "2.3 X-CALENDARSERVER-RESET-PARTSTAT Reply - non recurring",
</span><span class="lines">@@ -1728,6 +1736,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ None,
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "2.4 X-CALENDARSERVER-RESET-PARTSTAT Reply - non recurring",
</span><span class="lines">@@ -1774,6 +1783,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ None,
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "3.1 Simple VPOLL Reply - response added",
</span><span class="lines">@@ -1874,6 +1884,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ ('mailto:user2@example.com', set([("", True, False,)])),
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "3.2 Simple VPOLL Reply - response changed",
</span><span class="lines">@@ -1978,6 +1989,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ ('mailto:user2@example.com', set([("", True, False,)])),
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "3.3 Simple VPOLL Reply - response added and changed",
</span><span class="lines">@@ -2090,6 +2102,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ ('mailto:user2@example.com', set([("", True, False,)])),
</ins><span class="cx"> ),
</span><span class="cx"> (
</span><span class="cx"> "3.4 Simple VPOLL Reply - response one changed",
</span><span class="lines">@@ -2202,21 +2215,475 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> """,
</span><span class="cx"> True,
</span><ins>+ ('mailto:user2@example.com', set([("", True, False,)])),
</ins><span class="cx"> ),
</span><ins>+ (
+ "3.5 Simple VPOLL Reply - no changes",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN="User 01":mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:50
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN="User 01":mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ORGANIZER;CN="User 01":mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+METHOD:REPLY
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN="User 01":mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:50
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+END:VPOLL
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN="User 01":mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;SCHEDULE-STATUS=2.0:mailto:user2@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:50
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN="User 01":mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ORGANIZER;CN="User 01":mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+""",
+ True,
+ ('mailto:user2@example.com', set([])),
+ ),
</ins><span class="cx"> )
</span><span class="cx">
</span><del>- for title, calendar_txt, itip_txt, changed_txt, expected in data:
</del><ins>+ for title, calendar_txt, itip_txt, changed_txt, expected, processed in data:
</ins><span class="cx"> calendar = Component.fromString(calendar_txt)
</span><span class="cx"> itip = Component.fromString(itip_txt)
</span><span class="cx"> if expected:
</span><span class="cx"> changed = Component.fromString(changed_txt)
</span><span class="cx">
</span><del>- result, _ignore = iTipProcessing.processReply(itip, calendar)
</del><ins>+ result, result_processed = iTipProcessing.processReply(itip, calendar)
</ins><span class="cx"> self.assertEqual(result, expected, msg="Result mismatch: %s" % (title,))
</span><span class="cx"> if expected:
</span><span class="cx"> self.assertEqual(changed, calendar, msg="Calendar mismatch: %s" % (title,))
</span><ins>+ if processed is not None:
+ self.assertEqual(result_processed, processed, msg="Process mismatch: %s" % (title,))
</ins><span class="cx">
</span><span class="cx">
</span><ins>+ def test_processPollStatus(self):
+ """
+ Test iTIPProcessing.processPollStatus
+ """
+
+ data = (
+ (
+ "3.1 Simple VPOLL - response added",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+METHOD:POLLSTATUS
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:0
+END:VOTE
+END:VVOTER
+END:VPOLL
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:0
+END:VOTE
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+""",
+ ),
+ (
+ "3.2 Simple VPOLL - recipient response not changed",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:user2@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+METHOD:POLLSTATUS
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:50
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:0
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:0
+END:VOTE
+END:VVOTER
+END:VPOLL
+END:VCALENDAR
+""",
+ """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VPOLL
+UID:8D2B2048-7915-6ECD-A82B-01F4EF8EEBEA
+DTSTAMP:20150113T152404Z
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-MODE:BASIC
+POLL-PROPERTIES:DTSTART,DTEND
+SUMMARY:New Poll
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user1@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:100
+END:VOTE
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user2@example.com
+END:VVOTER
+BEGIN:VVOTER
+DTSTAMP:20150113T152404Z
+VOTER;RSVP=TRUE:mailto:user3@example.com
+BEGIN:VOTE
+POLL-ITEM-ID:1
+RESPONSE:100
+END:VOTE
+BEGIN:VOTE
+POLL-ITEM-ID:2
+RESPONSE:0
+END:VOTE
+END:VVOTER
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080601T120000Z
+DTEND:20080601T130000Z
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-ITEM-ID:1
+END:VEVENT
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20080602T120000Z
+DTEND:20080602T130000Z
+ATTENDEE:mailto:user1@example.com
+ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:user2@example.com
+ORGANIZER;CN=User 01:mailto:user1@example.com
+POLL-ITEM-ID:2
+END:VEVENT
+END:VPOLL
+END:VCALENDAR
+""",
+ ),
+ )
+
+ for title, calendar_txt, itip_txt, changed_txt in data:
+ calendar = Component.fromString(calendar_txt)
+ itip = Component.fromString(itip_txt)
+
+ result = iTipProcessing.processPollStatus(itip, calendar, "mailto:user2@example.com")
+ self.assertEqual(normalize_iCalStr(result), normalize_iCalStr(changed_txt), msg="Calendar mismatch: %s" % (title,))
+
+
</ins><span class="cx"> def test_update_attendee_partstat(self):
</span><span class="cx">
</span><span class="cx"> data = (
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/sql.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/sql.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/sql.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -2303,7 +2303,9 @@
</span><span class="cx"> self._cachedComponent = None
</span><span class="cx"> self._cachedCommponentPerUser = {}
</span><span class="cx">
</span><ins>+ self._lockedUID = False
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> @classmethod
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def _createInternal(cls, parent, name, component, internal_state, options=None, split_details=None):
</span><span class="lines">@@ -3116,8 +3118,8 @@
</span><span class="cx"> internal_request=is_internal,
</span><span class="cx"> ))
</span><span class="cx">
</span><del>- # group attendees
- if scheduler.state == "organizer":
</del><ins>+ # Group attendees - though not during a split
+ if scheduler.state == "organizer" and internal_state != ComponentUpdateState.SPLIT_OWNER:
</ins><span class="cx"> changed = yield self.reconcileGroupAttendees(component, inserting)
</span><span class="cx"> if changed:
</span><span class="cx"> yield scheduler.extractAttendees()
</span><span class="lines">@@ -3214,15 +3216,26 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><del>- def _lockUID(self, component, inserting, internal_state):
</del><ins>+ def _lockUID(self, uid, internal_state):
</ins><span class="cx"> """
</span><span class="cx"> Create a lock on the component's UID and verify, after getting the lock, that the incoming UID
</span><span class="cx"> meets the requirements of the store.
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+ if not self._lockedUID and internal_state in (ComponentUpdateState.NORMAL, ComponentUpdateState.SPLIT_OWNER):
+ yield NamedLock.acquire(self._txn, "ImplicitUIDLock:%s" % (hashlib.md5(uid).hexdigest(),))
+ self._lockedUID = True
+
+
+ @inlineCallbacks
+ def _lockAndCheckUID(self, component, inserting, internal_state):
+ """
+ Create a lock on the component's UID and verify, after getting the lock, that the incoming UID
+ meets the requirements of the store.
+ """
+
</ins><span class="cx"> new_uid = component.resourceUID()
</span><del>- if internal_state == ComponentUpdateState.NORMAL:
- yield NamedLock.acquire(self._txn, "ImplicitUIDLock:{0}".format(hashlib.md5(new_uid).hexdigest(),))
</del><ins>+ yield self._lockUID(new_uid, internal_state)
</ins><span class="cx">
</span><span class="cx"> # UID conflict check - note we do this after reserving the UID to avoid a race condition where two requests
</span><span class="cx"> # try to write the same calendar data to two different resource URIs.
</span><span class="lines">@@ -3302,9 +3315,27 @@
</span><span class="cx">
</span><span class="cx"> # Do scheduling only for owner split
</span><span class="cx"> if internal_state == ComponentUpdateState.SPLIT_OWNER:
</span><del>- yield self.doImplicitScheduling(component, inserting, internal_state, options, split_details)
</del><ins>+ # UID lock - this will remain active until the end of the current txn
+ yield self._lockAndCheckUID(component, inserting, internal_state)
</ins><span class="cx">
</span><del>- self.isScheduleObject = True
</del><ins>+ # Make sure various bits of scheduling meta-data are correctly setup to ensure the
+ # new resource created by a split has the proper state
+ implicit_result = yield self.doImplicitScheduling(component, inserting, internal_state, options, split_details)
+ if isinstance(implicit_result, int):
+ msg = "Invalid return status code from ImplicitScheduler during split: %s" % (implicit_result,)
+ log.error(msg)
+ raise InvalidObjectResourceError(msg)
+
+ self.isScheduleObject, new_component, did_implicit_action, schedule_state = implicit_result
+ if new_component is not None:
+ component = new_component
+ if did_implicit_action:
+ self._componentChanged = True
+
+ elif internal_state == ComponentUpdateState.SPLIT_ATTENDEE:
+ # This must always be set since the only time we get is is during scheduling
+ self.isScheduleObject = True
+
</ins><span class="cx"> self.processScheduleTags(component, inserting, internal_state)
</span><span class="cx">
</span><span class="cx"> elif internal_state != ComponentUpdateState.RAW:
</span><span class="lines">@@ -3312,7 +3343,7 @@
</span><span class="cx"> yield self.fullValidation(component, inserting, internal_state)
</span><span class="cx">
</span><span class="cx"> # UID lock - this will remain active until the end of the current txn
</span><del>- yield self._lockUID(component, inserting, internal_state)
</del><ins>+ yield self._lockAndCheckUID(component, inserting, internal_state)
</ins><span class="cx">
</span><span class="cx"> # Preserve private comments
</span><span class="cx"> yield self.preservePrivateComments(component, inserting, internal_state)
</span><span class="lines">@@ -4691,25 +4722,32 @@
</span><span class="cx"> @type pastuid: L{str}
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+ # Cannot create one with the same UID as this
+ if pastUID and pastUID == self._uid:
+ raise InvalidSplit("Cannot split an event and re-use the same UID.")
+
</ins><span class="cx"> # Must be recurring
</span><span class="cx"> component = yield self.component()
</span><span class="cx"> if not component.isRecurring():
</span><del>- raise InvalidSplit()
</del><ins>+ raise InvalidSplit("Cannot split a non-recurring event.")
</ins><span class="cx">
</span><span class="cx"> # Cannot be attendee
</span><span class="cx"> organizer = component.getOrganizer()
</span><span class="cx"> organizerAddress = (yield calendarUserFromCalendarUserAddress(organizer, self._txn)) if organizer else None
</span><span class="cx"> if organizer is not None and organizerAddress.record.uid != self.calendar().ownerHome().uid():
</span><del>- raise InvalidSplit()
</del><ins>+ raise InvalidSplit("Only organizers can split events.")
</ins><span class="cx">
</span><span class="cx"> # Determine valid split point
</span><span class="cx"> splitter = iCalSplitter(1024, 14)
</span><span class="cx"> rid = splitter.whereSplit(component, break_point=rid, allow_past_the_end=False)
</span><span class="cx"> if rid is None:
</span><del>- raise InvalidSplit()
</del><ins>+ raise InvalidSplit("Cannot find a suitable recurrence-id to split at.")
</ins><span class="cx">
</span><span class="cx"> # Do split and return new resource
</span><del>- olderObject = yield self.split(rid=rid, olderUID=pastUID)
</del><ins>+ try:
+ olderObject = yield self.split(rid=rid, olderUID=pastUID)
+ except (UIDExistsError, UIDExistsElsewhereError):
+ raise InvalidSplit("Chosen UID exists elsewhere.")
</ins><span class="cx"> returnValue(olderObject)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -4747,7 +4785,7 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> # First job is to grab a UID lock on this entire series of events
</span><del>- yield NamedLock.acquire(self._txn, "ImplicitUIDLock:{0}".format(hashlib.md5(self._uid).hexdigest(),))
</del><ins>+ yield self._lockUID(self._uid, internal_state=ComponentUpdateState.SPLIT_OWNER)
</ins><span class="cx">
</span><span class="cx"> # Find all other calendar objects on this server with the same UID
</span><span class="cx"> if onlyThis:
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcaldavdatastoretesttest_sqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/test/test_sql.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/test/test_sql.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/caldav/datastore/test/test_sql.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -5455,7 +5455,10 @@
</span><span class="cx">
</span><span class="cx"> responses = ScheduleResponseQueue("REQUEST", responsecode.OK)
</span><span class="cx"> for recipient in recipients:
</span><del>- responses.add(recipient, responsecode.OK, reqstatus=iTIPRequestStatus.MESSAGE_DELIVERED)
</del><ins>+ if recipient.startswith("urn:x-uid"):
+ responses.add(recipient, responsecode.OK, reqstatus=iTIPRequestStatus.MESSAGE_DELIVERED)
+ else:
+ responses.add(recipient, responsecode.NOT_FOUND, reqstatus=iTIPRequestStatus.INVALID_CALENDAR_USER)
</ins><span class="cx"> return succeed(responses)
</span><span class="cx">
</span><span class="cx"> component = Component.fromString(data % self.subs)
</span><span class="lines">@@ -6867,13 +6870,13 @@
</span><span class="cx">
</span><span class="cx"> # Get the existing and new object data
</span><span class="cx"> cobj1 = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
</span><del>- self.assertTrue(cobj1.isScheduleObject)
</del><ins>+ self.assertFalse(cobj1.isScheduleObject)
</ins><span class="cx"> ical1 = yield cobj1.component()
</span><span class="cx"> relID = ical1.masterComponent().propertyValue("RELATED-TO")
</span><span class="cx">
</span><span class="cx"> cobj2 = yield self.calendarObjectUnderTest(name=oldname, calendar_name="calendar", home="user01")
</span><span class="cx"> self.assertTrue(cobj2 is not None)
</span><del>- self.assertTrue(cobj2.isScheduleObject)
</del><ins>+ self.assertFalse(cobj2.isScheduleObject)
</ins><span class="cx"> ical2 = yield cobj2.component()
</span><span class="cx"> newUID = ical2.masterComponent().propertyValue("UID")
</span><span class="cx">
</span><span class="lines">@@ -7013,7 +7016,57 @@
</span><span class="cx"> self.assertEqual(normalize_iCalStr(ical_inbox), normalize_iCalStr(data_inbox2) % relsubs, "Failed inbox: %s" % (title,))
</span><span class="cx">
</span><span class="cx">
</span><ins>+ @inlineCallbacks
+ def test_calendarObjectSplit_splitat_no_same_uid(self):
+ """
+ Test that user triggered splitting of calendar objects does not work if the specified UID is the same
+ as the resource being split.
+ """
</ins><span class="cx">
</span><ins>+ yield self._setupSplitAt()
+
+ # Update it
+ cobj = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
+ yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText("%(now_back14)s" % self.subs), pastUID="12345-67890"), InvalidSplit)
+
+
+ @inlineCallbacks
+ def test_calendarObjectSplit_splitat_no_existing_uid(self):
+ """
+ Test that user triggered splitting of calendar objects does not work if the specified UID is the same
+ as another resource.
+ """
+
+ data_existing = """BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VEVENT
+UID:12345-67890-existing
+DTSTART:%(now_back28)s
+DURATION:PT1H
+DTSTAMP:20051222T210507Z
+RRULE:FREQ=DAILY;COUNT=50
+SUMMARY:1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+ 1234567890123456789012345678901234567890
+END:VEVENT
+END:VCALENDAR
+"""
+
+ yield self._setupSplitAt()
+
+ calendar = yield self.calendarUnderTest(name="calendar", home="user01")
+ component = Component.fromString(data_existing % self.subs)
+ yield calendar.createCalendarObjectWithName("data2.ics", component)
+ yield self.commit()
+
+ # Update it
+ cobj = yield self.calendarObjectUnderTest(name="data1.ics", calendar_name="calendar", home="user01")
+ yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText("%(now_back14)s" % self.subs), pastUID="12345-67890-existing"), InvalidSplit)
+
+
+
</ins><span class="cx"> class TimeRangeUpdateOptimization(CommonCommonTests, unittest.TestCase):
</span><span class="cx"> """
</span><span class="cx"> CalendarObject time range optimization tests.
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxdavcommondatastoretestutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/common/datastore/test/util.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/common/datastore/test/util.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txdav/common/datastore/test/util.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -262,6 +262,7 @@
</span><span class="cx"> reactor, store.newTransaction, None, useWorkerPool=False
</span><span class="cx"> )
</span><span class="cx"> store.queuer = store.queuer.transferProposalCallbacks(pool)
</span><ins>+ store.pool = pool
</ins><span class="cx"> pool.startService()
</span><span class="cx">
</span><span class="cx"> returnValue(store)
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboopod2podmigrationtxweb2davresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/pod2pod-migration/txweb2/dav/resource.py (14381 => 14382)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/pod2pod-migration/txweb2/dav/resource.py        2015-02-06 01:31:25 UTC (rev 14381)
+++ CalendarServer/branches/users/cdaboo/pod2pod-migration/txweb2/dav/resource.py        2015-02-06 19:17:54 UTC (rev 14382)
</span><span class="lines">@@ -706,7 +706,7 @@
</span><span class="cx"> def gotChildren(listChildrenResult):
</span><span class="cx"> children[:] = list(listChildrenResult)
</span><span class="cx"> getChild()
</span><del>- maybeDeferred(self.listChildren).addCallback(gotChildren)
</del><ins>+ maybeDeferred(self.listChildren).addCallback(gotChildren).addErrback(completionDeferred.errback)
</ins><span class="cx">
</span><span class="cx"> return completionDeferred
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>