<!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>[15430] CalendarServer/trunk</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/15430">15430</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2016-01-08 13:03:23 -0800 (Fri, 08 Jan 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Refactoring of calendar-specific code from contrib.performance.loadtest.  Requires use of ClientLoadSimulator project.</pre>

<h3>Added Paths</h3>
<ul>
<li><a href="#CalendarServertrunkbinnewsim">CalendarServer/trunk/bin/newsim</a></li>
<li>CalendarServer/trunk/simplugin/</li>
<li><a href="#CalendarServertrunksimplugin__init__py">CalendarServer/trunk/simplugin/__init__.py</a></li>
<li><a href="#CalendarServertrunksimplugincaldavclientpy">CalendarServer/trunk/simplugin/caldavclient.py</a></li>
<li><a href="#CalendarServertrunksimplugincaldavprofilepy">CalendarServer/trunk/simplugin/caldavprofile.py</a></li>
<li><a href="#CalendarServertrunksimpluginclientsplist">CalendarServer/trunk/simplugin/clients.plist</a></li>
<li><a href="#CalendarServertrunksimpluginconfigplist">CalendarServer/trunk/simplugin/config.plist</a></li>
<li>CalendarServer/trunk/simplugin/request-data/</li>
<li>CalendarServer/trunk/simplugin/request-data/OS_X_10_11/</li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11Profile">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/Profile</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11StartupProfile">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/StartupProfile</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11notification_multiget_report_hrefsrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/notification_multiget_report_hrefs.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11notification_syncrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/notification_sync.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11poll_calendar_depth1_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendar_depth1_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11poll_calendar_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendar_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11poll_calendarhome_depth1_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendarhome_depth1_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11poll_calendarhome_syncrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendarhome_sync.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11poll_notification_depth1_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_notification_depth1_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11post_freebusyrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/post_freebusy.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11principal_search_reportrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/principal_search_report.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11report_principal_searchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/report_principal_search.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_color_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_color_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_description_proppatchrequestxml">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_description_proppatch.request.xml</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_displayname_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_displayname_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_order_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_order_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_timezone_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_timezone_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_transparent_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_transparent_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendarhome_default_alarm_date_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendarhome_default_alarm_date_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendarhome_default_alarm_datetime_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendarhome_default_alarm_datetime_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_create_calendarrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_create_calendar.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_delegate_principal_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_delegate_principal_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_principal_expandrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_expand.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_principal_initial_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_initial_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_principal_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_principals_reportrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principals_report.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_query_events_depth1_reportrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_query_events_depth1_report.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_11startup_well_known_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_well_known_propfind.request</a></li>
<li>CalendarServer/trunk/simplugin/request-data/OS_X_10_6/</li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6poll_calendar_multigetrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_multiget.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6poll_calendar_multiget_hrefsrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_multiget_hrefs.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6poll_calendar_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6poll_calendar_propfind_d1request">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_propfind_d1.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6poll_calendarhome_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendarhome_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6poll_notification_propfind_d1request">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_notification_propfind_d1.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6post_availabilityrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/post_availability.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6startup_calendar_color_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_color_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6startup_calendar_order_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_order_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6startup_calendar_timezone_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_timezone_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6startup_notification_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_notification_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6startup_principal_expandrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_expand.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6startup_principal_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6startup_principal_propfind_initialrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_propfind_initial.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6startup_principals_reportrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principals_report.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6startup_well_knownrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_well_known.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_6user_list_principal_property_searchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_6/user_list_principal_property_search.request</a></li>
<li>CalendarServer/trunk/simplugin/request-data/OS_X_10_7/</li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7Profile">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/Profile</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendar_multigetrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_multiget.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendar_multiget_hrefsrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_multiget_hrefs.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendar_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendar_propfind_d1request">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_propfind_d1.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendar_syncrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_sync.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendarhome_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendarhome_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7poll_notification_propfind_d1request">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_notification_propfind_d1.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7post_availabilityrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/post_availability.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7startup_calendar_color_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_color_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7startup_calendar_order_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_order_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7startup_calendar_timezone_proppatchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_timezone_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7startup_delegate_principal_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_delegate_principal_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7startup_principal_expandrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_expand.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7startup_principal_propfindrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7startup_principal_propfind_initialrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_propfind_initial.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7startup_principals_reportrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principals_report.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7startup_well_knownrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_well_known.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataOS_X_10_7user_list_principal_property_searchrequest">CalendarServer/trunk/simplugin/request-data/OS_X_10_7/user_list_principal_property_search.request</a></li>
<li>CalendarServer/trunk/simplugin/request-data/iOS_5/</li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5Profile">CalendarServer/trunk/simplugin/request-data/iOS_5/Profile</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_multigetrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_multiget.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_multiget_hrefsrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_multiget_hrefs.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_propfindrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_propfind_d1request">CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_propfind_d1.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_vevent_tr_queryrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_vevent_tr_query.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_vtodo_queryrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_vtodo_query.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5poll_calendarhome_propfindrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendarhome_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5startup_calendar_color_proppatchrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/startup_calendar_color_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5startup_calendar_order_proppatchrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/startup_calendar_order_proppatch.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5startup_principal_propfindrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principal_propfind.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5startup_principal_propfind_initialrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principal_propfind_initial.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5startup_principals_reportrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principals_report.request</a></li>
<li><a href="#CalendarServertrunksimpluginrequestdataiOS_5startup_well_knownrequest">CalendarServer/trunk/simplugin/request-data/iOS_5/startup_well_known.request</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunkbinnewsim"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/bin/newsim (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/bin/newsim                                (rev 0)
+++ CalendarServer/trunk/bin/newsim        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+#!/bin/sh
+# -*- sh-basic-offset: 2 -*-
+
+##
+# Copyright (c) 2005-2016 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+set -e;
+set -u;
+
+wd=&quot;$(cd &quot;$(dirname &quot;$0&quot;)/..&quot; &amp;&amp; pwd -L)&quot;;
+
+. &quot;${wd}/bin/_build.sh&quot;;
+
+do_setup=&quot;false&quot;;
+develop &gt; /dev/null;
+
+exec &quot;${python}&quot; &quot;${wd}/clientsim/framework/sim.py&quot; &quot;--config=simplugin/config.plist&quot; &quot;--clients=simplugin/clients.plist&quot; &quot;$@&quot;;
</ins><span class="cx">Property changes on: CalendarServer/trunk/bin/newsim
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="CalendarServertrunksimplugin__init__py"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/__init__.py (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/__init__.py                                (rev 0)
+++ CalendarServer/trunk/simplugin/__init__.py        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,15 @@
</span><ins>+##
+# Copyright (c) 2012-2016 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
</ins></span></pre></div>
<a id="CalendarServertrunksimplugincaldavclientpy"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/caldavclient.py (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/caldavclient.py                                (rev 0)
+++ CalendarServer/trunk/simplugin/caldavclient.py        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2326 @@
</span><ins>+##
+# Copyright (c) 2010-2016 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+##
+from __future__ import print_function
+
+from caldavclientlibrary.protocol.caldav.definitions import caldavxml
+from caldavclientlibrary.protocol.caldav.definitions import csxml
+from caldavclientlibrary.protocol.calendarserver.invite import AddInvitees, RemoveInvitee, InviteUser
+from caldavclientlibrary.protocol.calendarserver.notifications import InviteNotification
+from caldavclientlibrary.protocol.url import URL
+from caldavclientlibrary.protocol.utils.xmlhelpers import BetterElementTree
+from caldavclientlibrary.protocol.webdav.definitions import davxml
+from caldavclientlibrary.protocol.webdav.propfindparser import PropFindParser
+
+from push.amppush import subscribeToIDs
+
+from clientsim.framework.httpclient import StringProducer, readBody
+from clientsim.framework.subscribe import Periodical
+
+from clientsim.framework.baseclient import (
+    IncorrectResponseCode, u2str, BaseClient
+)
+
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+from pycalendar.timezone import Timezone
+
+from twisted.internet.defer import Deferred, inlineCallbacks, returnValue, \
+    succeed
+from twisted.internet.task import LoopingCall
+from twisted.python.log import msg
+from twisted.python.util import FancyEqMixin
+from twisted.web.http import (
+    OK, MULTI_STATUS, CREATED, NO_CONTENT, PRECONDITION_FAILED,
+    MOVED_PERMANENTLY, FORBIDDEN, FOUND, NOT_FOUND
+)
+from twisted.web.http_headers import Headers
+
+from twistedcaldav.ical import Component, Property
+
+from urlparse import urlparse, urlsplit, urljoin
+from uuid import uuid4
+from xml.etree.ElementTree import ElementTree, Element, SubElement, QName
+
+from StringIO import StringIO
+
+import json
+import os
+import random
+import shutil
+
+from twisted.python.filepath import FilePath
+
+
+QName.__repr__ = lambda self: '&lt;QName %r&gt;' % (self.text,)
+
+
+
+SUPPORTED_REPORT_SET = '{DAV:}supported-report-set'
+
+def loadRequestBody(clientType, label):
+    return FilePath(__file__).sibling('request-data').child(clientType).child(label + '.request').getContent()
+
+
+class MissingCalendarHome(Exception):
+    &quot;&quot;&quot;
+    Raised when the calendar home for a user is 404
+    &quot;&quot;&quot;
+
+
+
+class XMPPPush(object, FancyEqMixin):
+    &quot;&quot;&quot;
+    This represents an XMPP PubSub location where push notifications for
+    particular calendar home might be received.
+    &quot;&quot;&quot;
+    compareAttributes = ('server', 'uri', 'pushkey')
+
+    def __init__(self, server, uri, pushkey):
+        self.server = server
+        self.uri = uri
+        self.pushkey = pushkey
+
+
+
+
+class Event(object):
+    def __init__(self, serializeBasePath, url, etag, component=None):
+        self.serializeBasePath = serializeBasePath
+        self.url = url
+        self.etag = etag
+        self.scheduleTag = None
+        if component is not None:
+            self.component = component
+        self.uid = component.resourceUID() if component is not None else None
+
+
+    def getUID(self):
+        &quot;&quot;&quot;
+        Return the UID of the calendar resource.
+        &quot;&quot;&quot;
+        return self.uid
+
+
+    def serializePath(self):
+        if self.serializeBasePath:
+            calendar = os.path.join(self.serializeBasePath, self.url.split(&quot;/&quot;)[-2])
+            if not os.path.exists(calendar):
+                os.makedirs(calendar)
+            return os.path.join(calendar, self.url.split(&quot;/&quot;)[-1])
+        else:
+            return None
+
+
+    def serialize(self):
+        &quot;&quot;&quot;
+        Create a dict of the data so we can serialize as JSON.
+        &quot;&quot;&quot;
+
+        result = {}
+        for attr in (&quot;url&quot;, &quot;etag&quot;, &quot;scheduleTag&quot;, &quot;uid&quot;,):
+            result[attr] = getattr(self, attr)
+        return result
+
+
+    @staticmethod
+    def deserialize(serializeLocation, data):
+        &quot;&quot;&quot;
+        Convert dict (deserialized from JSON) into an L{Event}.
+        &quot;&quot;&quot;
+
+        event = Event(serializeLocation, None, None)
+        for attr in (&quot;url&quot;, &quot;etag&quot;, &quot;scheduleTag&quot;, &quot;uid&quot;,):
+            setattr(event, attr, u2str(data[attr]))
+        return event
+
+
+    @property
+    def component(self):
+        &quot;&quot;&quot;
+        Data always read from disk - never cached in the object.
+        &quot;&quot;&quot;
+        path = self.serializePath()
+        if path and os.path.exists(path):
+            with open(path) as f:
+                comp = Component.fromString(f.read())
+            return comp
+        else:
+            return None
+
+
+    @component.setter
+    def component(self, component):
+        &quot;&quot;&quot;
+        Data always written to disk - never cached on the object.
+        &quot;&quot;&quot;
+        path = self.serializePath()
+        if path:
+            if component is None:
+                os.remove(path)
+            else:
+                with open(path, &quot;w&quot;) as f:
+                    f.write(str(component))
+        self.uid = component.resourceUID() if component is not None else None
+
+
+    def removed(self):
+        &quot;&quot;&quot;
+        Resource no longer exists on the server - remove associated data.
+        &quot;&quot;&quot;
+        path = self.serializePath()
+        if path and os.path.exists(path):
+            os.remove(path)
+
+
+
+class Calendar(object):
+    def __init__(
+        self, resourceType, componentTypes, name, url, changeToken,
+        shared=False, sharedByMe=False
+    ):
+        self.resourceType = resourceType
+        self.componentTypes = componentTypes
+        self.name = name
+        self.url = url
+        self.changeToken = changeToken
+        self.events = {}
+        self.shared = shared
+        self.sharedByMe = sharedByMe
+
+        if self.name is None and self.url is not None:
+            self.name = self.url.rstrip(&quot;/&quot;).split(&quot;/&quot;)[-1]
+
+
+    def serialize(self):
+        &quot;&quot;&quot;
+        Create a dict of the data so we can serialize as JSON.
+        &quot;&quot;&quot;
+
+        result = {}
+        for attr in (&quot;resourceType&quot;, &quot;name&quot;, &quot;url&quot;, &quot;changeToken&quot;, &quot;shared&quot;, &quot;sharedByMe&quot;):
+            result[attr] = getattr(self, attr)
+        result[&quot;componentTypes&quot;] = list(sorted(self.componentTypes))
+        result[&quot;events&quot;] = sorted(self.events.keys())
+        return result
+
+
+    @staticmethod
+    def deserialize(data, events):
+        &quot;&quot;&quot;
+        Convert dict (deserialized from JSON) into an L{Calendar}.
+        &quot;&quot;&quot;
+
+        calendar = Calendar(None, None, None, None, None)
+        for attr in (&quot;resourceType&quot;, &quot;name&quot;, &quot;url&quot;, &quot;changeToken&quot;, &quot;shared&quot;, &quot;sharedByMe&quot;):
+            setattr(calendar, attr, u2str(data[attr]))
+        calendar.componentTypes = set(map(u2str, data[&quot;componentTypes&quot;]))
+
+        for event in data[&quot;events&quot;]:
+            url = urljoin(calendar.url, event)
+            if url in events:
+                calendar.events[event] = events[url]
+            else:
+                # Ughh - an event is missing - force changeToken to empty to trigger full resync
+                calendar.changeToken = &quot;&quot;
+        return calendar
+
+
+    @staticmethod
+    def addInviteeXML(uid, summary, readwrite=True):
+        return AddInvitees(None, '/', [uid], readwrite, summary=summary).request_data.text
+
+
+    @staticmethod
+    def removeInviteeXML(uid):
+        invitee = InviteUser()
+        # Usually an InviteUser is populated through .parseFromUser, but we only care about a uid
+        invitee.user_uid = uid
+        return RemoveInvitee(None, '/', invitee).request_data.text
+
+
+
+class NotificationCollection(object):
+    def __init__(self, url, changeToken):
+        self.url = url
+        self.changeToken = changeToken
+        self.notifications = {}
+        self.name = &quot;notification&quot;
+
+
+    def serialize(self):
+        &quot;&quot;&quot;
+        Create a dict of the data so we can serialize as JSON.
+        &quot;&quot;&quot;
+
+        result = {}
+        for attr in (&quot;url&quot;, &quot;changeToken&quot;):
+            result[attr] = getattr(self, attr)
+        result[&quot;notifications&quot;] = sorted(self.notifications.keys())
+        return result
+
+
+    @staticmethod
+    def deserialize(data, notifications):
+        &quot;&quot;&quot;
+        Convert dict (deserialized from JSON) into an L{Calendar}.
+        &quot;&quot;&quot;
+
+        coll = NotificationCollection(None, None)
+        for attr in (&quot;url&quot;, &quot;changeToken&quot;):
+            if attr in data:
+                setattr(coll, attr, u2str(data[attr]))
+
+        if &quot;notifications&quot; in data:
+            for notification in data[&quot;notifications&quot;]:
+                url = urljoin(coll.url, notification)
+                if url in notifications:
+                    coll.notifications[notification] = notifications[url]
+                else:
+                    # Ughh - a notification is missing - force changeToken to empty to trigger full resync
+                    coll.changeToken = &quot;&quot;
+        return coll
+
+
+
+
+
+class BaseAppleClient(BaseClient):
+    &quot;&quot;&quot;
+    Implementation of common OS X/iOS client behavior.
+    &quot;&quot;&quot;
+
+    _events = None                  # Cache of events keyed by href
+    _calendars = None               # Cache of calendars keyed by href
+    _notificationCollection = None  # Cache of the notification collection
+
+    # The default interval, used if none is specified in external
+    # configuration.
+    CALENDAR_HOME_POLL_INTERVAL = 15 * 60
+
+    # The maximum number of resources to retrieve in a single multiget
+    MULTIGET_BATCH_SIZE = 200
+
+    # Override and turn on if client supports Sync REPORT
+    _SYNC_REPORT = False
+
+    # Override and turn on if client syncs using time-range queries
+    _SYNC_TIMERANGE = False
+
+    # Override and turn off if client does not support attendee lookups
+    _ATTENDEE_LOOKUPS = True
+
+    # Request body data
+    _LOAD_PATH = None
+
+    _STARTUP_WELL_KNOWN = None
+    _STARTUP_PRINCIPAL_PROPFIND_INITIAL = None
+    _STARTUP_PRINCIPAL_PROPFIND = None
+    _STARTUP_PRINCIPALS_REPORT = None
+    _STARTUP_PRINCIPAL_EXPAND = None
+    _STARTUP_PROPPATCH_CALENDAR_COLOR = None
+    _STARTUP_PROPPATCH_CALENDAR_ORDER = None
+    _STARTUP_PROPPATCH_CALENDAR_TIMEZONE = None
+
+    _POLL_CALENDARHOME_PROPFIND = None
+    _POLL_CALENDAR_PROPFIND = None
+    _POLL_CALENDAR_PROPFIND_D1 = None
+    _POLL_CALENDAR_MULTIGET_REPORT = None
+    _POLL_CALENDAR_MULTIGET_REPORT_HREF = None
+    _POLL_CALENDAR_SYNC_REPORT = None
+    _POLL_NOTIFICATION_PROPFIND = None
+    _POLL_NOTIFICATION_PROPFIND_D1 = None
+
+    _NOTIFICATION_SYNC_REPORT = None
+
+    _USER_LIST_PRINCIPAL_PROPERTY_SEARCH = None
+    _POST_AVAILABILITY = None
+
+    _CALENDARSERVER_PRINCIPAL_SEARCH_REPORT = None
+
+    email = None
+
+    def __init__(
+        self,
+        reactor,
+        server,
+        serializePath,
+        record,
+        auth,
+        title=None,
+        calendarHomePollInterval=None,
+        supportPush=True,
+        supportAmpPush=True,
+        principalPathTemplate=&quot;/principals/users/{}/&quot;,
+    ):
+        super(BaseAppleClient, self).__init__(
+            reactor, server, serializePath, record, auth, title=title
+        )
+
+        self.principalPathTemplate = principalPathTemplate
+
+        if calendarHomePollInterval is None:
+            calendarHomePollInterval = self.CALENDAR_HOME_POLL_INTERVAL
+        self.calendarHomePollInterval = calendarHomePollInterval
+
+        self.calendarHomeHref = None
+
+        self.supportPush = supportPush
+
+        self.supportAmpPush = supportAmpPush
+        ampPushHosts = self.server.get(&quot;ampPushHosts&quot;)
+        if ampPushHosts is None:
+            ampPushHosts = [urlparse(self.server[&quot;uri&quot;])[1].split(&quot;:&quot;)[0]]
+        self.ampPushHosts = ampPushHosts
+        self.ampPushPort = self.server.get(&quot;ampPushPort&quot;, 62311)
+
+        self.serializePath = serializePath
+
+        self.supportSync = self._SYNC_REPORT
+        self.supportNotificationSync = self._NOTIFICATION_SYNC_REPORT
+
+        self.supportEnhancedAttendeeAutoComplete = self._CALENDARSERVER_PRINCIPAL_SEARCH_REPORT
+
+        # Keep track of the calendars on this account, keys are
+        # Calendar URIs, values are Calendar instances.
+        self._calendars = {}
+
+        # The principalURL found during discovery
+        self.principalURL = None
+
+        # The principal collection found during startup
+        self.principalCollection = None
+
+        # Keep track of the events on this account, keys are event
+        # URIs (which are unambiguous across different calendars
+        # because they start with the uri of the calendar they are
+        # part of), values are Event instances.
+        self._events = {}
+
+        # Keep track of which calendar homes are being polled
+        self._checking = set()
+
+        # Keep track of XMPP parameters for calendar homes we encounter.  This
+        # dictionary has calendar home URLs as keys and XMPPPush instances as
+        # values.
+        self.xmpp = {}
+
+        self.ampPushKeys = {}
+
+        # Keep track of push factories so we can unsubscribe at shutdown
+        self._pushFactories = []
+
+        # Allow events to go out into the world.
+        self.catalog = {
+            &quot;eventChanged&quot;: Periodical(),
+        }
+
+        # Keep track of previously downloaded attachments
+        self._attachments = {}
+
+
+    def _setEvent(self, href, event):
+        &quot;&quot;&quot;
+        Cache the provided event
+        &quot;&quot;&quot;
+        self._events[href] = event
+        calendar, basePath = href.rsplit('/', 1)
+        self._calendars[calendar + '/'].events[basePath] = event
+
+
+    def _removeEvent(self, href):
+        &quot;&quot;&quot;
+        Remove event from local cache.
+        &quot;&quot;&quot;
+        self._events[href].removed()
+        del self._events[href]
+        calendar, basePath = href.rsplit('/', 1)
+        del self._calendars[calendar + '/'].events[basePath]
+
+
+
+    def _addDefaultHeaders(self, headers):
+        &quot;&quot;&quot;
+        Add the clients default set of headers to ones being used in a request.
+        Default is to add User-Agent, sub-classes should override to add other
+        client specific things, Accept etc.
+        &quot;&quot;&quot;
+        headers.setRawHeaders('User-Agent', [self.USER_AGENT])
+
+
+    @inlineCallbacks
+    def _request(self, expectedResponseCodes, method, url, headers=None, body=None, method_label=None):
+        &quot;&quot;&quot;
+        Execute a request and check against the expected response codes.
+        &quot;&quot;&quot;
+        if type(expectedResponseCodes) is int:
+            expectedResponseCodes = (expectedResponseCodes,)
+        if headers is None:
+            headers = Headers({})
+        self._addDefaultHeaders(headers)
+        msg(
+            type=&quot;request&quot;,
+            method=method_label if method_label else method,
+            url=url,
+            user=self.record.uid,
+            client_type=self.title,
+            client_id=self._client_id,
+        )
+
+        before = self.reactor.seconds()
+        response = yield self.agent.request(method, url, headers, body)
+
+        # XXX This is time to receive response headers, not time
+        # to receive full response.  Should measure the latter, if
+        # not both.
+        after = self.reactor.seconds()
+
+        success = response.code in expectedResponseCodes
+
+        msg(
+            type=&quot;response&quot;,
+            success=success,
+            method=method_label if method_label else method,
+            headers=headers,
+            body=body,
+            code=response.code,
+            user=self.record.uid,
+            client_type=self.title,
+            client_id=self._client_id,
+            duration=(after - before),
+            url=url,
+        )
+
+        if success:
+            returnValue(response)
+
+        raise IncorrectResponseCode(expectedResponseCodes, response)
+
+
+    def _parseMultiStatus(self, response, otherTokens=False):
+        &quot;&quot;&quot;
+        Parse a &lt;multistatus&gt; - might need to return other top-level elements
+        in the response - e.g. DAV:sync-token
+        I{PROPFIND} request for the principal URL.
+
+        @type response: C{str}
+        @rtype: C{cls}
+        &quot;&quot;&quot;
+        parser = PropFindParser()
+        parser.parseData(response)
+        if otherTokens:
+            return (parser.getResults(), parser.getOthers(),)
+        else:
+            return parser.getResults()
+
+    _CALENDAR_TYPES = set([
+        caldavxml.calendar,
+        caldavxml.schedule_inbox,
+    ])
+
+    @inlineCallbacks
+    def _propfind(self, url, body, depth='0', allowedStatus=(MULTI_STATUS,), method_label=None):
+        &quot;&quot;&quot;
+        Issue a PROPFIND on the chosen URL
+        &quot;&quot;&quot;
+        hdrs = Headers({'content-type': ['text/xml']})
+        if depth is not None:
+            hdrs.addRawHeader('depth', depth)
+        response = yield self._request(
+            allowedStatus,
+            'PROPFIND',
+            self.server[&quot;uri&quot;] + url.encode('utf-8'),
+            hdrs,
+            StringProducer(body),
+            method_label=method_label,
+        )
+
+        body = yield readBody(response)
+        result = self._parseMultiStatus(body) if response.code == MULTI_STATUS else None
+
+        returnValue((response, result,))
+
+
+    @inlineCallbacks
+    def _proppatch(self, url, body, method_label=None):
+        &quot;&quot;&quot;
+        Issue a PROPPATCH on the chosen URL
+        &quot;&quot;&quot;
+        hdrs = Headers({'content-type': ['text/xml']})
+        response = yield self._request(
+            (OK, MULTI_STATUS,),
+            'PROPPATCH',
+            self.server[&quot;uri&quot;] + url.encode('utf-8'),
+            hdrs,
+            StringProducer(body),
+            method_label=method_label,
+        )
+        if response.code == MULTI_STATUS:
+            body = yield readBody(response)
+            result = self._parseMultiStatus(body)
+            returnValue(result)
+        else:
+            returnValue(None)
+
+
+    @inlineCallbacks
+    def _get(self, url, allowedStatus=(MULTI_STATUS,), method_label=None):
+        &quot;&quot;&quot;
+        Issue a GET on the chosen URL
+        &quot;&quot;&quot;
+        response = yield self._request(
+            allowedStatus,
+            'GET',
+            url,
+            method_label=method_label,
+        )
+
+        body = yield readBody(response)
+        returnValue(body)
+
+
+    @inlineCallbacks
+    def _report(self, url, body, depth='0', allowedStatus=(MULTI_STATUS,), otherTokens=False, method_label=None):
+        &quot;&quot;&quot;
+        Issue a REPORT on the chosen URL
+        &quot;&quot;&quot;
+        hdrs = Headers({'content-type': ['text/xml']})
+        if depth is not None:
+            hdrs.addRawHeader('depth', depth)
+        response = yield self._request(
+            allowedStatus,
+            'REPORT',
+            self.server[&quot;uri&quot;] + url.encode('utf-8'),
+            hdrs,
+            StringProducer(body),
+            method_label=method_label,
+        )
+
+        body = yield readBody(response)
+        result = self._parseMultiStatus(body, otherTokens) if response.code == MULTI_STATUS else None
+
+        returnValue(result)
+
+
+    @inlineCallbacks
+    def _startupPropfindWellKnown(self):
+        &quot;&quot;&quot;
+        Issue a PROPFIND on the /.well-known/caldav/ URL
+        &quot;&quot;&quot;
+
+        location = &quot;/.well-known/caldav/&quot;
+        response, result = yield self._propfind(
+            location,
+            self._STARTUP_WELL_KNOWN,
+            allowedStatus=(MULTI_STATUS, MOVED_PERMANENTLY, FOUND,),
+            method_label=&quot;PROPFIND{well-known}&quot;,
+        )
+
+        # Follow any redirect
+        if response.code in (MOVED_PERMANENTLY, FOUND,):
+            location = response.headers.getRawHeaders(&quot;location&quot;)[0]
+            location = urlsplit(location)[2]
+            response, result = yield self._propfind(
+                location,
+                self._STARTUP_WELL_KNOWN,
+                allowedStatus=(MULTI_STATUS),
+                method_label=&quot;PROPFIND{well-known}&quot;,
+            )
+
+        returnValue(result[location])
+
+
+    @inlineCallbacks
+    def _principalPropfindInitial(self, user):
+        &quot;&quot;&quot;
+        Issue a PROPFIND on the /principals/users/&lt;uid&gt; URL to retrieve
+        the /principals/__uids__/&lt;guid&gt; principal URL
+        &quot;&quot;&quot;
+        principalPath = self.principalPathTemplate.format(user)
+        _ignore_response, result = yield self._propfind(
+            principalPath,
+            self._STARTUP_PRINCIPAL_PROPFIND_INITIAL,
+            method_label=&quot;PROPFIND{find-principal}&quot;,
+        )
+        returnValue(result[principalPath])
+
+
+    @inlineCallbacks
+    def _principalPropfind(self):
+        &quot;&quot;&quot;
+        Issue a PROPFIND on the likely principal URL for the given
+        user and return a L{Principal} instance constructed from the
+        response.
+        &quot;&quot;&quot;
+        _ignore_response, result = yield self._propfind(
+            self.principalURL,
+            self._STARTUP_PRINCIPAL_PROPFIND,
+            method_label=&quot;PROPFIND{principal}&quot;,
+        )
+        returnValue(result[self.principalURL])
+
+
+    def _principalSearchPropertySetReport(self, principalCollectionSet):
+        &quot;&quot;&quot;
+        Issue a principal-search-property-set REPORT against the chosen URL
+        &quot;&quot;&quot;
+        return self._report(
+            principalCollectionSet,
+            self._STARTUP_PRINCIPALS_REPORT,
+            allowedStatus=(OK,),
+            method_label=&quot;REPORT{pset}&quot;,
+        )
+
+
+    @inlineCallbacks
+    def _calendarHomePropfind(self, calendarHomeSet):
+        &quot;&quot;&quot;
+        Do the poll Depth:1 PROPFIND on the calendar home.
+        &quot;&quot;&quot;
+        if not calendarHomeSet.endswith('/'):
+            calendarHomeSet = calendarHomeSet + '/'
+        _ignore_response, result = yield self._propfind(
+            calendarHomeSet,
+            self._POLL_CALENDARHOME_PROPFIND,
+            depth='1',
+            method_label=&quot;PROPFIND{home}&quot;,
+        )
+        calendars, notificationCollection = self._extractCalendars(
+            result, calendarHomeSet
+        )
+        returnValue((calendars, notificationCollection, result,))
+
+
+    @inlineCallbacks
+    def _extractPrincipalDetails(self):
+        # Using the actual principal URL, retrieve principal information
+        principal = yield self._principalPropfind()
+
+        hrefs = principal.getHrefProperties()
+
+        # Remember our outbox and ignore notifications
+        self.outbox = hrefs[caldavxml.schedule_outbox_URL].toString()
+        self.notificationURL = None
+
+        # Remember our own email-like principal address
+        self.email = None
+        self.uuid = None
+        cuaddrs = hrefs[caldavxml.calendar_user_address_set]
+        if isinstance(cuaddrs, URL):
+            cuaddrs = (cuaddrs,)
+        for cuaddr in cuaddrs:
+            if cuaddr.toString().startswith(u&quot;mailto:&quot;):
+                self.email = cuaddr.toString()
+            elif cuaddr.toString().startswith(u&quot;urn:x-uid&quot;):
+                self.uuid = cuaddr.toString()
+            elif cuaddr.toString().startswith(u&quot;urn:uuid&quot;) and self.uuid is None:
+                self.uuid = cuaddr.toString()
+        if self.email is None:
+            raise ValueError(&quot;Cannot operate without a mail-style principal URL&quot;)
+
+        # Do another kind of thing I guess
+        self.principalCollection = hrefs[davxml.principal_collection_set].toString()
+        yield self._principalSearchPropertySetReport(self.principalCollection)
+
+        returnValue(principal)
+
+
+    def _extractCalendars(self, results, calendarHome=None):
+        &quot;&quot;&quot;
+        Parse a calendar home PROPFIND response and create local state
+        representing the calendars it contains.
+
+        If XMPP push is enabled, also look for and record information about
+        that from the response.
+        &quot;&quot;&quot;
+        calendars = []
+        notificationCollection = None
+
+        changeTag = davxml.sync_token if self.supportSync else csxml.getctag
+
+        for href in results:
+
+            if href == calendarHome:
+                text = results[href].getTextProperties()
+
+                try:
+                    pushkey = text[csxml.pushkey]
+                except KeyError:
+                    pass
+                else:
+                    if pushkey:
+                        self.ampPushKeys[href] = pushkey
+
+                try:
+                    server = text[csxml.xmpp_server]
+                    uri = text[csxml.xmpp_uri]
+                    pushkey = text[csxml.pushkey]
+                except KeyError:
+                    pass
+                else:
+                    if server and uri:
+                        self.xmpp[href] = XMPPPush(server, uri, pushkey)
+
+            nodes = results[href].getNodeProperties()
+            isCalendar = False
+            isNotifications = False
+            isShared = False
+            isSharedByMe = False
+            resourceType = None
+            for nodeType in nodes[davxml.resourcetype]:
+                if nodeType.tag in self._CALENDAR_TYPES:
+                    isCalendar = True
+                    resourceType = nodeType.tag
+                elif nodeType.tag == csxml.notification:
+                    isNotifications = True
+                elif nodeType.tag.startswith(&quot;{http://calendarserver.org/ns/}shared&quot;):
+                    isShared = True
+                    if nodeType.tag == &quot;{http://calendarserver.org/ns/}shared-owner&quot;:
+                        isSharedByMe = True
+
+            if isCalendar:
+                textProps = results[href].getTextProperties()
+                componentTypes = set()
+                if nodeType.tag == caldavxml.calendar:
+                    if caldavxml.supported_calendar_component_set in nodes:
+                        for comp in nodes[caldavxml.supported_calendar_component_set]:
+                            componentTypes.add(comp.get(&quot;name&quot;).upper())
+
+                calendars.append(Calendar(
+                    resourceType,
+                    componentTypes,
+                    textProps.get(davxml.displayname, None),
+                    href,
+                    textProps.get(changeTag, None),
+                    shared=isShared,
+                    sharedByMe=isSharedByMe
+                ))
+
+            elif isNotifications:
+                textProps = results[href].getTextProperties()
+                notificationCollection = NotificationCollection(
+                    href,
+                    textProps.get(changeTag, None)
+                )
+
+        return calendars, notificationCollection
+
+
+    def _updateCalendar(self, calendar, newToken, fetchEvents=True):
+        &quot;&quot;&quot;
+        Update the local cached data for a calendar in an appropriate manner.
+        &quot;&quot;&quot;
+        if self.supportSync:
+            return self._updateCalendar_SYNC(calendar, newToken, fetchEvents=fetchEvents)
+        else:
+            return self._updateCalendar_PROPFIND(calendar, newToken)
+
+
+    @inlineCallbacks
+    def _updateCalendar_PROPFIND(self, calendar, newToken):
+        &quot;&quot;&quot;
+        Sync a collection by doing a full PROPFIND Depth:1 on it and then sync
+        the results with local cached data.
+        &quot;&quot;&quot;
+
+        # Grab old hrefs prior to the PROPFIND so we sync with the old state. We need this because
+        # the sim can fire a PUT between the PROPFIND and when process the removals.
+        old_hrefs = set([calendar.url + child for child in calendar.events.keys()])
+
+        _ignore_response, result = yield self._propfind(
+            calendar.url,
+            self._POLL_CALENDAR_PROPFIND_D1,
+            depth='1',
+            method_label=&quot;PROPFIND{calendar}&quot;
+        )
+
+        yield self._updateApplyChanges(calendar, result, old_hrefs)
+
+        # Now update calendar to the new token
+        self._calendars[calendar.url].changeToken = newToken
+
+
+    @inlineCallbacks
+    def _updateCalendar_SYNC(self, calendar, newToken, fetchEvents=True):
+        &quot;&quot;&quot;
+        Execute a sync REPORT against a calendar and apply changes to the local cache.
+        The new token from the changed collection is passed in and must be applied to
+        the existing calendar once sync is done.
+        &quot;&quot;&quot;
+
+        # Grab old hrefs prior to the REPORT so we sync with the old state. We need this because
+        # the sim can fire a PUT between the REPORT and when process the removals.
+        old_hrefs = set([calendar.url + child for child in calendar.events.keys()])
+
+        # Get changes from sync REPORT (including the other nodes at the top-level
+        # which will have the new sync token.
+        fullSync = not calendar.changeToken
+        result = yield self._report(
+            calendar.url,
+            self._POLL_CALENDAR_SYNC_REPORT % {'sync-token': calendar.changeToken},
+            depth='1',
+            allowedStatus=(MULTI_STATUS, FORBIDDEN,),
+            otherTokens=True,
+            method_label=&quot;REPORT{sync}&quot; if calendar.changeToken else &quot;REPORT{sync-init}&quot;,
+        )
+        if result is None:
+            if not fullSync:
+                fullSync = True
+                result = yield self._report(
+                    calendar.url,
+                    self._POLL_CALENDAR_SYNC_REPORT % {'sync-token': ''},
+                    depth='1',
+                    otherTokens=True,
+                    method_label=&quot;REPORT{sync}&quot; if calendar.changeToken else &quot;REPORT{sync-init}&quot;,
+                )
+            else:
+                raise IncorrectResponseCode((MULTI_STATUS,), None)
+
+        result, others = result
+
+        if fetchEvents:
+            changed = []
+            for responseHref in result:
+                if responseHref == calendar.url:
+                    continue
+
+                try:
+                    etag = result[responseHref].getTextProperties()[davxml.getetag]
+                except KeyError:
+                    # XXX Ignore things with no etag?  Seems to be dropbox.
+                    continue
+
+                # Differentiate a remove vs new/update result
+                if result[responseHref].getStatus() / 100 == 2:
+                    if responseHref not in self._events:
+                        self._setEvent(responseHref, Event(self.serializeLocation(), responseHref, None))
+
+                    event = self._events[responseHref]
+                    if event.etag != etag:
+                        changed.append(responseHref)
+                elif result[responseHref].getStatus() == 404:
+                    self._removeEvent(responseHref)
+
+            yield self._updateChangedEvents(calendar, changed)
+
+            # Handle removals only when doing an initial sync
+            if fullSync:
+                # Detect removed items and purge them
+                remove_hrefs = old_hrefs - set(changed)
+                for href in remove_hrefs:
+                    self._removeEvent(href)
+
+        # Now update calendar to the new token taken from the report
+        for node in others:
+            if node.tag == davxml.sync_token:
+                newToken = node.text
+                break
+        self._calendars[calendar.url].changeToken = newToken
+
+
+    @inlineCallbacks
+    def _updateApplyChanges(self, calendar, multistatus, old_hrefs):
+        &quot;&quot;&quot;
+        Given a multistatus for an entire collection, sync the reported items
+        against the cached items.
+        &quot;&quot;&quot;
+
+        # Detect changes and new items
+        all_hrefs = []
+        changed_hrefs = []
+        for responseHref in multistatus:
+            if responseHref == calendar.url:
+                continue
+            all_hrefs.append(responseHref)
+            try:
+                etag = multistatus[responseHref].getTextProperties()[davxml.getetag]
+            except KeyError:
+                # XXX Ignore things with no etag?  Seems to be dropbox.
+                continue
+
+            if responseHref not in self._events:
+                self._setEvent(responseHref, Event(self.serializeLocation(), responseHref, None))
+
+            event = self._events[responseHref]
+            if event.etag != etag:
+                changed_hrefs.append(responseHref)
+
+        # Retrieve changes
+        yield self._updateChangedEvents(calendar, changed_hrefs)
+
+        # Detect removed items and purge them
+        remove_hrefs = old_hrefs - set(all_hrefs)
+        for href in remove_hrefs:
+            self._removeEvent(href)
+
+
+    @inlineCallbacks
+    def _updateChangedEvents(self, calendar, changed):
+        &quot;&quot;&quot;
+        Given a set of changed hrefs, batch multiget them all to update the
+        local cache.
+        &quot;&quot;&quot;
+
+        changed.sort()
+        while changed:
+            batchedHrefs = changed[:self.MULTIGET_BATCH_SIZE]
+            changed = changed[self.MULTIGET_BATCH_SIZE:]
+
+            multistatus = yield self._eventReport(calendar.url, batchedHrefs)
+            for responseHref in batchedHrefs:
+                try:
+                    res = multistatus[responseHref]
+                except KeyError:
+                    # Resource might have been deleted
+                    continue
+                if res.getStatus() == 200:
+                    text = res.getTextProperties()
+                    etag = text[davxml.getetag]
+                    try:
+                        scheduleTag = text[caldavxml.schedule_tag]
+                    except KeyError:
+                        scheduleTag = None
+                    body = text[caldavxml.calendar_data]
+                    self.eventChanged(responseHref, etag, scheduleTag, body)
+
+
+    def eventChanged(self, href, etag, scheduleTag, body):
+        event = self._events[href]
+        event.etag = etag
+        if scheduleTag is not None:
+            event.scheduleTag = scheduleTag
+        event.component = Component.fromString(body)
+        self.catalog[&quot;eventChanged&quot;].issue(href)
+
+
+    def _eventReport(self, calendar, events):
+        # Next do a REPORT on events that might have information
+        # we don't know about.
+        hrefs = &quot;&quot;.join([self._POLL_CALENDAR_MULTIGET_REPORT_HREF % {'href': event} for event in events])
+
+        label_suffix = &quot;small&quot;
+        if len(events) &gt; 5:
+            label_suffix = &quot;medium&quot;
+        if len(events) &gt; 20:
+            label_suffix = &quot;large&quot;
+        if len(events) &gt; 75:
+            label_suffix = &quot;huge&quot;
+
+        return self._report(
+            calendar,
+            self._POLL_CALENDAR_MULTIGET_REPORT % {'hrefs': hrefs},
+            depth=None,
+            method_label=&quot;REPORT{multiget-%s}&quot; % (label_suffix,),
+        )
+
+
+    @inlineCallbacks
+    def _checkCalendarsForEvents(self, calendarHomeSet, firstTime=False, push=False):
+        &quot;&quot;&quot;
+        The actions a client does when polling for changes, or in response to a
+        push notification of a change. There are some actions done on the first poll
+        we should emulate.
+        &quot;&quot;&quot;
+
+        result = True
+        try:
+            result = yield self._newOperation(&quot;push&quot; if push else &quot;poll&quot;, self._poll(calendarHomeSet, firstTime))
+        finally:
+            if result:
+                try:
+                    self._checking.remove(calendarHomeSet)
+                except KeyError:
+                    pass
+        returnValue(result)
+
+
+    @inlineCallbacks
+    def _updateNotifications(self, oldToken, newToken):
+
+        fullSync = not oldToken
+
+        # Get the list of notification xml resources
+
+        result = yield self._report(
+            self._notificationCollection.url,
+            self._NOTIFICATION_SYNC_REPORT % {'sync-token': oldToken},
+            depth='1',
+            allowedStatus=(MULTI_STATUS, FORBIDDEN,),
+            otherTokens=True,
+            method_label=&quot;REPORT{sync}&quot; if oldToken else &quot;REPORT{sync-init}&quot;,
+        )
+        if result is None:
+            if not fullSync:
+                fullSync = True
+                result = yield self._report(
+                    self._notificationCollection.url,
+                    self._NOTIFICATION_SYNC_REPORT % {'sync-token': ''},
+                    depth='1',
+                    otherTokens=True,
+                    method_label=&quot;REPORT{sync}&quot; if oldToken else &quot;REPORT{sync-init}&quot;,
+                )
+            else:
+                raise IncorrectResponseCode((MULTI_STATUS,), None)
+
+        result, _ignore_others = result
+
+        # Scan for the sharing invites
+        inviteNotifications = []
+        toDelete = []
+        for responseHref in result:
+            if responseHref == self._notificationCollection.url:
+                continue
+
+            # try:
+            #     etag = result[responseHref].getTextProperties()[davxml.getetag]
+            # except KeyError:
+            #     # XXX Ignore things with no etag?  Seems to be dropbox.
+            #     continue
+
+            toDelete.append(responseHref)
+
+            if result[responseHref].getStatus() / 100 == 2:
+                # Get the notification
+                response = yield self._request(
+                    OK,
+                    'GET',
+                    self.server[&quot;uri&quot;] + responseHref.encode('utf-8'),
+                    method_label=&quot;GET{notification}&quot;,
+                )
+                body = yield readBody(response)
+                node = ElementTree(file=StringIO(body)).getroot()
+                if node.tag == str(csxml.notification):
+                    nurl = URL(url=responseHref)
+                    for child in node.getchildren():
+                        if child.tag == str(csxml.invite_notification):
+                            if child.find(str(csxml.invite_noresponse)) is not None:
+                                inviteNotifications.append(
+                                    InviteNotification().parseFromNotification(
+                                        nurl, child
+                                    )
+                                )
+
+        # Accept the invites
+        for notification in inviteNotifications:
+            # Create an invite-reply
+            &quot;&quot;&quot;
+            &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+            &lt;C:invite-reply xmlns:C=&quot;http://calendarserver.org/ns/&quot;&gt;
+              &lt;A:href xmlns:A=&quot;DAV:&quot;&gt;urn:x-uid:10000000-0000-0000-0000-000000000002&lt;/A:href&gt;
+              &lt;C:invite-accepted/&gt;
+              &lt;C:hosturl&gt;
+                &lt;A:href xmlns:A=&quot;DAV:&quot;&gt;/calendars/__uids__/10000000-0000-0000-0000-000000000001/A1DDC58B-651E-4B1C-872A-C6588CA09ADB&lt;/A:href&gt;
+              &lt;/C:hosturl&gt;
+              &lt;C:in-reply-to&gt;d2683fa9-7a50-4390-82bb-cbcea5e0fa86&lt;/C:in-reply-to&gt;
+              &lt;C:summary&gt;to share&lt;/C:summary&gt;
+            &lt;/C:invite-reply&gt;
+            &quot;&quot;&quot;
+            reply = Element(csxml.invite_reply)
+            href = SubElement(reply, davxml.href)
+            href.text = notification.user_uid
+            SubElement(reply, csxml.invite_accepted)
+            hosturl = SubElement(reply, csxml.hosturl)
+            href = SubElement(hosturl, davxml.href)
+            href.text = notification.hosturl
+            inReplyTo = SubElement(reply, csxml.in_reply_to)
+            inReplyTo.text = notification.uid
+            summary = SubElement(reply, csxml.summary)
+            summary.text = notification.summary
+
+            xmldoc = BetterElementTree(reply)
+            os = StringIO()
+            xmldoc.writeUTF8(os)
+            # Post to my calendar home
+            response = yield self.postXML(
+                self.calendarHomeHref,
+                os.getvalue(),
+                &quot;POST{invite-accept}&quot;
+            )
+
+        # Delete all the notification resources
+        for responseHref in toDelete:
+            response = yield self._request(
+                (NO_CONTENT, NOT_FOUND),
+                'DELETE',
+                self.server[&quot;uri&quot;] + responseHref.encode('utf-8'),
+                method_label=&quot;DELETE{invite}&quot;,
+            )
+
+        self._notificationCollection.changeToken = newToken
+
+
+    @inlineCallbacks
+    def _poll(self, calendarHomeSet, firstTime):
+        &quot;&quot;&quot;
+        This gets called during a normal poll or in response to a push
+        &quot;&quot;&quot;
+
+        if calendarHomeSet in self._checking:
+            returnValue(False)
+        self._checking.add(calendarHomeSet)
+
+        calendars, notificationCollection, results = yield self._calendarHomePropfind(calendarHomeSet)
+
+        # First time operations
+        if firstTime:
+            yield self._pollFirstTime1(results[calendarHomeSet], calendars)
+
+        # Normal poll
+        for cal in calendars:
+            newToken = cal.changeToken
+            if cal.url not in self._calendars:
+                # Calendar seen for the first time - reload it
+                self._calendars[cal.url] = cal
+                cal.changeToken = &quot;&quot;
+                # If this is the first time this run and we have no cached copy
+                # of this calendar, do an update but don't fetch the events.
+                # We'll only take notice of ongoing activity and not bother
+                # with existing events.
+                yield self._updateCalendar(
+                    self._calendars[cal.url], newToken,
+                    fetchEvents=(not firstTime)
+                )
+            elif self._calendars[cal.url].changeToken != newToken:
+                # Calendar changed - reload it
+                yield self._updateCalendar(self._calendars[cal.url], newToken)
+
+        if notificationCollection is not None:
+            if self.supportNotificationSync:
+                if self._notificationCollection:
+                    oldToken = self._notificationCollection.changeToken
+                else:
+                    oldToken = &quot;&quot;
+                self._notificationCollection = notificationCollection
+                newToken = notificationCollection.changeToken
+                yield self._updateNotifications(oldToken, newToken)
+            else:
+                # When there is no sync REPORT, clients have to do a full PROPFIND
+                # on the notification collection because there is no ctag
+                self._notificationCollection = notificationCollection
+                yield self._notificationPropfind(self._notificationCollection.url)
+                yield self._notificationChangesPropfind(self._notificationCollection.url)
+
+        # One time delegate expansion
+        if firstTime:
+            yield self._pollFirstTime2()
+
+        returnValue(True)
+
+
+    @inlineCallbacks
+    def _pollFirstTime1(self, homeNode, calendars):
+        # Detect sync report if needed
+        if self.supportSync:
+            nodes = homeNode.getNodeProperties()
+            syncnodes = nodes[davxml.supported_report_set].findall(
+                str(davxml.supported_report) + &quot;/&quot; +
+                str(davxml.report) + &quot;/&quot; +
+                str(davxml.sync_collection)
+            )
+            self.supportSync = len(syncnodes) != 0
+
+        # Patch calendar properties
+        for cal in calendars:
+            if cal.name != &quot;inbox&quot;:
+                yield self._proppatch(
+                    cal.url,
+                    self._STARTUP_PROPPATCH_CALENDAR_COLOR,
+                    method_label=&quot;PROPPATCH{calendar}&quot;,
+                )
+                yield self._proppatch(
+                    cal.url,
+                    self._STARTUP_PROPPATCH_CALENDAR_ORDER,
+                    method_label=&quot;PROPPATCH{calendar}&quot;,
+                )
+                yield self._proppatch(
+                    cal.url,
+                    self._STARTUP_PROPPATCH_CALENDAR_TIMEZONE,
+                    method_label=&quot;PROPPATCH{calendar}&quot;,
+                )
+
+
+    def _pollFirstTime2(self):
+        return self._principalExpand(self.principalURL)
+
+
+    @inlineCallbacks
+    def _notificationPropfind(self, notificationURL):
+        _ignore_response, result = yield self._propfind(
+            notificationURL,
+            self._POLL_NOTIFICATION_PROPFIND,
+            method_label=&quot;PROPFIND{notification}&quot;,
+        )
+        returnValue(result)
+
+
+    @inlineCallbacks
+    def _notificationChangesPropfind(self, notificationURL):
+        _ignore_response, result = yield self._propfind(
+            notificationURL,
+            self._POLL_NOTIFICATION_PROPFIND_D1,
+            depth='1',
+            method_label=&quot;PROPFIND{notification-items}&quot;,
+        )
+        returnValue(result)
+
+
+    @inlineCallbacks
+    def _principalExpand(self, principalURL):
+        result = yield self._report(
+            principalURL,
+            self._STARTUP_PRINCIPAL_EXPAND,
+            depth=None,
+            method_label=&quot;REPORT{expand}&quot;,
+        )
+        returnValue(result)
+
+
+    def startup(self):
+        raise NotImplementedError
+
+
+    def _calendarCheckLoop(self, calendarHome):
+        &quot;&quot;&quot;
+        Periodically check the calendar home for changes to calendars.
+        &quot;&quot;&quot;
+        pollCalendarHome = LoopingCall(
+            self._checkCalendarsForEvents, calendarHome)
+        return pollCalendarHome.start(self.calendarHomePollInterval, now=False)
+
+
+    @inlineCallbacks
+    def _newOperation(self, label, deferred):
+        before = self.reactor.seconds()
+        msg(
+            type=&quot;operation&quot;,
+            phase=&quot;start&quot;,
+            user=self.record.uid,
+            client_type=self.title,
+            client_id=self._client_id,
+            label=label,
+        )
+
+        try:
+            result = yield deferred
+        except IncorrectResponseCode:
+            # Let this through
+            success = False
+            result = None
+        except:
+            # Anything else is fatal
+            raise
+        else:
+            success = True
+
+        after = self.reactor.seconds()
+        msg(
+            type=&quot;operation&quot;,
+            phase=&quot;end&quot;,
+            duration=after - before,
+            user=self.record.uid,
+            client_type=self.title,
+            client_id=self._client_id,
+            label=label,
+            success=success,
+        )
+        returnValue(result)
+
+
+    def _receivedPush(self, inboundID, dataChangedTimestamp, priority=5):
+        for href, id in self.ampPushKeys.iteritems():
+            if inboundID == id:
+                self._checkCalendarsForEvents(href, push=True)
+                break
+        else:
+            # somehow we are not subscribed to this id
+            pass
+
+
+    def _monitorAmpPush(self, home, pushKeys):
+        &quot;&quot;&quot;
+        Start monitoring for AMP-based push notifications
+        &quot;&quot;&quot;
+        for host in self.ampPushHosts:
+            subscribeToIDs(
+                host, self.ampPushPort, pushKeys,
+                self._receivedPush, self.reactor
+            )
+
+
+    @inlineCallbacks
+    def _unsubscribePubSub(self):
+        for factory in self._pushFactories:
+            yield factory.unsubscribeAll()
+
+
+    @inlineCallbacks
+    def run(self):
+        &quot;&quot;&quot;
+        Emulate a CalDAV client.
+        &quot;&quot;&quot;
+        @inlineCallbacks
+        def startup():
+            principal = yield self.startup()
+            hrefs = principal.getHrefProperties()
+            calendarHome = hrefs[caldavxml.calendar_home_set].toString()
+            if calendarHome is None:
+                raise MissingCalendarHome
+            else:
+                self.calendarHomeHref = calendarHome
+            yield self._checkCalendarsForEvents(calendarHome, firstTime=True)
+            returnValue(calendarHome)
+        calendarHome = yield self._newOperation(&quot;startup: %s&quot; % (self.title,), startup())
+
+        self.started = True
+
+        # Start monitoring PubSub notifications, if possible.
+        # _checkCalendarsForEvents populates self.xmpp if it finds
+        # anything.
+        if self.supportAmpPush and calendarHome in self.ampPushKeys:
+            pushKeys = self.ampPushKeys.values()
+            self._monitorAmpPush(calendarHome, pushKeys)
+            # Run indefinitely.
+            yield Deferred()
+        else:
+            # This completes when the calendar home poll loop completes, which
+            # currently it never will except due to an unexpected error.
+            yield self._calendarCheckLoop(calendarHome)
+
+
+    def stop(self):
+        &quot;&quot;&quot;
+        Called before connections are closed, giving a chance to clean up
+        &quot;&quot;&quot;
+
+        self.serialize()
+        return self._unsubscribePubSub()
+
+
+    def serializeLocation(self):
+        &quot;&quot;&quot;
+        Return the path to the directory where data for this user is serialized.
+        &quot;&quot;&quot;
+        if self.serializePath is None or not os.path.isdir(self.serializePath):
+            return None
+
+        key = &quot;%s-%s&quot; % (self.record.uid, self.title.replace(&quot; &quot;, &quot;_&quot;))
+        path = os.path.join(self.serializePath, key)
+        if not os.path.exists(path):
+            os.mkdir(path)
+        elif not os.path.isdir(path):
+            return None
+
+        return path
+
+
+    def serialize(self):
+        &quot;&quot;&quot;
+        Write current state to disk.
+        &quot;&quot;&quot;
+
+        path = self.serializeLocation()
+        if path is None:
+            return
+
+        # Create dict for all the data we need to store
+        data = {
+            &quot;principalURL&quot;: self.principalURL,
+            &quot;calendars&quot;: [calendar.serialize() for calendar in sorted(self._calendars.values(), key=lambda x:x.name)],
+            &quot;events&quot;: [event.serialize() for event in sorted(self._events.values(), key=lambda x:x.url)],
+            &quot;notificationCollection&quot; : self._notificationCollection.serialize() if self._notificationCollection else {},
+            &quot;attachments&quot;: self._attachments
+        }
+        # Write JSON data
+        with open(os.path.join(path, &quot;index.json&quot;), &quot;w&quot;) as f:
+            json.dump(data, f, indent=2)
+
+
+    def deserialize(self):
+        &quot;&quot;&quot;
+        Read state from disk.
+        &quot;&quot;&quot;
+
+        self._calendars = {}
+        self._events = {}
+        self._attachments = {}
+
+        path = self.serializeLocation()
+        if path is None:
+            return
+
+        # Parse JSON data for calendars
+        try:
+            with open(os.path.join(path, &quot;index.json&quot;)) as f:
+                data = json.load(f)
+        except IOError:
+            return
+
+        self.principalURL = data[&quot;principalURL&quot;]
+
+        # Extract all the events first, then do the calendars (which reference the events)
+        for event in data[&quot;events&quot;]:
+            event = Event.deserialize(self.serializeLocation(), event)
+            self._events[event.url] = event
+        for calendar in data[&quot;calendars&quot;]:
+            calendar = Calendar.deserialize(calendar, self._events)
+            self._calendars[calendar.url] = calendar
+        if data.get(&quot;notificationCollection&quot;):
+            self._notificationCollection = NotificationCollection.deserialize(data, {})
+        self._attachments = data.get(&quot;attachments&quot;, {})
+
+
+
+    @inlineCallbacks
+    def reset(self):
+        path = self.serializeLocation()
+        if path is not None and os.path.exists(path):
+            shutil.rmtree(path)
+        yield self.startup()
+        yield self._checkCalendarsForEvents(self.calendarHomeHref)
+
+
+    def _makeSelfAttendee(self):
+        attendee = Property(
+            name=u'ATTENDEE',
+            value=self.email,
+            params={
+                'CN': self.record.commonName,
+                'CUTYPE': 'INDIVIDUAL',
+                'PARTSTAT': 'ACCEPTED',
+            },
+        )
+        return attendee
+
+
+    def _makeSelfOrganizer(self):
+        organizer = Property(
+            name=u'ORGANIZER',
+            value=self.email,
+            params={
+                'CN': self.record.commonName,
+            },
+        )
+        return organizer
+
+
+    @inlineCallbacks
+    def addEventAttendee(self, href, attendee):
+
+        event = self._events[href]
+        component = event.component
+
+        # Trigger auto-complete behavior
+        yield self._attendeeAutoComplete(component, attendee)
+
+        # If the event has no attendees, add ourselves as an attendee.
+        attendees = list(component.mainComponent().properties('ATTENDEE'))
+        if len(attendees) == 0:
+            # First add ourselves as a participant and as the
+            # organizer.  In the future for this event we should
+            # already have those roles.
+            component.mainComponent().addProperty(self._makeSelfOrganizer())
+            component.mainComponent().addProperty(self._makeSelfAttendee())
+        attendees.append(attendee)
+        component.mainComponent().addProperty(attendee)
+
+        label_suffix = &quot;small&quot;
+        if len(attendees) &gt; 5:
+            label_suffix = &quot;medium&quot;
+        if len(attendees) &gt; 20:
+            label_suffix = &quot;large&quot;
+        if len(attendees) &gt; 75:
+            label_suffix = &quot;huge&quot;
+
+        # At last, upload the new event definition
+        response = yield self._request(
+            (NO_CONTENT, PRECONDITION_FAILED,),
+            'PUT',
+            self.server[&quot;uri&quot;] + href.encode('utf-8'),
+            Headers({
+                    'content-type': ['text/calendar'],
+                    'if-match': [event.etag]}),
+            StringProducer(component.getTextWithTimezones(includeTimezones=True)),
+            method_label=&quot;PUT{organizer-%s}&quot; % (label_suffix,)
+        )
+
+        # Finally, re-retrieve the event to update the etag
+        yield self._updateEvent(response, href)
+
+
+    @inlineCallbacks
+    def _attendeeAutoComplete(self, component, attendee):
+
+        if self._ATTENDEE_LOOKUPS:
+            # Temporarily use some non-test names (some which will return
+            # many results, and others which will return fewer) because the
+            # test account names are all too similar
+            # name = attendee.parameterValue('CN').encode(&quot;utf-8&quot;)
+            # prefix = name[:4].lower()
+            prefix = random.choice([
+                &quot;chris&quot;, &quot;cyru&quot;, &quot;dre&quot;, &quot;eric&quot;, &quot;morg&quot;,
+                &quot;well&quot;, &quot;wilfr&quot;, &quot;witz&quot;
+            ])
+
+            email = attendee.value()
+            if email.startswith(&quot;mailto:&quot;):
+                email = email[7:]
+            elif attendee.hasParameter('EMAIL'):
+                email = attendee.parameterValue('EMAIL').encode(&quot;utf-8&quot;)
+
+            if self.supportEnhancedAttendeeAutoComplete:
+                # New calendar server enhanced query
+                search = &quot;&lt;C:search-token&gt;{}&lt;/C:search-token&gt;&quot;.format(prefix)
+                body = self._CALENDARSERVER_PRINCIPAL_SEARCH_REPORT.format(
+                    context=&quot;attendee&quot;, searchTokens=search)
+                yield self._report(
+                    self.principalCollection,
+                    body,
+                    depth=None,
+                    method_label=&quot;REPORT{cpsearch}&quot;,
+                )
+            else:
+                # First try to discover some names to supply to the
+                # auto-completion
+                yield self._report(
+                    self.principalCollection,
+                    self._USER_LIST_PRINCIPAL_PROPERTY_SEARCH % {
+                        'displayname': prefix,
+                        'email': prefix,
+                        'firstname': prefix,
+                        'lastname': prefix,
+                    },
+                    depth=None,
+                    method_label=&quot;REPORT{psearch}&quot;,
+                )
+
+            # Now learn about the attendee's availability
+            yield self.requestAvailability(
+                component.mainComponent().getStartDateUTC(),
+                component.mainComponent().getEndDateUTC(),
+                [self.email, u'mailto:' + email],
+                [component.resourceUID()]
+            )
+
+
+    @inlineCallbacks
+    def changeEventAttendee(self, href, oldAttendee, newAttendee):
+        event = self._events[href]
+        component = event.component
+
+        # Change the event to have the new attendee instead of the old attendee
+        component.mainComponent().removeProperty(oldAttendee)
+        component.mainComponent().addProperty(newAttendee)
+        okCodes = NO_CONTENT
+        headers = Headers({
+            'content-type': ['text/calendar'],
+        })
+        if event.scheduleTag is not None:
+            headers.addRawHeader('if-schedule-tag-match', event.scheduleTag)
+            okCodes = (NO_CONTENT, PRECONDITION_FAILED,)
+
+        attendees = list(component.mainComponent().properties('ATTENDEE'))
+        label_suffix = &quot;small&quot;
+        if len(attendees) &gt; 5:
+            label_suffix = &quot;medium&quot;
+        if len(attendees) &gt; 20:
+            label_suffix = &quot;large&quot;
+        if len(attendees) &gt; 75:
+            label_suffix = &quot;huge&quot;
+
+        response = yield self._request(
+            okCodes,
+            'PUT',
+            self.server[&quot;uri&quot;] + href.encode('utf-8'),
+            headers, StringProducer(component.getTextWithTimezones(includeTimezones=True)),
+            method_label=&quot;PUT{attendee-%s}&quot; % (label_suffix,),
+        )
+
+        # Finally, re-retrieve the event to update the etag
+        yield self._updateEvent(response, href)
+
+
+    @inlineCallbacks
+    def deleteEvent(self, href):
+        &quot;&quot;&quot;
+        Issue a DELETE for the given URL and remove local state
+        associated with that event.
+        &quot;&quot;&quot;
+
+        self._removeEvent(href)
+
+        response = yield self._request(
+            (NO_CONTENT, NOT_FOUND),
+            'DELETE',
+            self.server[&quot;uri&quot;] + href.encode('utf-8'),
+            method_label=&quot;DELETE{event}&quot;,
+        )
+        returnValue(response)
+
+
+    @inlineCallbacks
+    def addEvent(self, href, component, invite=False):
+        headers = Headers({
+            'content-type': ['text/calendar'],
+        })
+
+        attendees = list(component.mainComponent().properties('ATTENDEE'))
+        label_suffix = &quot;small&quot;
+        if len(attendees) &gt; 5:
+            label_suffix = &quot;medium&quot;
+        if len(attendees) &gt; 20:
+            label_suffix = &quot;large&quot;
+        if len(attendees) &gt; 75:
+            label_suffix = &quot;huge&quot;
+
+        response = yield self._request(
+            CREATED,
+            'PUT',
+            self.server[&quot;uri&quot;] + href.encode('utf-8'),
+            headers,
+            StringProducer(component.getTextWithTimezones(includeTimezones=True)),
+            method_label=&quot;PUT{organizer-%s}&quot; % (label_suffix,) if invite else &quot;PUT{event}&quot;,
+        )
+        self._localUpdateEvent(response, href, component)
+
+
+    @inlineCallbacks
+    def addInvite(self, href, component):
+        &quot;&quot;&quot;
+        Add an event that is an invite - i.e., has attendees. We will do attendee lookups and freebusy
+        checks on each attendee to simulate what happens when an organizer creates a new invite.
+        &quot;&quot;&quot;
+
+        # Do lookup and free busy of each attendee (not self)
+        attendees = list(component.mainComponent().properties('ATTENDEE'))
+        for attendee in attendees:
+            if attendee.value() in (self.uuid, self.email):
+                continue
+            yield self._attendeeAutoComplete(component, attendee)
+
+        # Now do a normal PUT
+        yield self.addEvent(href, component, invite=True)
+
+
+    @inlineCallbacks
+    def changeEvent(self, href):
+
+        event = self._events[href]
+        component = event.component
+
+        # At last, upload the new event definition
+        response = yield self._request(
+            (NO_CONTENT, PRECONDITION_FAILED,),
+            'PUT',
+            self.server[&quot;uri&quot;] + href.encode('utf-8'),
+            Headers({
+                'content-type': ['text/calendar'],
+                'if-match': [event.etag]
+            }),
+            StringProducer(component.getTextWithTimezones(includeTimezones=True)),
+            method_label=&quot;PUT{update}&quot;
+        )
+
+        # Finally, re-retrieve the event to update the etag
+        yield self._updateEvent(response, href)
+
+
+    def _localUpdateEvent(self, response, href, component):
+        headers = response.headers
+        etag = headers.getRawHeaders(&quot;etag&quot;, [None])[0]
+        scheduleTag = headers.getRawHeaders(&quot;schedule-tag&quot;, [None])[0]
+
+        event = Event(self.serializeLocation(), href, etag, component)
+        event.scheduleTag = scheduleTag
+        self._setEvent(href, event)
+
+
+    def updateEvent(self, href):
+        return self._updateEvent(None, href)
+
+
+    @inlineCallbacks
+    def _updateEvent(self, ignored, href):
+        response = yield self._request(
+            OK,
+            'GET',
+            self.server[&quot;uri&quot;] + href.encode('utf-8'),
+            method_label=&quot;GET{event}&quot;,
+        )
+        headers = response.headers
+        etag = headers.getRawHeaders('etag')[0]
+        scheduleTag = headers.getRawHeaders('schedule-tag', [None])[0]
+        body = yield readBody(response)
+        self.eventChanged(href, etag, scheduleTag, body)
+
+
+    @inlineCallbacks
+    def requestAvailability(self, start, end, users, mask=set()):
+        &quot;&quot;&quot;
+        Issue a VFREEBUSY request for I{roughly} the given date range for the
+        given users.  The date range is quantized to one day.  Because of this
+        it is an error for the range to span more than 24 hours.
+
+        @param start: A C{datetime} instance giving the beginning of the
+            desired range.
+
+        @param end: A C{datetime} instance giving the end of the desired range.
+
+        @param users: An iterable of user UUIDs which will be included in the
+            request.
+
+        @param mask: An iterable of event UIDs which are to be ignored for the
+            purposes of this availability lookup.
+
+        @return: A C{Deferred} which fires with a C{dict}.  Keys in the dict
+            are user UUIDs (those requested) and values are something else.
+        &quot;&quot;&quot;
+        outbox = self.server[&quot;uri&quot;] + self.outbox
+
+        if mask:
+            maskStr = u'\r\n'.join(['X-CALENDARSERVER-MASK-UID:' + uid
+                                    for uid in mask]) + u'\r\n'
+        else:
+            maskStr = u''
+        maskStr = maskStr.encode('utf-8')
+
+        attendeeStr = '\r\n'.join(['ATTENDEE:' + uuid.encode('utf-8')
+                                   for uuid in users]) + '\r\n'
+
+        # iCal issues 24 hour wide vfreebusy requests, starting and ending at 4am.
+        if start.compareDate(end):
+            msg(&quot;Availability request spanning multiple days (%r to %r), &quot;
+                &quot;dropping the end date.&quot; % (start, end))
+
+        start.setTimezone(Timezone.UTCTimezone)
+        start.setHHMMSS(0, 0, 0)
+        end = start + Duration(hours=24)
+
+        start = start.getText()
+        end = end.getText()
+        now = DateTime.getNowUTC().getText()
+
+        label_suffix = &quot;small&quot;
+        if len(users) &gt; 5:
+            label_suffix = &quot;medium&quot;
+        if len(users) &gt; 20:
+            label_suffix = &quot;large&quot;
+        if len(users) &gt; 75:
+            label_suffix = &quot;huge&quot;
+
+        response = yield self._request(
+            OK, 'POST', outbox,
+            Headers({
+                    'content-type': ['text/calendar'],
+                    'originator': [self.email],
+                    'recipient': [u', '.join(users).encode('utf-8')]}),
+            StringProducer(self._POST_AVAILABILITY % {
+                'attendees': attendeeStr,
+                'summary': (u'Availability for %s' % (', '.join(users),)).encode('utf-8'),
+                'organizer': self.email.encode('utf-8'),
+                'vfreebusy-uid': str(uuid4()).upper(),
+                'event-mask': maskStr,
+                'start': start,
+                'end': end,
+                'now': now,
+            }),
+            method_label=&quot;POST{fb-%s}&quot; % (label_suffix,),
+        )
+        body = yield readBody(response)
+        returnValue(body)
+
+
+    @inlineCallbacks
+    def postAttachment(self, href, content):
+        url = self.server[&quot;uri&quot;] + &quot;{0}?{1}&quot;.format(href, &quot;action=attachment-add&quot;)
+        filename = 'file-{}.txt'.format(len(content))
+        headers = Headers({
+            'Content-Disposition': ['attachment; filename=&quot;{}&quot;'.format(filename)]
+        })
+        response = yield self._request(
+            CREATED,
+            'POST',
+            url,
+            headers=headers,
+            body=StringProducer(content),
+            method_label=&quot;POST{attach}&quot;
+        )
+        body = yield readBody(response)
+
+        # We don't want to download an attachment we uploaded, so look for the
+        # Cal-Managed-Id: and Location: headers and remember those
+        managedId = response.headers.getRawHeaders(&quot;Cal-Managed-Id&quot;)[0]
+        location = response.headers.getRawHeaders(&quot;Location&quot;)[0]
+        self._attachments[managedId] = location
+
+        yield self.updateEvent(href)
+        returnValue(body)
+
+
+    @inlineCallbacks
+    def getAttachment(self, href, managedId):
+
+        # If we've already downloaded this managedId, skip it.
+        if managedId not in self._attachments:
+            self._attachments[managedId] = href
+            yield self._newOperation(&quot;download&quot;, self._get(href, 200))
+
+
+    @inlineCallbacks
+    def postXML(self, href, content, label):
+        headers = Headers({
+            'content-type': ['text/xml']
+        })
+        response = yield self._request(
+            (OK, CREATED, MULTI_STATUS),
+            'POST',
+            self.server[&quot;uri&quot;] + href,
+            headers=headers,
+            body=StringProducer(content),
+            method_label=label
+        )
+        body = yield readBody(response)
+        returnValue(body)
+
+
+
+class OS_X_10_6(BaseAppleClient):
+    &quot;&quot;&quot;
+    Implementation of the OS X 10.6 iCal network behavior.
+
+    Anything OS X 10.6 iCal does on its own, or any particular
+    network behaviors it takes in response to a user action, belong on
+    this class.
+
+    Usage-profile based behaviors (&quot;the user modifies an event every
+    3.2 minutes&quot;) belong elsewhere.
+    &quot;&quot;&quot;
+
+    _client_type = &quot;OS X 10.6&quot;
+
+    USER_AGENT = &quot;DAVKit/4.0.3 (732); CalendarStore/4.0.3 (991); iCal/4.0.3 (1388); Mac OS X/10.6.4 (10F569)&quot;
+
+    # The default interval, used if none is specified in external
+    # configuration.  This is also the actual value used by Snow
+    # Leopard iCal.
+    CALENDAR_HOME_POLL_INTERVAL = 15 * 60
+
+    # The maximum number of resources to retrieve in a single multiget
+    MULTIGET_BATCH_SIZE = 200
+
+    # Override and turn on if client supports Sync REPORT
+    _SYNC_REPORT = False
+
+    # Override and turn on if client syncs using time-range queries
+    _SYNC_TIMERANGE = False
+
+    # Override and turn off if client does not support attendee lookups
+    _ATTENDEE_LOOKUPS = True
+
+    # Request body data
+    _LOAD_PATH = &quot;OS_X_10_6&quot;
+
+    _STARTUP_WELL_KNOWN = loadRequestBody(_LOAD_PATH, 'startup_well_known')
+    _STARTUP_PRINCIPAL_PROPFIND_INITIAL = loadRequestBody(_LOAD_PATH, 'startup_principal_propfind_initial')
+    _STARTUP_PRINCIPAL_PROPFIND = loadRequestBody(_LOAD_PATH, 'startup_principal_propfind')
+    _STARTUP_PRINCIPALS_REPORT = loadRequestBody(_LOAD_PATH, 'startup_principals_report')
+    _STARTUP_PRINCIPAL_EXPAND = loadRequestBody(_LOAD_PATH, 'startup_principal_expand')
+    _STARTUP_PROPPATCH_CALENDAR_COLOR = loadRequestBody(_LOAD_PATH, 'startup_calendar_color_proppatch')
+    _STARTUP_PROPPATCH_CALENDAR_ORDER = loadRequestBody(_LOAD_PATH, 'startup_calendar_order_proppatch')
+    _STARTUP_PROPPATCH_CALENDAR_TIMEZONE = loadRequestBody(_LOAD_PATH, 'startup_calendar_timezone_proppatch')
+
+    _POLL_CALENDARHOME_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendarhome_propfind')
+    _POLL_CALENDAR_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind')
+    _POLL_CALENDAR_PROPFIND_D1 = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind_d1')
+    _POLL_CALENDAR_MULTIGET_REPORT = loadRequestBody(_LOAD_PATH, 'poll_calendar_multiget')
+    _POLL_CALENDAR_MULTIGET_REPORT_HREF = loadRequestBody(_LOAD_PATH, 'poll_calendar_multiget_hrefs')
+    _POLL_CALENDAR_SYNC_REPORT = None
+    _POLL_NOTIFICATION_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind')
+    _POLL_NOTIFICATION_PROPFIND_D1 = loadRequestBody(_LOAD_PATH, 'poll_notification_propfind_d1')
+
+    _USER_LIST_PRINCIPAL_PROPERTY_SEARCH = loadRequestBody(_LOAD_PATH, 'user_list_principal_property_search')
+    _POST_AVAILABILITY = loadRequestBody(_LOAD_PATH, 'post_availability')
+
+    @inlineCallbacks
+    def startup(self):
+
+        # Try to read data from disk - if it succeeds self.principalURL will be set
+        self.deserialize()
+
+        if self.principalURL is None:
+            # PROPFIND principal path to retrieve actual principal-URL
+            response = yield self._principalPropfindInitial(self.record.uid)
+            hrefs = response.getHrefProperties()
+            self.principalURL = hrefs[davxml.principal_URL].toString()
+
+        # Using the actual principal URL, retrieve principal information
+        principal = (yield self._extractPrincipalDetails())
+        returnValue(principal)
+
+
+
+class OS_X_10_7(BaseAppleClient):
+    &quot;&quot;&quot;
+    Implementation of the OS X 10.7 iCal network behavior.
+    &quot;&quot;&quot;
+
+    _client_type = &quot;OS X 10.7&quot;
+
+    USER_AGENT = &quot;CalendarStore/5.0.2 (1166); iCal/5.0.2 (1571); Mac OS X/10.7.3 (11D50)&quot;
+
+    # The default interval, used if none is specified in external
+    # configuration.  This is also the actual value used by Snow
+    # Leopard iCal.
+    CALENDAR_HOME_POLL_INTERVAL = 15 * 60
+
+    # The maximum number of resources to retrieve in a single multiget
+    MULTIGET_BATCH_SIZE = 50
+
+    # Override and turn on if client supports Sync REPORT
+    _SYNC_REPORT = True
+
+    # Override and turn on if client syncs using time-range queries
+    _SYNC_TIMERANGE = False
+
+    # Override and turn off if client does not support attendee lookups
+    _ATTENDEE_LOOKUPS = True
+
+    # Request body data
+    _LOAD_PATH = &quot;OS_X_10_7&quot;
+
+    _STARTUP_WELL_KNOWN = loadRequestBody(_LOAD_PATH, 'startup_well_known')
+    _STARTUP_PRINCIPAL_PROPFIND_INITIAL = loadRequestBody(_LOAD_PATH, 'startup_principal_propfind_initial')
+    _STARTUP_PRINCIPAL_PROPFIND = loadRequestBody(_LOAD_PATH, 'startup_principal_propfind')
+    _STARTUP_PRINCIPALS_REPORT = loadRequestBody(_LOAD_PATH, 'startup_principals_report')
+    _STARTUP_PRINCIPAL_EXPAND = loadRequestBody(_LOAD_PATH, 'startup_principal_expand')
+    _STARTUP_PROPPATCH_CALENDAR_COLOR = loadRequestBody(_LOAD_PATH, 'startup_calendar_color_proppatch')
+    _STARTUP_PROPPATCH_CALENDAR_ORDER = loadRequestBody(_LOAD_PATH, 'startup_calendar_order_proppatch')
+    _STARTUP_PROPPATCH_CALENDAR_TIMEZONE = loadRequestBody(_LOAD_PATH, 'startup_calendar_timezone_proppatch')
+
+    _POLL_CALENDARHOME_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendarhome_propfind')
+    _POLL_CALENDAR_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind')
+    _POLL_CALENDAR_PROPFIND_D1 = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind_d1')
+    _POLL_CALENDAR_MULTIGET_REPORT = loadRequestBody(_LOAD_PATH, 'poll_calendar_multiget')
+    _POLL_CALENDAR_MULTIGET_REPORT_HREF = loadRequestBody(_LOAD_PATH, 'poll_calendar_multiget_hrefs')
+    _POLL_CALENDAR_SYNC_REPORT = loadRequestBody(_LOAD_PATH, 'poll_calendar_sync')
+    _POLL_NOTIFICATION_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind')
+    _POLL_NOTIFICATION_PROPFIND_D1 = loadRequestBody(_LOAD_PATH, 'poll_notification_propfind_d1')
+
+    _USER_LIST_PRINCIPAL_PROPERTY_SEARCH = loadRequestBody(_LOAD_PATH, 'user_list_principal_property_search')
+    _POST_AVAILABILITY = loadRequestBody(_LOAD_PATH, 'post_availability')
+
+
+    def _addDefaultHeaders(self, headers):
+        &quot;&quot;&quot;
+        Add the clients default set of headers to ones being used in a request.
+        Default is to add User-Agent, sub-classes should override to add other
+        client specific things, Accept etc.
+        &quot;&quot;&quot;
+
+        super(OS_X_10_7, self)._addDefaultHeaders(headers)
+        headers.setRawHeaders('Accept', ['*/*'])
+        headers.setRawHeaders('Accept-Language', ['en-us'])
+        headers.setRawHeaders('Accept-Encoding', ['gzip,deflate'])
+        headers.setRawHeaders('Connection', ['keep-alive'])
+
+
+    @inlineCallbacks
+    def startup(self):
+
+        # Try to read data from disk - if it succeeds self.principalURL will be set
+        self.deserialize()
+
+        if self.principalURL is None:
+            # PROPFIND well-known with redirect
+            response = yield self._startupPropfindWellKnown()
+            hrefs = response.getHrefProperties()
+            if davxml.current_user_principal in hrefs:
+                self.principalURL = hrefs[davxml.current_user_principal].toString()
+            elif davxml.principal_URL in hrefs:
+                self.principalURL = hrefs[davxml.principal_URL].toString()
+            else:
+                # PROPFIND principal path to retrieve actual principal-URL
+                response = yield self._principalPropfindInitial(self.record.uid)
+                hrefs = response.getHrefProperties()
+                self.principalURL = hrefs[davxml.principal_URL].toString()
+
+        # Using the actual principal URL, retrieve principal information
+        principal = yield self._extractPrincipalDetails()
+        returnValue(principal)
+
+
+
+class OS_X_10_11(BaseAppleClient):
+    &quot;&quot;&quot;
+    Implementation of the OS X 10.11 Calendar.app network behavior.
+    &quot;&quot;&quot;
+
+    _client_type = &quot;OS X 10.11&quot;
+
+    USER_AGENT = &quot;Mac+OS+X/10.11 (15A283) CalendarAgent/361&quot;
+
+    # The default interval, used if none is specified in external
+    # configuration.  This is also the actual value used by El
+    # Capital Calendar.app.
+    CALENDAR_HOME_POLL_INTERVAL = 15 * 60  # in seconds
+
+    # The maximum number of resources to retrieve in a single multiget
+    MULTIGET_BATCH_SIZE = 50
+
+    # Override and turn on if client supports Sync REPORT
+    _SYNC_REPORT = True
+
+    # Override and turn off if client does not support attendee lookups
+    _ATTENDEE_LOOKUPS = True
+
+    # Request body data
+    _LOAD_PATH = &quot;OS_X_10_11&quot;
+
+    _STARTUP_WELL_KNOWN = loadRequestBody(_LOAD_PATH, 'startup_well_known_propfind')
+    _STARTUP_PRINCIPAL_PROPFIND_INITIAL = loadRequestBody(_LOAD_PATH, 'startup_principal_initial_propfind')
+    _STARTUP_PRINCIPAL_PROPFIND = loadRequestBody(_LOAD_PATH, 'startup_principal_propfind')
+    _STARTUP_PRINCIPALS_REPORT = loadRequestBody(_LOAD_PATH, 'startup_principals_report')
+    _STARTUP_PRINCIPAL_EXPAND = loadRequestBody(_LOAD_PATH, 'startup_principal_expand')
+
+    _STARTUP_CREATE_CALENDAR = loadRequestBody(_LOAD_PATH, 'startup_create_calendar')
+    _STARTUP_PROPPATCH_CALENDAR_COLOR = loadRequestBody(_LOAD_PATH, 'startup_calendar_color_proppatch')
+    # _STARTUP_PROPPATCH_CALENDAR_NAME = loadRequestBody(_LOAD_PATH, 'startup_calendar_displayname_proppatch')
+    _STARTUP_PROPPATCH_CALENDAR_ORDER = loadRequestBody(_LOAD_PATH, 'startup_calendar_order_proppatch')
+    _STARTUP_PROPPATCH_CALENDAR_TIMEZONE = loadRequestBody(_LOAD_PATH, 'startup_calendar_timezone_proppatch')
+
+    _POLL_CALENDARHOME_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendarhome_depth1_propfind')
+    _POLL_CALENDAR_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind')
+    _POLL_CALENDAR_PROPFIND_D1 = loadRequestBody(_LOAD_PATH, 'poll_calendar_depth1_propfind')
+    _POLL_CALENDAR_MULTIGET_REPORT = loadRequestBody('OS_X_10_7', 'poll_calendar_multiget')
+    _POLL_CALENDAR_MULTIGET_REPORT_HREF = loadRequestBody('OS_X_10_7', 'poll_calendar_multiget_hrefs')
+    _POLL_CALENDAR_SYNC_REPORT = loadRequestBody('OS_X_10_7', 'poll_calendar_sync')
+    _POLL_NOTIFICATION_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind')
+    _POLL_NOTIFICATION_PROPFIND_D1 = loadRequestBody(_LOAD_PATH, 'poll_notification_depth1_propfind')
+
+    _NOTIFICATION_SYNC_REPORT = loadRequestBody(_LOAD_PATH, 'notification_sync')
+
+    _USER_LIST_PRINCIPAL_PROPERTY_SEARCH = loadRequestBody('OS_X_10_7', 'user_list_principal_property_search')
+    _POST_AVAILABILITY = loadRequestBody('OS_X_10_7', 'post_availability')
+
+    _CALENDARSERVER_PRINCIPAL_SEARCH_REPORT = loadRequestBody(_LOAD_PATH, 'principal_search_report')
+
+
+    def _addDefaultHeaders(self, headers):
+        &quot;&quot;&quot;
+        Add the clients default set of headers to ones being used in a request.
+        Default is to add User-Agent, sub-classes should override to add other
+        client specific things, Accept etc.
+        &quot;&quot;&quot;
+
+        super(OS_X_10_11, self)._addDefaultHeaders(headers)
+        headers.setRawHeaders('Accept', ['*/*'])
+        headers.setRawHeaders('Accept-Language', ['en-us'])
+        headers.setRawHeaders('Accept-Encoding', ['gzip,deflate'])
+        headers.setRawHeaders('Connection', ['keep-alive'])
+
+
+    @inlineCallbacks
+    def startup(self):
+        # Try to read data from disk - if it succeeds self.principalURL will be set
+        self.deserialize()
+
+        if self.principalURL is None:
+            # PROPFIND well-known with redirect
+            response = yield self._startupPropfindWellKnown()
+            hrefs = response.getHrefProperties()
+            if davxml.current_user_principal in hrefs:
+                self.principalURL = hrefs[davxml.current_user_principal].toString()
+            elif davxml.principal_URL in hrefs:
+                self.principalURL = hrefs[davxml.principal_URL].toString()
+            else:
+                # PROPFIND principal path to retrieve actual principal-URL
+                response = yield self._principalPropfindInitial(self.record.uid)
+                hrefs = response.getHrefProperties()
+                self.principalURL = hrefs[davxml.principal_URL].toString()
+
+        # Using the actual principal URL, retrieve principal information
+        principal = yield self._extractPrincipalDetails()
+        returnValue(principal)
+
+
+
+class iOS_5(BaseAppleClient):
+    &quot;&quot;&quot;
+    Implementation of the iOS 5 network behavior.
+    &quot;&quot;&quot;
+
+    _client_type = &quot;iOS 5&quot;
+
+    USER_AGENT = &quot;iOS/5.1 (9B179) dataaccessd/1.0&quot;
+
+    # The default interval, used if none is specified in external
+    # configuration.  This is also the actual value used by Snow
+    # Leopard iCal.
+    CALENDAR_HOME_POLL_INTERVAL = 15 * 60
+
+    # The maximum number of resources to retrieve in a single multiget
+    MULTIGET_BATCH_SIZE = 50
+
+    # Override and turn on if client supports Sync REPORT
+    _SYNC_REPORT = False
+
+    # Override and turn on if client syncs using time-range queries
+    _SYNC_TIMERANGE = True
+
+    # Override and turn off if client does not support attendee lookups
+    _ATTENDEE_LOOKUPS = False
+
+    # Request body data
+    _LOAD_PATH = &quot;iOS_5&quot;
+
+    _STARTUP_WELL_KNOWN = loadRequestBody(_LOAD_PATH, 'startup_well_known')
+    _STARTUP_PRINCIPAL_PROPFIND_INITIAL = loadRequestBody(_LOAD_PATH, 'startup_principal_propfind_initial')
+    _STARTUP_PRINCIPAL_PROPFIND = loadRequestBody(_LOAD_PATH, 'startup_principal_propfind')
+    _STARTUP_PRINCIPALS_REPORT = loadRequestBody(_LOAD_PATH, 'startup_principals_report')
+    _STARTUP_PROPPATCH_CALENDAR_COLOR = loadRequestBody(_LOAD_PATH, 'startup_calendar_color_proppatch')
+    _STARTUP_PROPPATCH_CALENDAR_ORDER = loadRequestBody(_LOAD_PATH, 'startup_calendar_order_proppatch')
+
+    _POLL_CALENDARHOME_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendarhome_propfind')
+    _POLL_CALENDAR_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind')
+    _POLL_CALENDAR_VEVENT_TR_QUERY = loadRequestBody(_LOAD_PATH, 'poll_calendar_vevent_tr_query')
+    _POLL_CALENDAR_VTODO_QUERY = loadRequestBody(_LOAD_PATH, 'poll_calendar_vtodo_query')
+    _POLL_CALENDAR_PROPFIND_D1 = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind_d1')
+    _POLL_CALENDAR_MULTIGET_REPORT = loadRequestBody(_LOAD_PATH, 'poll_calendar_multiget')
+    _POLL_CALENDAR_MULTIGET_REPORT_HREF = loadRequestBody(_LOAD_PATH, 'poll_calendar_multiget_hrefs')
+
+
+    def _addDefaultHeaders(self, headers):
+        &quot;&quot;&quot;
+        Add the clients default set of headers to ones being used in a request.
+        Default is to add User-Agent, sub-classes should override to add other
+        client specific things, Accept etc.
+        &quot;&quot;&quot;
+
+        super(iOS_5, self)._addDefaultHeaders(headers)
+        headers.setRawHeaders('Accept', ['*/*'])
+        headers.setRawHeaders('Accept-Language', ['en-us'])
+        headers.setRawHeaders('Accept-Encoding', ['gzip,deflate'])
+        headers.setRawHeaders('Connection', ['keep-alive'])
+
+
+    @inlineCallbacks
+    def _pollFirstTime1(self, homeNode, calendars):
+        # Patch calendar properties
+        for cal in calendars:
+            if cal.name != &quot;inbox&quot;:
+                yield self._proppatch(
+                    cal.url,
+                    self._STARTUP_PROPPATCH_CALENDAR_COLOR,
+                    method_label=&quot;PROPPATCH{calendar}&quot;,
+                )
+                yield self._proppatch(
+                    cal.url,
+                    self._STARTUP_PROPPATCH_CALENDAR_ORDER,
+                    method_label=&quot;PROPPATCH{calendar}&quot;,
+                )
+
+
+    def _pollFirstTime2(self):
+        # Nothing here
+        return succeed(None)
+
+
+    def _updateCalendar(self, calendar, newToken):
+        &quot;&quot;&quot;
+        Update the local cached data for a calendar in an appropriate manner.
+        &quot;&quot;&quot;
+        if calendar.name == &quot;inbox&quot;:
+            # Inbox is done as a PROPFIND Depth:1
+            return self._updateCalendar_PROPFIND(calendar, newToken)
+        elif &quot;VEVENT&quot; in calendar.componentTypes:
+            # VEVENTs done as time-range VEVENT-only queries
+            return self._updateCalendar_VEVENT(calendar, newToken)
+        elif &quot;VTODO&quot; in calendar.componentTypes:
+            # VTODOs done as VTODO-only queries
+            return self._updateCalendar_VTODO(calendar, newToken)
+
+
+    @inlineCallbacks
+    def _updateCalendar_VEVENT(self, calendar, newToken):
+        &quot;&quot;&quot;
+        Sync all locally cached VEVENTs using a VEVENT-only time-range query.
+        &quot;&quot;&quot;
+
+        # Grab old hrefs prior to the PROPFIND so we sync with the old state. We need this because
+        # the sim can fire a PUT between the PROPFIND and when process the removals.
+        old_hrefs = set([calendar.url + child for child in calendar.events.keys()])
+
+        now = DateTime.getNowUTC()
+        now.setDateOnly(True)
+        now.offsetMonth(-1) # 1 month back default
+        result = yield self._report(
+            calendar.url,
+            self._POLL_CALENDAR_VEVENT_TR_QUERY % {&quot;start-date&quot;: now.getText()},
+            depth='1',
+            method_label=&quot;REPORT{vevent}&quot;,
+        )
+
+        yield self._updateApplyChanges(calendar, result, old_hrefs)
+
+        # Now update calendar to the new token
+        self._calendars[calendar.url].changeToken = newToken
+
+
+    @inlineCallbacks
+    def _updateCalendar_VTODO(self, calendar, newToken):
+        &quot;&quot;&quot;
+        Sync all locally cached VTODOs using a VTODO-only query.
+        &quot;&quot;&quot;
+
+        # Grab old hrefs prior to the PROPFIND so we sync with the old state. We need this because
+        # the sim can fire a PUT between the PROPFIND and when process the removals.
+        old_hrefs = set([calendar.url + child for child in calendar.events.keys()])
+
+        result = yield self._report(
+            calendar.url,
+            self._POLL_CALENDAR_VTODO_QUERY,
+            depth='1',
+            method_label=&quot;REPORT{vtodo}&quot;,
+        )
+
+        yield self._updateApplyChanges(calendar, result, old_hrefs)
+
+        # Now update calendar to the new token
+        self._calendars[calendar.url].changeToken = newToken
+
+
+    @inlineCallbacks
+    def startup(self):
+
+        # Try to read data from disk - if it succeeds self.principalURL will be set
+        self.deserialize()
+
+        if self.principalURL is None:
+            # PROPFIND well-known with redirect
+            response = yield self._startupPropfindWellKnown()
+            hrefs = response.getHrefProperties()
+            if davxml.current_user_principal in hrefs:
+                self.principalURL = hrefs[davxml.current_user_principal].toString()
+            elif davxml.principal_URL in hrefs:
+                self.principalURL = hrefs[davxml.principal_URL].toString()
+            else:
+                # PROPFIND principal path to retrieve actual principal-URL
+                response = yield self._principalPropfindInitial(self.record.uid)
+                hrefs = response.getHrefProperties()
+                self.principalURL = hrefs[davxml.principal_URL].toString()
+
+        # Using the actual principal URL, retrieve principal information
+        principal = yield self._extractPrincipalDetails()
+        returnValue(principal)
</ins></span></pre></div>
<a id="CalendarServertrunksimplugincaldavprofilepy"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/caldavprofile.py (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/caldavprofile.py                                (rev 0)
+++ CalendarServer/trunk/simplugin/caldavprofile.py        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,1166 @@
</span><ins>+##
+# Copyright (c) 2011-2016 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+##
+
+&quot;&quot;&quot;
+Implementation of specific end-user behaviors.
+&quot;&quot;&quot;
+
+from __future__ import division
+
+import json
+import sys
+from uuid import uuid4
+
+from caldavclientlibrary.protocol.caldav.definitions import caldavxml
+
+from twisted.python import context
+from twisted.python.log import msg
+from twisted.python.failure import Failure
+from twisted.internet.defer import Deferred, succeed, inlineCallbacks, returnValue
+from twisted.internet.task import LoopingCall
+from twisted.web.http import PRECONDITION_FAILED
+
+from twistedcaldav.ical import Property, Component
+
+from clientsim.framework.stats import NearFutureDistribution, NormalDistribution, UniformDiscreteDistribution, mean, median
+from clientsim.framework.stats import LogNormalDistribution, RecurrenceDistribution
+from clientsim.framework.logger import SummarizingMixin
+from clientsim.framework.baseclient import IncorrectResponseCode
+from clientsim.framework.baseprofile import ProfileBase as SuperProfileBase, loopWithDistribution
+from simplugin.caldavclient import Calendar
+
+from pycalendar.datetime import DateTime
+from pycalendar.duration import Duration
+
+from datetime import datetime
+
+class ProfileBase(SuperProfileBase):
+
+    def _calendarsOfType(self, calendarType, componentType, justOwned=False):
+        results = []
+
+        for cal in self._client._calendars.itervalues():
+            if cal.resourceType == calendarType and componentType in cal.componentTypes:
+                if justOwned:
+                    if (not cal.shared) or cal.sharedByMe:
+                        results.append(cal)
+                else:
+                    results.append(cal)
+
+        return results
+
+
+    def _getRandomCalendarOfType(self, componentType, justOwned=False):
+        &quot;&quot;&quot;
+        Return a random L{Calendar} object from the current user
+        or C{None} if there are no calendars to work with
+        &quot;&quot;&quot;
+        calendars = self._calendarsOfType(caldavxml.calendar, componentType, justOwned=justOwned)
+        if not calendars:
+            return None
+        # Choose a random calendar
+        calendar = self.random.choice(calendars)
+        return calendar
+
+
+    def _getRandomEventOfType(self, componentType, justOwned=True):
+        &quot;&quot;&quot;
+        Return a random L{Event} object from the current user
+        or C{None} if there are no events to work with
+        &quot;&quot;&quot;
+        calendars = self._calendarsOfType(caldavxml.calendar, componentType, justOwned=justOwned)
+        while calendars:
+            calendar = self.random.choice(calendars)
+            calendars.remove(calendar)
+            if not calendar.events:
+                continue
+
+            events = calendar.events.keys()
+            while events:
+                href = self.random.choice(events)
+                events.remove(href)
+                event = calendar.events[href]
+                if not event.component:
+                    continue
+                if event.scheduleTag:
+                    continue
+
+                return event
+        return None
+
+
+    def _isSelfAttendee(self, attendee):
+        &quot;&quot;&quot;
+        Try to match one of the attendee's identifiers against one of
+        C{self._client}'s identifiers.  Return C{True} if something matches,
+        C{False} otherwise.
+        &quot;&quot;&quot;
+        return attendee.parameterValue('EMAIL') == self._client.email[len('mailto:'):]
+
+
+    def _newOperation(self, label, deferred):
+        &quot;&quot;&quot;
+        Helper to emit a log event when a new operation is started and
+        another one when it completes.
+        &quot;&quot;&quot;
+        # If this is a scheduled request, record the lag in the
+        # scheduling now so it can be reported when the response is
+        # received.
+        lag = context.get('lag', None)
+
+        before = self._reactor.seconds()
+        msg(
+            type=&quot;operation&quot;,
+            phase=&quot;start&quot;,
+            user=self._client.record.uid,
+            client_type=self._client.title,
+            client_id=self._client._client_id,
+            label=label,
+            lag=lag,
+        )
+
+        def finished(passthrough):
+            success = not isinstance(passthrough, Failure)
+            if not success:
+                passthrough.trap(IncorrectResponseCode)
+                passthrough = passthrough.value.response
+            after = self._reactor.seconds()
+            msg(
+                type=&quot;operation&quot;,
+                phase=&quot;end&quot;,
+                duration=after - before,
+                user=self._client.record.uid,
+                client_type=self._client.title,
+                client_id=self._client._client_id,
+                label=label,
+                success=success,
+            )
+            return passthrough
+        deferred.addBoth(finished)
+        return deferred
+
+
+    def _failedOperation(self, label, reason):
+        &quot;&quot;&quot;
+        Helper to emit a log event when an operation fails.
+        &quot;&quot;&quot;
+        msg(
+            type=&quot;operation&quot;,
+            phase=&quot;failed&quot;,
+            user=self._client.record.uid,
+            client_type=self._client.title,
+            client_id=self._client._client_id,
+            label=label,
+            reason=reason,
+        )
+        self._sim._simFailure(&quot;%s: %s&quot; % (label, reason,), self._reactor)
+
+
+
+class CannotAddAttendee(Exception):
+    &quot;&quot;&quot;
+    Indicates no new attendees can be invited to a particular event.
+    &quot;&quot;&quot;
+    pass
+
+
+
+
+
+class Inviter(ProfileBase):
+    &quot;&quot;&quot;
+    A Calendar user who invites other users to new events.
+    &quot;&quot;&quot;
+    _eventTemplate = Component.fromString(&quot;&quot;&quot;\
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20101018T155431Z
+UID:C98AD237-55AD-4F7D-9009-0D355D835822
+DTEND;TZID=America/New_York:20101021T130000
+TRANSP:OPAQUE
+SUMMARY:Simple event
+DTSTART;TZID=America/New_York:20101021T120000
+DTSTAMP:20101018T155438Z
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR
+&quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;\r\n&quot;))
+
+
+    def setParameters(
+        self,
+        enabled=True,
+        sendInvitationDistribution=NormalDistribution(600, 60),
+        inviteeDistribution=UniformDiscreteDistribution(range(-10, 11)),
+        inviteeClumping=True,
+        inviteeCountDistribution=LogNormalDistribution(1.2, 1.2),
+        eventStartDistribution=NearFutureDistribution(),
+        eventDurationDistribution=UniformDiscreteDistribution([
+            15 * 60, 30 * 60,
+            45 * 60, 60 * 60,
+            120 * 60
+        ]),
+        recurrenceDistribution=RecurrenceDistribution(False),
+    ):
+        self.enabled = enabled
+        self._sendInvitationDistribution = sendInvitationDistribution
+        self._inviteeDistribution = inviteeDistribution
+        self._inviteeClumping = inviteeClumping
+        self._inviteeCountDistribution = inviteeCountDistribution
+        self._eventStartDistribution = eventStartDistribution
+        self._eventDurationDistribution = eventDurationDistribution
+        self._recurrenceDistribution = recurrenceDistribution
+
+
+    def run(self):
+        return loopWithDistribution(
+            self._reactor, self._sendInvitationDistribution, self._invite)
+
+
+    def _addAttendee(self, event, attendees):
+        &quot;&quot;&quot;
+        Create a new attendee to add to the list of attendees for the
+        given event.
+        &quot;&quot;&quot;
+        selfRecord = self._sim.getUserRecord(self._number)
+        invitees = set([u'mailto:%s' % (selfRecord.email,)])
+        for att in attendees:
+            invitees.add(att.value())
+
+        for _ignore_i in range(10):
+
+            sample = self._inviteeDistribution.sample()
+            if self._inviteeClumping:
+                sample = self._number + sample
+            invitee = max(0, sample)
+
+            try:
+                record = self._sim.getUserRecord(invitee)
+            except IndexError:
+                continue
+            cuaddr = u'mailto:%s' % (record.email,)
+            if cuaddr not in invitees:
+                break
+        else:
+            raise CannotAddAttendee(&quot;Can't find uninvited user to invite.&quot;)
+
+        attendee = Property(
+            name=u'ATTENDEE',
+            value=cuaddr.encode(&quot;utf-8&quot;),
+            params={
+                'CN': record.commonName,
+                'CUTYPE': 'INDIVIDUAL',
+                'PARTSTAT': 'NEEDS-ACTION',
+                'ROLE': 'REQ-PARTICIPANT',
+                'RSVP': 'TRUE',
+            },
+        )
+
+        event.addProperty(attendee)
+        attendees.append(attendee)
+
+
+    def _invite(self):
+        &quot;&quot;&quot;
+        Try to add a new event, or perhaps remove an
+        existing attendee from an event.
+
+        @return: C{None} if there are no events to play with,
+            otherwise a L{Deferred} which fires when the attendee
+            change has been made.
+        &quot;&quot;&quot;
+
+        if not self._client.started:
+            return succeed(None)
+
+        # Find calendars which are eligible for invites
+        calendars = self._calendarsOfType(caldavxml.calendar, &quot;VEVENT&quot;)
+
+        while calendars:
+            # Pick one at random from which to try to create an event
+            # to modify.
+            calendar = self.random.choice(calendars)
+            calendars.remove(calendar)
+
+            # Copy the template event and fill in some of its fields
+            # to make a new event to create on the calendar.
+            vcalendar = self._eventTemplate.duplicate()
+            vevent = vcalendar.mainComponent()
+            uid = str(uuid4())
+            dtstart = self._eventStartDistribution.sample()
+            dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
+            vevent.replaceProperty(Property(&quot;CREATED&quot;, DateTime.getNowUTC()))
+            vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
+            vevent.replaceProperty(Property(&quot;DTSTART&quot;, dtstart))
+            vevent.replaceProperty(Property(&quot;DTEND&quot;, dtend))
+            vevent.replaceProperty(Property(&quot;UID&quot;, uid))
+
+            rrule = self._recurrenceDistribution.sample()
+            if rrule is not None:
+                vevent.addProperty(Property(None, None, None, pycalendar=rrule))
+
+            vevent.addProperty(self._client._makeSelfOrganizer())
+            vevent.addProperty(self._client._makeSelfAttendee())
+
+            attendees = list(vevent.properties('ATTENDEE'))
+            for _ignore in range(int(self._inviteeCountDistribution.sample())):
+                try:
+                    self._addAttendee(vevent, attendees)
+                except CannotAddAttendee:
+                    continue
+
+            href = '%s%s.ics' % (calendar.url, uid)
+            d = self._client.addInvite(href, vcalendar)
+            return self._newOperation(&quot;invite&quot;, d)
+
+
+
+class Accepter(ProfileBase):
+    &quot;&quot;&quot;
+    A Calendar user who accepts invitations to events. As well as accepting requests, this
+    will also remove cancels and replies.
+    &quot;&quot;&quot;
+    def setParameters(
+        self,
+        enabled=True,
+        acceptDelayDistribution=NormalDistribution(1200, 60)
+    ):
+        self.enabled = enabled
+        self._accepting = set()
+        self._acceptDelayDistribution = acceptDelayDistribution
+
+
+    def run(self):
+        self._subscription = self._client.catalog[&quot;eventChanged&quot;].subscribe(self.eventChanged)
+        # TODO: Propagate errors from eventChanged and _acceptInvitation to this Deferred
+        return Deferred()
+
+
+    def eventChanged(self, href):
+        # Just respond to normal calendar events
+        calendar = href.rsplit('/', 1)[0] + '/'
+        try:
+            calendar = self._client._calendars[calendar]
+        except KeyError:
+            return
+
+        if calendar.resourceType == caldavxml.schedule_inbox:
+            # Handle inbox differently
+            self.inboxEventChanged(calendar, href)
+        elif calendar.resourceType == caldavxml.calendar:
+            self.calendarEventChanged(calendar, href)
+        else:
+            return
+
+
+    def calendarEventChanged(self, calendar, href):
+        if href in self._accepting:
+            return
+
+        component = self._client._events[href].component
+        # Check to see if this user is in the attendee list in the
+        # NEEDS-ACTION PARTSTAT.
+        attendees = tuple(component.mainComponent().properties('ATTENDEE'))
+        for attendee in attendees:
+            if self._isSelfAttendee(attendee):
+                if attendee.parameterValue('PARTSTAT') == 'NEEDS-ACTION':
+                    delay = self._acceptDelayDistribution.sample()
+                    self._accepting.add(href)
+                    self._reactor.callLater(
+                        delay, self._acceptInvitation, href, attendee)
+
+
+    def inboxEventChanged(self, calendar, href):
+        if href in self._accepting:
+            return
+
+        component = self._client._events[href].component
+        method = component.propertyValue('METHOD')
+        if method == &quot;REPLY&quot;:
+            # Replies are immediately deleted
+            self._accepting.add(href)
+            self._reactor.callLater(
+                0, self._handleReply, href)
+
+        elif method == &quot;CANCEL&quot;:
+            # Cancels are handled after a user delay
+            delay = self._acceptDelayDistribution.sample()
+            self._accepting.add(href)
+            self._reactor.callLater(
+                delay, self._handleCancel, href)
+
+
+    def _acceptInvitation(self, href, attendee):
+        def change():
+            accepted = self._makeAcceptedAttendee(attendee)
+            return self._client.changeEventAttendee(href, attendee, accepted)
+        d = change()
+
+        def scheduleError(reason):
+            reason.trap(IncorrectResponseCode)
+            if reason.value.response.code != PRECONDITION_FAILED:
+                return reason.value.response.code
+
+            # Download the event again and attempt to make the change
+            # to the attendee list again.
+            d = self._client.updateEvent(href)
+            def cbUpdated(ignored):
+                d = change()
+                d.addErrback(scheduleError)
+                return d
+            d.addCallback(cbUpdated)
+            return d
+        d.addErrback(scheduleError)
+
+        def accepted(ignored):
+            # Find the corresponding event in the inbox and delete it.
+            uid = self._client._events[href].getUID()
+            for cal in self._client._calendars.itervalues():
+                if cal.resourceType == caldavxml.schedule_inbox:
+                    for event in cal.events.itervalues():
+                        if uid == event.getUID():
+                            return self._client.deleteEvent(event.url)
+        d.addCallback(accepted)
+        def finished(passthrough):
+            self._accepting.remove(href)
+            return passthrough
+        d.addBoth(finished)
+        return self._newOperation(&quot;accept&quot;, d)
+
+
+    def _handleReply(self, href):
+        d = self._client.deleteEvent(href)
+        d.addBoth(self._finishRemoveAccepting, href)
+        return self._newOperation(&quot;reply done&quot;, d)
+
+
+    def _finishRemoveAccepting(self, passthrough, href):
+        self._accepting.remove(href)
+        if isinstance(passthrough, Failure):
+            passthrough.trap(IncorrectResponseCode)
+            passthrough = passthrough.value.response
+        return passthrough
+
+
+    def _handleCancel(self, href):
+
+        uid = self._client._events[href].getUID()
+        d = self._client.deleteEvent(href)
+
+        def removed(ignored):
+            # Find the corresponding event in any calendar and delete it.
+            for cal in self._client._calendars.itervalues():
+                if cal.resourceType == caldavxml.calendar:
+                    for event in cal.events.itervalues():
+                        if uid == event.getUID():
+                            return self._client.deleteEvent(event.url)
+        d.addCallback(removed)
+        d.addBoth(self._finishRemoveAccepting, href)
+        return self._newOperation(&quot;cancelled&quot;, d)
+
+
+    def _makeAcceptedAttendee(self, attendee):
+        accepted = attendee.duplicate()
+        accepted.setParameter('PARTSTAT', 'ACCEPTED')
+        accepted.removeParameter('RSVP')
+        return accepted
+
+
+
+class AttachmentDownloader(ProfileBase):
+    &quot;&quot;&quot;
+    A Calendar user who downloads attachments.
+    &quot;&quot;&quot;
+    def setParameters(
+        self,
+        enabled=True,
+    ):
+        self.enabled = enabled
+
+
+    def run(self):
+        self._subscription = self._client.catalog[&quot;eventChanged&quot;].subscribe(self.eventChanged)
+        return Deferred()
+
+
+    def eventChanged(self, href):
+        # Just respond to normal calendar events
+        calendar = href.rsplit('/', 1)[0] + '/'
+        try:
+            calendar = self._client._calendars[calendar]
+        except KeyError:
+            return
+
+        if calendar.resourceType == caldavxml.calendar:
+            self.calendarEventChanged(calendar, href)
+
+
+    def calendarEventChanged(self, calendar, href):
+        component = self._client._events[href].component
+        attachments = tuple(component.mainComponent().properties('ATTACH'))
+        if attachments:
+            for attachment in attachments:
+                attachmentHref = attachment.value()
+                managedId = attachment.parameterValue('MANAGED-ID')
+                self._reactor.callLater(
+                    0, self._client.getAttachment, attachmentHref, managedId
+                )
+
+
+
+class Eventer(ProfileBase):
+    &quot;&quot;&quot;
+    A Calendar user who creates new events.
+    &quot;&quot;&quot;
+    _eventTemplate = Component.fromString(&quot;&quot;&quot;\
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20101018T155431Z
+UID:C98AD237-55AD-4F7D-9009-0D355D835822
+DTEND;TZID=America/New_York:20101021T130000
+TRANSP:OPAQUE
+SUMMARY:Simple event
+DTSTART;TZID=America/New_York:20101021T120000
+DTSTAMP:20101018T155438Z
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR
+&quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;\r\n&quot;))
+
+    def setParameters(
+        self,
+        enabled=True,
+        interval=25,
+        eventStartDistribution=NearFutureDistribution(),
+        eventDurationDistribution=UniformDiscreteDistribution([
+            15 * 60, 30 * 60,
+            45 * 60, 60 * 60,
+            120 * 60
+        ]),
+        recurrenceDistribution=RecurrenceDistribution(False),
+    ):
+        self.enabled = enabled
+        self._interval = interval
+        self._eventStartDistribution = eventStartDistribution
+        self._eventDurationDistribution = eventDurationDistribution
+        self._recurrenceDistribution = recurrenceDistribution
+
+
+    def run(self):
+        self._call = LoopingCall(self._addEvent)
+        self._call.clock = self._reactor
+        return self._call.start(self._interval)
+
+
+    def _addEvent(self):
+        # Don't perform any operations until the client is up and running
+        if not self._client.started:
+            return succeed(None)
+
+        calendar = self._getRandomCalendarOfType('VEVENT')
+
+        if not calendar:
+            # No VEVENT calendars, so no new event...
+            return succeed(None)
+
+        # Copy the template event and fill in some of its fields
+        # to make a new event to create on the calendar.
+        vcalendar = self._eventTemplate.duplicate()
+        vevent = vcalendar.mainComponent()
+        uid = str(uuid4())
+        dtstart = self._eventStartDistribution.sample()
+        dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
+        vevent.replaceProperty(Property(&quot;CREATED&quot;, DateTime.getNowUTC()))
+        vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
+        vevent.replaceProperty(Property(&quot;DTSTART&quot;, dtstart))
+        vevent.replaceProperty(Property(&quot;DTEND&quot;, dtend))
+        vevent.replaceProperty(Property(&quot;UID&quot;, uid))
+
+        rrule = self._recurrenceDistribution.sample()
+        if rrule is not None:
+            vevent.addProperty(Property(None, None, None, pycalendar=rrule))
+
+        href = '%s%s.ics' % (calendar.url, uid)
+        d = self._client.addEvent(href, vcalendar)
+        return self._newOperation(&quot;create&quot;, d)
+
+
+
+class EventUpdaterBase(ProfileBase):
+
+    @inlineCallbacks
+    def action(self):
+        # Don't perform any operations until the client is up and running
+        if not self._client.started:
+            returnValue(None)
+
+        event = self._getRandomEventOfType('VEVENT', justOwned=True)
+        if not event:
+            returnValue(None)
+        component = event.component
+        vevent = component.mainComponent()
+
+        label = yield self.modifyEvent(event.url, vevent)
+        if label:
+            vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
+
+            event.component = component
+            yield self._newOperation(
+                label,
+                self._client.changeEvent(event.url)
+            )
+
+
+    def run(self):
+        self._call = LoopingCall(self.action)
+        self._call.clock = self._reactor
+        return self._call.start(self._interval)
+
+
+    def modifyEvent(self, href, vevent):
+        &quot;&quot;&quot;Overridden by subclasses&quot;&quot;&quot;
+        pass
+
+
+
+class TitleChanger(EventUpdaterBase):
+
+    def setParameters(
+        self,
+        enabled=True,
+        interval=60,
+        titleLengthDistribution=NormalDistribution(10, 2)
+    ):
+        self.enabled = enabled
+        self._interval = interval
+        self._titleLength = titleLengthDistribution
+
+
+    def modifyEvent(self, _ignore_href, vevent):
+        length = max(5, int(self._titleLength.sample()))
+        vevent.replaceProperty(Property(&quot;SUMMARY&quot;, &quot;Event&quot; + &quot;.&quot; * (length - 5)))
+        return succeed(&quot;update{title}&quot;)
+
+
+
+class DescriptionChanger(EventUpdaterBase):
+
+    def setParameters(
+        self,
+        enabled=True,
+        interval=60,
+        descriptionLengthDistribution=NormalDistribution(10, 2)
+    ):
+        self.enabled = enabled
+        self._interval = interval
+        self._descriptionLength = descriptionLengthDistribution
+
+
+    def modifyEvent(self, _ignore_href, vevent):
+        length = int(self._descriptionLength.sample())
+        vevent.replaceProperty(Property(&quot;DESCRIPTION&quot;, &quot;.&quot; * length))
+        return succeed(&quot;update{description}&quot;)
+
+
+
+class Attacher(EventUpdaterBase):
+
+    def setParameters(
+        self,
+        enabled=True,
+        interval=60,
+        fileSizeDistribution=NormalDistribution(1024, 1),
+    ):
+        self.enabled = enabled
+        self._interval = interval
+        self._fileSize = fileSizeDistribution
+
+
+    @inlineCallbacks
+    def modifyEvent(self, href, vevent):
+        fileSize = int(self._fileSize.sample())
+        yield self._client.postAttachment(href, 'x' * fileSize)
+        returnValue(None)
+
+
+
+class EventCountLimiter(EventUpdaterBase):
+    &quot;&quot;&quot;
+    Examines the number of events in each calendar collection, and when that
+    count exceeds eventCountLimit, events are randomly removed until the count
+    falls back to the limit.
+    &quot;&quot;&quot;
+
+    def setParameters(
+        self,
+        enabled=True,
+        interval=60,
+        eventCountLimit=1000
+    ):
+        self.enabled = enabled
+        self._interval = interval
+        self._limit = eventCountLimit
+
+
+    @inlineCallbacks
+    def action(self):
+        # Don't perform any operations until the client is up and running
+        if not self._client.started:
+            returnValue(None)
+
+        for calendar in self._calendarsOfType(caldavxml.calendar, &quot;VEVENT&quot;, justOwned=True):
+            while len(calendar.events) &gt; self._limit:
+                event = calendar.events[self.random.choice(calendar.events.keys())]
+                yield self._client.deleteEvent(event.url)
+
+
+
+class CalendarSharer(ProfileBase):
+    &quot;&quot;&quot;
+    A Calendar user who shares calendars to other random users.
+    &quot;&quot;&quot;
+    def setParameters(
+        self,
+        enabled=True,
+        interval=60
+    ):
+        self.enabled = enabled
+        self._interval = interval
+
+
+    def run(self):
+        self._call = LoopingCall(self.action)
+        self._call.clock = self._reactor
+        return self._call.start(self._interval)
+
+
+    @inlineCallbacks
+    def action(self):
+        # Don't perform any operations until the client is up and running
+        if not self._client.started:
+            returnValue(None)
+
+        yield self.shareCalendar()
+
+
+    @inlineCallbacks
+    def shareCalendar(self):
+
+        # pick a calendar
+        calendar = self._getRandomCalendarOfType('VEVENT', justOwned=True)
+        if not calendar:
+            returnValue(None)
+
+        # pick a random sharee
+        shareeRecord = self._sim.getRandomUserRecord(besides=self._number)
+        if shareeRecord is None:
+            returnValue(None)
+
+        # POST the sharing invite
+        mailto = &quot;mailto:{}&quot;.format(shareeRecord.email)
+        body = Calendar.addInviteeXML(mailto, calendar.name, readwrite=True)
+        yield self._client.postXML(
+            calendar.url,
+            body,
+            label=&quot;POST{share-calendar}&quot;
+        )
+
+
+
+class AlarmAcknowledger(ProfileBase):
+    &quot;&quot;&quot;
+    A Calendar user who creates a new event, and then updates its alarm.
+    &quot;&quot;&quot;
+    _eventTemplate = Component.fromString(&quot;&quot;&quot;\
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+CREATED:20101018T155431Z
+UID:C98AD237-55AD-4F7D-9009-0D355D835822
+DTEND;TZID=America/New_York:20101021T130000
+TRANSP:OPAQUE
+SUMMARY:Simple event
+DTSTART;TZID=America/New_York:20101021T120000
+DTSTAMP:20101018T155438Z
+SEQUENCE:2
+BEGIN:VALARM
+X-WR-ALARMUID:D9D1AC84-F629-4B9D-9B6B-4A6CA9A11FEF
+UID:D9D1AC84-F629-4B9D-9B6B-4A6CA9A11FEF
+DESCRIPTION:Event reminder
+TRIGGER:-PT8M
+ACTION:DISPLAY
+END:VALARM
+END:VEVENT
+END:VCALENDAR
+&quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;\r\n&quot;))
+
+    def setParameters(
+        self,
+        enabled=True,
+        interval=5,
+        pastTheHour=[0, 15, 30, 45],
+        eventStartDistribution=NearFutureDistribution(),
+        eventDurationDistribution=UniformDiscreteDistribution([
+            15 * 60, 30 * 60,
+            45 * 60, 60 * 60,
+            120 * 60
+        ]),
+        recurrenceDistribution=RecurrenceDistribution(False),
+    ):
+        self.enabled = enabled
+        self._interval = interval
+        self._pastTheHour = pastTheHour
+        self._eventStartDistribution = eventStartDistribution
+        self._eventDurationDistribution = eventDurationDistribution
+        self._recurrenceDistribution = recurrenceDistribution
+        self._lastMinuteChecked = -1
+
+
+    def initialize(self):
+        &quot;&quot;&quot;
+        Called before the profile runs for real. Can be used to initialize client state.
+
+        @return: a L{Deferred} that fires when initialization is done
+        &quot;&quot;&quot;
+
+        return self._initEvent()
+
+
+    def run(self):
+        self._call = LoopingCall(self._updateEvent)
+        self._call.clock = self._reactor
+        return self._call.start(self._interval)
+
+
+    def _initEvent(self):
+        # Don't perform any operations until the client is up and running
+        if not self._client.started:
+            return succeed(None)
+
+        # If it already exists, don't re-create
+        calendar = self._calendarsOfType(caldavxml.calendar, &quot;VEVENT&quot;)[0]
+        if calendar.events:
+            events = [event for event in calendar.events.values() if event.url.endswith(&quot;event_to_update.ics&quot;)]
+            if events:
+                return succeed(None)
+
+        # Copy the template event and fill in some of its fields
+        # to make a new event to create on the calendar.
+        vcalendar = self._eventTemplate.duplicate()
+        vevent = vcalendar.mainComponent()
+        uid = str(uuid4())
+        dtstart = self._eventStartDistribution.sample()
+        dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
+        vevent.replaceProperty(Property(&quot;CREATED&quot;, DateTime.getNowUTC()))
+        vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
+        vevent.replaceProperty(Property(&quot;DTSTART&quot;, dtstart))
+        vevent.replaceProperty(Property(&quot;DTEND&quot;, dtend))
+        vevent.replaceProperty(Property(&quot;UID&quot;, uid))
+
+        rrule = self._recurrenceDistribution.sample()
+        if rrule is not None:
+            vevent.addProperty(Property(None, None, None, pycalendar=rrule))
+
+        href = '%s%s' % (calendar.url, &quot;event_to_update.ics&quot;)
+        d = self._client.addEvent(href, vcalendar)
+        return self._newOperation(&quot;create&quot;, d)
+
+
+    def _shouldUpdate(self, minutePastTheHour):
+        &quot;&quot;&quot;
+        We want to only acknowledge our alarm at the &quot;past the hour&quot; minutes
+        we've been configured for.
+        &quot;&quot;&quot;
+        should = False
+        if minutePastTheHour in self._pastTheHour:
+            # This is one of the minutes we should update on, but only update
+            # as we pass into this minute, and not subsequent times
+            if minutePastTheHour != self._lastMinuteChecked:
+                should = True
+
+        self._lastMinuteChecked = minutePastTheHour
+        return should
+
+
+    def _updateEvent(self):
+        &quot;&quot;&quot;
+        Set the ACKNOWLEDGED property on an event.
+
+        @return: C{None} if there are no events to play with,
+            otherwise a L{Deferred} which fires when the acknowledged
+            change has been made.
+        &quot;&quot;&quot;
+
+        # Only do updates when we reach of the designated minutes past the hour
+        if not self._shouldUpdate(datetime.now().minute):
+            return succeed(None)
+
+        if not self._client.started:
+            return succeed(None)
+
+        # If it does not exist, try to create it
+        calendar = self._calendarsOfType(caldavxml.calendar, &quot;VEVENT&quot;)[0]
+        if not calendar.events:
+            return self._initEvent()
+        events = [event for event in calendar.events.values() if event.url.endswith(&quot;event_to_update.ics&quot;)]
+        if not events:
+            return self._initEvent()
+        event = events[0]
+
+        # Add/update the ACKNOWLEDGED property
+        component = event.component.mainComponent()
+        component.replaceProperty(Property(&quot;ACKNOWLEDGED&quot;, DateTime.getNowUTC()))
+        d = self._client.changeEvent(event.url)
+        return self._newOperation(&quot;update&quot;, d)
+
+
+
+class Tasker(ProfileBase):
+    &quot;&quot;&quot;
+    A Calendar user who creates new tasks.
+    &quot;&quot;&quot;
+    _taskTemplate = Component.fromString(&quot;&quot;&quot;\
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+CALSCALE:GREGORIAN
+BEGIN:VTODO
+CREATED:20101018T155431Z
+UID:C98AD237-55AD-4F7D-9009-0D355D835822
+SUMMARY:Simple task
+DUE;TZID=America/New_York:20101021T120000
+DTSTAMP:20101018T155438Z
+END:VTODO
+END:VCALENDAR
+&quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;\r\n&quot;))
+
+    def setParameters(
+        self,
+        enabled=True,
+        interval=25,
+        taskDueDistribution=NearFutureDistribution(),
+    ):
+        self.enabled = enabled
+        self._interval = interval
+        self._taskStartDistribution = taskDueDistribution
+
+
+    def run(self):
+        self._call = LoopingCall(self._addTask)
+        self._call.clock = self._reactor
+        return self._call.start(self._interval)
+
+
+    def _addTask(self):
+        # Don't perform any operations until the client is up and running
+        if not self._client.started:
+            return succeed(None)
+
+        calendars = self._calendarsOfType(caldavxml.calendar, &quot;VTODO&quot;)
+
+        while calendars:
+            calendar = self.random.choice(calendars)
+            calendars.remove(calendar)
+
+            # Copy the template task and fill in some of its fields
+            # to make a new task to create on the calendar.
+            vcalendar = self._taskTemplate.duplicate()
+            vtodo = vcalendar.mainComponent()
+            uid = str(uuid4())
+            due = self._taskStartDistribution.sample()
+            vtodo.replaceProperty(Property(&quot;CREATED&quot;, DateTime.getNowUTC()))
+            vtodo.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
+            vtodo.replaceProperty(Property(&quot;DUE&quot;, due))
+            vtodo.replaceProperty(Property(&quot;UID&quot;, uid))
+
+            href = '%s%s.ics' % (calendar.url, uid)
+            d = self._client.addEvent(href, vcalendar)
+            return self._newOperation(&quot;create&quot;, d)
+
+
+
+class Resetter(ProfileBase):
+    &quot;&quot;&quot;
+    A Calendar user who resets their account and re-downloads everything.
+    &quot;&quot;&quot;
+
+    def setParameters(
+        self,
+        enabled=True,
+        interval=600,
+    ):
+        self.enabled = enabled
+        self._interval = interval
+
+
+    def run(self):
+        self._call = LoopingCall(self._resetAccount)
+        self._call.clock = self._reactor
+        return self._call.start(self._interval)
+
+
+    def _resetAccount(self):
+        # Don't perform any operations until the client is up and running
+        if not self._client.started:
+            return succeed(None)
+
+        return self._client.reset()
+
+
+
+class OperationLogger(SummarizingMixin):
+    &quot;&quot;&quot;
+    Profiles will initiate operations which may span multiple requests.  Start
+    and stop log messages are emitted for these operations and logged by this
+    logger.
+    &quot;&quot;&quot;
+    formats = {
+        u&quot;start&quot; : u&quot;%(user)s - - - - - - - - - - - %(label)8s BEGIN %(lag)s&quot;,
+        u&quot;end&quot;   : u&quot;%(user)s - - - - - - - - - - - %(label)8s END [%(duration)5.2f s]&quot;,
+        u&quot;failed&quot;: u&quot;%(user)s x x x x x x x x x x x %(label)8s FAILED %(reason)s&quot;,
+    }
+
+    lagFormat = u'{lag %5.2f ms}'
+
+    # the response time thresholds to display together with failing % count threshold
+    _thresholds_default = {
+        &quot;operations&quot;: {
+            &quot;limits&quot;: [0.1, 0.5, 1.0, 3.0, 5.0, 10.0, 30.0],
+            &quot;thresholds&quot;: {
+                &quot;default&quot;: [100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0],
+            }
+        }
+    }
+    _lag_cut_off = 1.0      # Maximum allowed median scheduling latency, seconds
+    _fail_cut_off = 1.0     # % of total count at which failed requests will cause a failure
+
+    _fields_init = [
+        ('operation', -30, '%-30s'),
+        ('count', 8, '%8s'),
+        ('failed', 8, '%8s'),
+    ]
+
+    _fields_extend = [
+        ('mean', 8, '%8.4f'),
+        ('median', 8, '%8.4f'),
+        ('stddev', 8, '%8.4f'),
+        ('avglag (ms)', 12, '%12.4f'),
+        ('STATUS', 8, '%8s'),
+    ]
+
+    def __init__(self, outfile=None, **params):
+        self._perOperationTimes = {}
+        self._perOperationLags = {}
+        if outfile is None:
+            outfile = sys.stdout
+        self._outfile = outfile
+
+        # Load parameters from config
+        if &quot;thresholdsPath&quot; in params:
+            with open(params[&quot;thresholdsPath&quot;]) as f:
+                jsondata = json.load(f)
+        elif &quot;thresholds&quot; in params:
+            jsondata = params[&quot;thresholds&quot;]
+        else:
+            jsondata = self._thresholds_default
+        self._thresholds = [[limit, {}] for limit in jsondata[&quot;operations&quot;][&quot;limits&quot;]]
+        for ctr, item in enumerate(self._thresholds):
+            for k, v in jsondata[&quot;operations&quot;][&quot;thresholds&quot;].items():
+                item[1][k] = v[ctr]
+
+        self._fields = self._fields_init[:]
+        for threshold, _ignore_fail_at in self._thresholds:
+            self._fields.append(('&gt;%g sec' % (threshold,), 10, '%10s'))
+        self._fields.extend(self._fields_extend)
+
+        if &quot;lagCutoff&quot; in params:
+            self._lag_cut_off = params[&quot;lagCutoff&quot;]
+
+        if &quot;failCutoff&quot; in params:
+            self._fail_cut_off = params[&quot;failCutoff&quot;]
+
+        self._fail_if_no_push = params.get(&quot;failIfNoPush&quot;, False)
+
+
+    def observe(self, event):
+        if event.get(&quot;type&quot;) == &quot;operation&quot;:
+            event = event.copy()
+            lag = event.get('lag')
+            if lag is None:
+                event['lag'] = ''
+            else:
+                event['lag'] = self.lagFormat % (lag * 1000.0,)
+
+            self._outfile.write(
+                (self.formats[event[u'phase']] % event).encode('utf-8') + '\n')
+
+            if event[u'phase'] == u'end':
+                dataset = self._perOperationTimes.setdefault(event[u'label'], [])
+                dataset.append((event[u'success'], event[u'duration']))
+            elif lag is not None:
+                dataset = self._perOperationLags.setdefault(event[u'label'], [])
+                dataset.append(lag)
+
+
+    def _summarizeData(self, operation, data):
+        avglag = mean(self._perOperationLags.get(operation, [0.0])) * 1000.0
+        data = SummarizingMixin._summarizeData(self, operation, data)
+        return data[:-1] + (avglag,) + data[-1:]
+
+
+    def report(self, output):
+        output.write(&quot;\n&quot;)
+        self.printHeader(output, [
+            (label, width)
+            for (label, width, _ignore_fmt) in self._fields
+        ])
+        self.printData(
+            output,
+            [fmt for (label, width, fmt) in self._fields],
+            sorted(self._perOperationTimes.items())
+        )
+
+    _LATENCY_REASON = &quot;Median %(operation)s scheduling lag greater than %(cutoff)sms&quot;
+    _FAILED_REASON = &quot;Greater than %(cutoff).0f%% %(operation)s failed&quot;
+    _PUSH_MISSING_REASON = &quot;Push was configured but no pushes were received by clients&quot;
+
+    def failures(self):
+        reasons = []
+
+        for operation, lags in self._perOperationLags.iteritems():
+            if median(lags) &gt; self._lag_cut_off:
+                reasons.append(self._LATENCY_REASON % dict(
+                    operation=operation.upper(), cutoff=self._lag_cut_off * 1000))
+
+        for operation, times in self._perOperationTimes.iteritems():
+            failures = len([success for (success, _ignore_duration) in times if not success])
+            if failures * 100.0 / len(times) &gt; self._fail_cut_off:
+                reasons.append(self._FAILED_REASON % dict(
+                    operation=operation.upper(), cutoff=self._fail_cut_off))
+
+        if self._fail_if_no_push and &quot;push&quot; not in self._perOperationTimes:
+            reasons.append(self._PUSH_MISSING_REASON)
+
+        return reasons
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginclientsplist"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/clients.plist (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/clients.plist                                (rev 0)
+++ CalendarServer/trunk/simplugin/clients.plist        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,722 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+
+&lt;!--
+    Copyright (c) 2011-2016 Apple Inc. All rights reserved.
+
+    Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+  --&gt;
+
+&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
+&lt;plist version=&quot;1.0&quot;&gt;
+        &lt;dict&gt;
+                &lt;!-- Define the kinds of software and user behavior the load simulation
+                        will simulate. --&gt;
+                &lt;key&gt;clients&lt;/key&gt;
+
+                &lt;!-- Have as many different kinds of software and user behavior configurations
+                        as you want. Each is a dict --&gt;
+                &lt;array&gt;
+
+                        &lt;dict&gt;
+
+                                &lt;!-- Here is a OS X client simulator. --&gt;
+                                &lt;key&gt;software&lt;/key&gt;
+                                &lt;string&gt;simplugin.caldavclient.OS_X_10_11&lt;/string&gt;
+
+                                &lt;!-- Arguments to use to initialize the OS_X_10_11 instance. --&gt;
+                                &lt;key&gt;params&lt;/key&gt;
+                                &lt;dict&gt;
+                                        &lt;!-- Name that appears in logs. --&gt;
+                                        &lt;key&gt;title&lt;/key&gt;
+                                        &lt;string&gt;10.11&lt;/string&gt;
+
+                                        &lt;!-- OS_X_10_11 can poll the calendar home at some interval. This is
+                                                in seconds. --&gt;
+                                        &lt;key&gt;calendarHomePollInterval&lt;/key&gt;
+                                        &lt;integer&gt;30&lt;/integer&gt;
+
+                                        &lt;!-- If the server advertises xmpp push, OS_X_10_7 can wait for notifications
+                                                about calendar home changes instead of polling for them periodically. If
+                                                this option is true, then look for the server advertisement for xmpp push
+                                                and use it if possible. Still fall back to polling if there is no xmpp push
+                                                advertised. --&gt;
+                                        &lt;key&gt;supportPush&lt;/key&gt;
+                                        &lt;true/&gt;
+
+                                        &lt;key&gt;supportAmpPush&lt;/key&gt;
+                                        &lt;true/&gt;
+
+                                        &lt;!-- The template URI for doing initial principal lookup on. --&gt;
+                                        &lt;key&gt;principalPathTemplate&lt;/key&gt;
+                                        &lt;string&gt;/principals/users/{}/&lt;/string&gt;
+
+                                &lt;/dict&gt;
+
+                                &lt;!-- The profiles define certain types of user behavior on top of the
+                                        client software being simulated. --&gt;
+                                &lt;key&gt;profiles&lt;/key&gt;
+                                &lt;array&gt;
+
+                                        &lt;!-- First an event-creating profile, which will periodically create
+                                                new events at a random time on a random calendar. --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.Eventer&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define the interval (in seconds) at which this profile will use
+                                                                its client to create a new event. --&gt;
+                                                        &lt;key&gt;interval&lt;/key&gt;
+                                                        &lt;integer&gt;120&lt;/integer&gt;
+
+                                                        &lt;!-- Define how start times (DTSTART) for the randomly generated events
+                                                                will be selected. This is an example of a &quot;Distribution&quot; parameter. The value
+                                                                for most &quot;Distribution&quot; parameters are interchangeable and extensible. --&gt;
+                                                        &lt;key&gt;eventStartDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+
+                                                                &lt;!-- This distribution is pretty specialized. It produces timestamps
+                                                                        in the near future, limited to certain days of the week and certain hours
+                                                                        of the day. --&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.WorkDistribution&lt;/string&gt;
+
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- These are the days of the week the distribution will use. --&gt;
+                                                                        &lt;key&gt;daysOfWeek&lt;/key&gt;
+                                                                        &lt;array&gt;
+                                                                                &lt;string&gt;mon&lt;/string&gt;
+                                                                                &lt;string&gt;tue&lt;/string&gt;
+                                                                                &lt;string&gt;wed&lt;/string&gt;
+                                                                                &lt;string&gt;thu&lt;/string&gt;
+                                                                                &lt;string&gt;fri&lt;/string&gt;
+                                                                        &lt;/array&gt;
+
+                                                                        &lt;!-- The earliest hour of a day at which an event might be scheduled. --&gt;
+                                                                        &lt;key&gt;beginHour&lt;/key&gt;
+                                                                        &lt;integer&gt;8&lt;/integer&gt;
+
+                                                                        &lt;!-- And the latest hour of a day (at which an event will be scheduled
+                                                                                to begin!). --&gt;
+                                                                        &lt;key&gt;endHour&lt;/key&gt;
+                                                                        &lt;integer&gt;16&lt;/integer&gt;
+
+                                                                        &lt;!-- The timezone in which the event is scheduled. (XXX Does this
+                                                                                really work right?) --&gt;
+                                                                        &lt;key&gt;tzname&lt;/key&gt;
+                                                                        &lt;string&gt;America/Los_Angeles&lt;/string&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+
+                                                        &lt;!-- Define how recurrences are created. --&gt;
+                                                        &lt;key&gt;recurrenceDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+
+                                                                &lt;!-- This distribution is pretty specialized.  We have a fixed set of
+                                                                     RRULEs defined for this distribution and pick each based on a
+                                                                     weight. --&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.RecurrenceDistribution&lt;/string&gt;
+
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- False to disable RRULEs --&gt;
+                                                                        &lt;key&gt;allowRecurrence&lt;/key&gt;
+                                                                        &lt;true/&gt;
+
+                                                                        &lt;!-- These are the weights for the specific set of RRULEs. --&gt;
+                                                                        &lt;key&gt;weights&lt;/key&gt;
+                                                                        &lt;dict&gt;
+                                                                                &lt;!-- Half of all events will be non-recurring --&gt;
+                                                                                &lt;key&gt;none&lt;/key&gt;
+                                                                                &lt;integer&gt;50&lt;/integer&gt;
+
+                                                                                &lt;!-- Daily and weekly are pretty common --&gt;
+                                                                                &lt;key&gt;daily&lt;/key&gt;
+                                                                                &lt;integer&gt;10&lt;/integer&gt;
+                                                                                &lt;key&gt;weekly&lt;/key&gt;
+                                                                                &lt;integer&gt;20&lt;/integer&gt;
+
+                                                                                &lt;!-- Monthly, yearly, daily &amp; weekly limit not so common --&gt;
+                                                                                &lt;key&gt;monthly&lt;/key&gt;
+                                                                                &lt;integer&gt;2&lt;/integer&gt;
+                                                                                &lt;key&gt;yearly&lt;/key&gt;
+                                                                                &lt;integer&gt;1&lt;/integer&gt;
+                                                                                &lt;key&gt;dailylimit&lt;/key&gt;
+                                                                                &lt;integer&gt;2&lt;/integer&gt;
+                                                                                &lt;key&gt;weeklylimit&lt;/key&gt;
+                                                                                &lt;integer&gt;5&lt;/integer&gt;
+
+                                                                                &lt;!-- Work days pretty common --&gt;
+                                                                                &lt;key&gt;workdays&lt;/key&gt;
+                                                                                &lt;integer&gt;10&lt;/integer&gt;
+                                                                        &lt;/dict&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+                                        &lt;!-- This profile will create a new event, and then periodically update the ACKNOWLEDGED property. --&gt;
+
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.AlarmAcknowledger&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define how often to check (in seconds) whether it's
+                                                        time to do an alarm acknowledgement --&gt;
+                                                        &lt;key&gt;interval&lt;/key&gt;
+                                                        &lt;integer&gt;15&lt;/integer&gt;
+
+                                                        &lt;!-- Acknowledgements will only actually occur at one of these
+                                                        minutes past the hour: --&gt;
+                                                        &lt;key&gt;pastTheHour&lt;/key&gt;
+                                                        &lt;array&gt;
+                                                                &lt;integer&gt;0&lt;/integer&gt;
+                                                                &lt;integer&gt;15&lt;/integer&gt;
+                                                                &lt;integer&gt;30&lt;/integer&gt;
+                                                                &lt;integer&gt;45&lt;/integer&gt;
+                                                        &lt;/array&gt;
+
+                                                        &lt;!-- Define how start times (DTSTART) for the randomly generated events
+                                                                will be selected. This is an example of a &quot;Distribution&quot; parameter. The value
+                                                                for most &quot;Distribution&quot; parameters are interchangeable and extensible. --&gt;
+                                                        &lt;key&gt;eventStartDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+
+                                                                &lt;!-- This distribution is pretty specialized. It produces timestamps
+                                                                        in the near future, limited to certain days of the week and certain hours
+                                                                        of the day. --&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.WorkDistribution&lt;/string&gt;
+
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- These are the days of the week the distribution will use. --&gt;
+                                                                        &lt;key&gt;daysOfWeek&lt;/key&gt;
+                                                                        &lt;array&gt;
+                                                                                &lt;string&gt;mon&lt;/string&gt;
+                                                                                &lt;string&gt;tue&lt;/string&gt;
+                                                                                &lt;string&gt;wed&lt;/string&gt;
+                                                                                &lt;string&gt;thu&lt;/string&gt;
+                                                                                &lt;string&gt;fri&lt;/string&gt;
+                                                                        &lt;/array&gt;
+
+                                                                        &lt;!-- The earliest hour of a day at which an event might be scheduled. --&gt;
+                                                                        &lt;key&gt;beginHour&lt;/key&gt;
+                                                                        &lt;integer&gt;8&lt;/integer&gt;
+
+                                                                        &lt;!-- And the latest hour of a day (at which an event will be scheduled
+                                                                                to begin!). --&gt;
+                                                                        &lt;key&gt;endHour&lt;/key&gt;
+                                                                        &lt;integer&gt;16&lt;/integer&gt;
+
+                                                                        &lt;!-- The timezone in which the event is scheduled. (XXX Does this
+                                                                                really work right?) --&gt;
+                                                                        &lt;key&gt;tzname&lt;/key&gt;
+                                                                        &lt;string&gt;America/Los_Angeles&lt;/string&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+
+                                                        &lt;!-- Define how recurrences are created. --&gt;
+                                                        &lt;key&gt;recurrenceDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+
+                                                                &lt;!-- This distribution is pretty specialized.  We have a fixed set of
+                                                                     RRULEs defined for this distribution and pick each based on a
+                                                                     weight. --&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.RecurrenceDistribution&lt;/string&gt;
+
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- False to disable RRULEs --&gt;
+                                                                        &lt;key&gt;allowRecurrence&lt;/key&gt;
+                                                                        &lt;true/&gt;
+
+                                                                        &lt;!-- These are the weights for the specific set of RRULEs. --&gt;
+                                                                        &lt;key&gt;weights&lt;/key&gt;
+                                                                        &lt;dict&gt;
+                                                                                &lt;!-- Half of all events will be non-recurring --&gt;
+                                                                                &lt;key&gt;none&lt;/key&gt;
+                                                                                &lt;integer&gt;50&lt;/integer&gt;
+
+                                                                                &lt;!-- Daily and weekly are pretty common --&gt;
+                                                                                &lt;key&gt;daily&lt;/key&gt;
+                                                                                &lt;integer&gt;25&lt;/integer&gt;
+                                                                                &lt;key&gt;weekly&lt;/key&gt;
+                                                                                &lt;integer&gt;25&lt;/integer&gt;
+
+                                                                                &lt;!-- Monthly, yearly, daily &amp; weekly limit not so common --&gt;
+                                                                                &lt;key&gt;monthly&lt;/key&gt;
+                                                                                &lt;integer&gt;0&lt;/integer&gt;
+                                                                                &lt;key&gt;yearly&lt;/key&gt;
+                                                                                &lt;integer&gt;0&lt;/integer&gt;
+                                                                                &lt;key&gt;dailylimit&lt;/key&gt;
+                                                                                &lt;integer&gt;0&lt;/integer&gt;
+                                                                                &lt;key&gt;weeklylimit&lt;/key&gt;
+                                                                                &lt;integer&gt;0&lt;/integer&gt;
+
+                                                                                &lt;!-- Work days pretty common --&gt;
+                                                                                &lt;key&gt;workdays&lt;/key&gt;
+                                                                                &lt;integer&gt;0&lt;/integer&gt;
+                                                                        &lt;/dict&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+                                        &lt;!-- Picks a random event and changes the title --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.TitleChanger&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define the interval (in seconds) at which this profile will use
+                                                                its client to create a new event. --&gt;
+                                                        &lt;key&gt;interval&lt;/key&gt;
+                                                        &lt;integer&gt;120&lt;/integer&gt;
+
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+                                        &lt;!-- Picks a random event and changes the description --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.DescriptionChanger&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define the interval (in seconds) at which this profile will use
+                                                                its client to create a new event. --&gt;
+                                                        &lt;key&gt;interval&lt;/key&gt;
+                                                        &lt;integer&gt;120&lt;/integer&gt;
+
+                                                        &lt;!-- Define the description length distribution. --&gt;
+                                                        &lt;key&gt;descriptionLengthDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.LogNormalDistribution&lt;/string&gt;
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- mode - peak--&gt;
+                                                                        &lt;key&gt;mode&lt;/key&gt;
+                                                                        &lt;integer&gt;450&lt;/integer&gt;
+                                                                        &lt;!-- mean - average--&gt;
+                                                                        &lt;key&gt;median&lt;/key&gt;
+                                                                        &lt;integer&gt;650&lt;/integer&gt;
+                                                                        &lt;!-- maximum --&gt;
+                                                                        &lt;key&gt;maximum&lt;/key&gt;
+                                                                        &lt;real&gt;1000000&lt;/real&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+                                        &lt;!-- Picks a random event and attaches --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.Attacher&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define the interval (in seconds) at which this profile will use
+                                                                its client to create a new event. --&gt;
+                                                        &lt;key&gt;interval&lt;/key&gt;
+                                                        &lt;integer&gt;120&lt;/integer&gt;
+
+                                                        &lt;!-- Define the attachment size distribution. --&gt;
+                                                        &lt;key&gt;fileSizeDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.NormalDistribution&lt;/string&gt;
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- mu gives the mean of the normal distribution (in seconds). --&gt;
+                                                                        &lt;key&gt;mu&lt;/key&gt;
+                                                                        &lt;integer&gt;500000&lt;/integer&gt;
+
+                                                                        &lt;!-- and sigma gives its standard deviation. --&gt;
+                                                                        &lt;key&gt;sigma&lt;/key&gt;
+                                                                        &lt;integer&gt;100000&lt;/integer&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+                                        &lt;!-- Removes events from calendars exceeding a threshold --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.EventCountLimiter&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define the interval (in seconds) at which this profile will check
+                                                                for too-large collections. --&gt;
+                                                        &lt;key&gt;interval&lt;/key&gt;
+                                                        &lt;integer&gt;60&lt;/integer&gt;
+
+                                                        &lt;!-- The upper bound. --&gt;
+                                                        &lt;key&gt;eventCountLimit&lt;/key&gt;
+                                                        &lt;integer&gt;100&lt;/integer&gt;
+
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+
+                                        &lt;!-- Shares calendars --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.CalendarSharer&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define the interval (in seconds) at which this profile will share calendars. --&gt;
+                                                        &lt;key&gt;interval&lt;/key&gt;
+                                                        &lt;integer&gt;300&lt;/integer&gt;
+
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+                                        &lt;!-- This profile invites some number of new attendees to new events. --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.Inviter&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define the frequency at which new invitations will be sent out. --&gt;
+                                                        &lt;key&gt;sendInvitationDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.NormalDistribution&lt;/string&gt;
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- mu gives the mean of the normal distribution (in seconds). --&gt;
+                                                                        &lt;key&gt;mu&lt;/key&gt;
+                                                                        &lt;integer&gt;120&lt;/integer&gt;
+
+                                                                        &lt;!-- and sigma gives its standard deviation. --&gt;
+                                                                        &lt;key&gt;sigma&lt;/key&gt;
+                                                                        &lt;integer&gt;5&lt;/integer&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+
+                                                        &lt;!-- Define the distribution of who will be invited to an event.
+
+                                                                When inviteeClumping is turned on each invitee is based on a sample of
+                                                                users &quot;close to&quot; the organizer based on account index. If the clumping
+                                                                is too &quot;tight&quot; for the requested number of attendees, then invites for
+                                                                those larger numbers will simply fail (the sim will report that situation).
+
+                                                                When inviteeClumping is off invitees will be sampled across an entire
+                                                                range of account indexes. In this case the distribution ought to be a
+                                                                UniformIntegerDistribution with min=0 and max set to the number of accounts.
+                                                        --&gt;
+                                                        &lt;key&gt;inviteeDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.UniformIntegerDistribution&lt;/string&gt;
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- The minimum value (inclusive) of the uniform distribution. --&gt;
+                                                                        &lt;key&gt;min&lt;/key&gt;
+                                                                        &lt;integer&gt;0&lt;/integer&gt;
+                                                                        &lt;!-- The maximum value (exclusive) of the uniform distribution. --&gt;
+                                                                        &lt;key&gt;max&lt;/key&gt;
+                                                                        &lt;integer&gt;99&lt;/integer&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+
+                                                        &lt;key&gt;inviteeClumping&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define the distribution of how many attendees will be invited to an event.
+
+                                                                LogNormal is the best fit to observed data.
+
+
+                                                                For LogNormal &quot;mode&quot; is the peak, &quot;mean&quot; is the mean value.        For invites,
+                                                                mode should typically be 1, and mean whatever matches the user behavior.
+                                                                Our typical mean is 6.
+                                                             --&gt;
+                                                        &lt;key&gt;inviteeCountDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.LogNormalDistribution&lt;/string&gt;
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- mode - peak--&gt;
+                                                                        &lt;key&gt;mode&lt;/key&gt;
+                                                                        &lt;integer&gt;6&lt;/integer&gt;
+                                                                        &lt;!-- mean - average--&gt;
+                                                                        &lt;key&gt;median&lt;/key&gt;
+                                                                        &lt;integer&gt;8&lt;/integer&gt;
+                                                                        &lt;!-- maximum --&gt;
+                                                                        &lt;key&gt;maximum&lt;/key&gt;
+                                                                        &lt;real&gt;60&lt;/real&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+
+                                                        &lt;!-- Define how start times (DTSTART) for the randomly generated events
+                                                                will be selected. This is an example of a &quot;Distribution&quot; parameter. The value
+                                                                for most &quot;Distribution&quot; parameters are interchangeable and extensible. --&gt;
+                                                        &lt;key&gt;eventStartDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+
+                                                                &lt;!-- This distribution is pretty specialized. It produces timestamps
+                                                                        in the near future, limited to certain days of the week and certain hours
+                                                                        of the day. --&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.WorkDistribution&lt;/string&gt;
+
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- These are the days of the week the distribution will use. --&gt;
+                                                                        &lt;key&gt;daysOfWeek&lt;/key&gt;
+                                                                        &lt;array&gt;
+                                                                                &lt;string&gt;mon&lt;/string&gt;
+                                                                                &lt;string&gt;tue&lt;/string&gt;
+                                                                                &lt;string&gt;wed&lt;/string&gt;
+                                                                                &lt;string&gt;thu&lt;/string&gt;
+                                                                                &lt;string&gt;fri&lt;/string&gt;
+                                                                        &lt;/array&gt;
+
+                                                                        &lt;!-- The earliest hour of a day at which an event might be scheduled. --&gt;
+                                                                        &lt;key&gt;beginHour&lt;/key&gt;
+                                                                        &lt;integer&gt;8&lt;/integer&gt;
+
+                                                                        &lt;!-- And the latest hour of a day (at which an event will be scheduled
+                                                                                to begin!). --&gt;
+                                                                        &lt;key&gt;endHour&lt;/key&gt;
+                                                                        &lt;integer&gt;16&lt;/integer&gt;
+
+                                                                        &lt;!-- The timezone in which the event is scheduled. (XXX Does this
+                                                                                really work right?) --&gt;
+                                                                        &lt;key&gt;tzname&lt;/key&gt;
+                                                                        &lt;string&gt;America/Los_Angeles&lt;/string&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+
+                                                        &lt;!-- Define how recurrences are created. --&gt;
+                                                        &lt;key&gt;recurrenceDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+
+                                                                &lt;!-- This distribution is pretty specialized.  We have a fixed set of
+                                                                     RRULEs defined for this distribution and pick each based on a
+                                                                     weight. --&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.RecurrenceDistribution&lt;/string&gt;
+
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- False to disable RRULEs --&gt;
+                                                                        &lt;key&gt;allowRecurrence&lt;/key&gt;
+                                                                        &lt;true/&gt;
+
+                                                                        &lt;!-- These are the weights for the specific set of RRULEs. --&gt;
+                                                                        &lt;key&gt;weights&lt;/key&gt;
+                                                                        &lt;dict&gt;
+                                                                                &lt;!-- Half of all events will be non-recurring --&gt;
+                                                                                &lt;key&gt;none&lt;/key&gt;
+                                                                                &lt;integer&gt;50&lt;/integer&gt;
+
+                                                                                &lt;!-- Daily and weekly are pretty common --&gt;
+                                                                                &lt;key&gt;daily&lt;/key&gt;
+                                                                                &lt;integer&gt;10&lt;/integer&gt;
+                                                                                &lt;key&gt;weekly&lt;/key&gt;
+                                                                                &lt;integer&gt;20&lt;/integer&gt;
+
+                                                                                &lt;!-- Monthly, yearly, daily &amp; weekly limit not so common --&gt;
+                                                                                &lt;key&gt;monthly&lt;/key&gt;
+                                                                                &lt;integer&gt;2&lt;/integer&gt;
+                                                                                &lt;key&gt;yearly&lt;/key&gt;
+                                                                                &lt;integer&gt;1&lt;/integer&gt;
+                                                                                &lt;key&gt;dailylimit&lt;/key&gt;
+                                                                                &lt;integer&gt;2&lt;/integer&gt;
+                                                                                &lt;key&gt;weeklylimit&lt;/key&gt;
+                                                                                &lt;integer&gt;5&lt;/integer&gt;
+
+                                                                                &lt;!-- Work days pretty common --&gt;
+                                                                                &lt;key&gt;workdays&lt;/key&gt;
+                                                                                &lt;integer&gt;10&lt;/integer&gt;
+                                                                        &lt;/dict&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+                                        &lt;!-- This profile accepts invitations to events, handles cancels, and
+                                             handles replies received. --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.Accepter&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define how long to wait after seeing a new invitation before
+                                                                accepting it.
+
+                                                                For LogNormal &quot;mode&quot; is the peak, &quot;median&quot; is the 50% cummulative value
+                                                                (i.e., half of the user have accepted by that time).
+                                                        --&gt;
+                                                        &lt;key&gt;acceptDelayDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.LogNormalDistribution&lt;/string&gt;
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- mode - peak--&gt;
+                                                                        &lt;key&gt;mode&lt;/key&gt;
+                                                                        &lt;integer&gt;300&lt;/integer&gt;
+                                                                        &lt;!-- median - 50% done--&gt;
+                                                                        &lt;key&gt;median&lt;/key&gt;
+                                                                        &lt;integer&gt;1800&lt;/integer&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+
+                                        &lt;!-- This profile downloads attachments when an event changes. --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.AttachmentDownloader&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+                                        &lt;!-- A task-creating profile, which will periodically create
+                                                new tasks at a random time on a random calendar. --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.Tasker&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;true/&gt;
+
+                                                        &lt;!-- Define the interval (in seconds) at which this profile will use
+                                                                its client to create a new task. --&gt;
+                                                        &lt;key&gt;interval&lt;/key&gt;
+                                                        &lt;integer&gt;300&lt;/integer&gt;
+
+                                                        &lt;!-- Define how due times (DUE) for the randomly generated tasks
+                                                                will be selected. This is an example of a &quot;Distribution&quot; parameter. The value
+                                                                for most &quot;Distribution&quot; parameters are interchangeable and extensible. --&gt;
+                                                        &lt;key&gt;taskDueDistribution&lt;/key&gt;
+                                                        &lt;dict&gt;
+
+                                                                &lt;!-- This distribution is pretty specialized. It produces timestamps
+                                                                        in the near future, limited to certain days of the week and certain hours
+                                                                        of the day. --&gt;
+                                                                &lt;key&gt;type&lt;/key&gt;
+                                                                &lt;string&gt;clientsim.framework.stats.WorkDistribution&lt;/string&gt;
+
+                                                                &lt;key&gt;params&lt;/key&gt;
+                                                                &lt;dict&gt;
+                                                                        &lt;!-- These are the days of the week the distribution will use. --&gt;
+                                                                        &lt;key&gt;daysOfWeek&lt;/key&gt;
+                                                                        &lt;array&gt;
+                                                                                &lt;string&gt;mon&lt;/string&gt;
+                                                                                &lt;string&gt;tue&lt;/string&gt;
+                                                                                &lt;string&gt;wed&lt;/string&gt;
+                                                                                &lt;string&gt;thu&lt;/string&gt;
+                                                                                &lt;string&gt;fri&lt;/string&gt;
+                                                                        &lt;/array&gt;
+
+                                                                        &lt;!-- The earliest hour of a day at which an event might be scheduled. --&gt;
+                                                                        &lt;key&gt;beginHour&lt;/key&gt;
+                                                                        &lt;integer&gt;8&lt;/integer&gt;
+
+                                                                        &lt;!-- And the latest hour of a day (at which an event will be scheduled
+                                                                                to begin!). --&gt;
+                                                                        &lt;key&gt;endHour&lt;/key&gt;
+                                                                        &lt;integer&gt;16&lt;/integer&gt;
+
+                                                                        &lt;!-- The timezone in which the event is scheduled. (XXX Does this
+                                                                                really work right?) --&gt;
+                                                                        &lt;key&gt;tzname&lt;/key&gt;
+                                                                        &lt;string&gt;America/Los_Angeles&lt;/string&gt;
+                                                                &lt;/dict&gt;
+                                                        &lt;/dict&gt;
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+
+                                        &lt;!-- A profile which will periodically reset itself, as if a user removed
+                                                and re-added their account. --&gt;
+                                        &lt;dict&gt;
+                                                &lt;key&gt;class&lt;/key&gt;
+                                                &lt;string&gt;simplugin.caldavprofile.Resetter&lt;/string&gt;
+
+                                                &lt;key&gt;params&lt;/key&gt;
+                                                &lt;dict&gt;
+                                                        &lt;key&gt;enabled&lt;/key&gt;
+                                                        &lt;false/&gt;
+
+                                                        &lt;!-- Define the interval (in seconds) at which this profile will
+                                                                reset its client. --&gt;
+                                                        &lt;key&gt;interval&lt;/key&gt;
+                                                        &lt;integer&gt;600&lt;/integer&gt;
+                                                &lt;/dict&gt;
+                                        &lt;/dict&gt;
+
+                                &lt;/array&gt;
+
+                                &lt;!-- Determine the frequency at which this client configuration will
+                                        appear in the clients which are created by the load tester. --&gt;
+                                &lt;key&gt;weight&lt;/key&gt;
+                                &lt;integer&gt;1&lt;/integer&gt;
+                        &lt;/dict&gt;
+                &lt;/array&gt;
+        &lt;/dict&gt;
+&lt;/plist&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginconfigplist"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/config.plist (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/config.plist                                (rev 0)
+++ CalendarServer/trunk/simplugin/config.plist        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,223 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+
+&lt;!--
+    Copyright (c) 2011-2016 Apple Inc. All rights reserved.
+
+    Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+  --&gt;
+
+&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
+&lt;plist version=&quot;1.0&quot;&gt;
+        &lt;dict&gt;
+                &lt;!-- Identify all the servers to be load tested. --&gt;
+                &lt;key&gt;servers&lt;/key&gt;
+                &lt;dict&gt;
+                        &lt;key&gt;PodA&lt;/key&gt;
+                        &lt;dict&gt;
+                                &lt;key&gt;enabled&lt;/key&gt;
+                                &lt;true/&gt;
+
+                                &lt;!-- Identify the server to be load tested. --&gt;
+                                &lt;key&gt;uri&lt;/key&gt;
+                                &lt;string&gt;http://localhost:8008&lt;/string&gt;
+
+                                &lt;key&gt;ampPushHosts&lt;/key&gt;
+                                &lt;array&gt;
+                                        &lt;string&gt;localhost&lt;/string&gt;
+                            &lt;/array&gt;
+                                &lt;key&gt;ampPushPort&lt;/key&gt;
+                                &lt;integer&gt;62311&lt;/integer&gt;
+
+                                &lt;!--  Define whether server supports stats socket. --&gt;
+                                &lt;key&gt;stats&lt;/key&gt;
+                                &lt;dict&gt;
+                                        &lt;key&gt;enabled&lt;/key&gt;
+                                        &lt;true/&gt;
+                                        &lt;key&gt;Port&lt;/key&gt;
+                                        &lt;integer&gt;8100&lt;/integer&gt;
+                                &lt;/dict&gt;
+                        &lt;/dict&gt;
+                        &lt;key&gt;PodB&lt;/key&gt;
+                        &lt;dict&gt;
+                                &lt;key&gt;enabled&lt;/key&gt;
+                                &lt;false/&gt;
+
+                                &lt;!-- Identify the server to be load tested. --&gt;
+                                &lt;key&gt;uri&lt;/key&gt;
+                                &lt;string&gt;https://localhost:8543&lt;/string&gt;
+
+                                &lt;key&gt;ampPushHosts&lt;/key&gt;
+                                &lt;array&gt;
+                                        &lt;string&gt;localhost&lt;/string&gt;
+                            &lt;/array&gt;
+                                &lt;key&gt;ampPushPort&lt;/key&gt;
+                                &lt;integer&gt;62312&lt;/integer&gt;
+
+                                &lt;!--  Define whether server supports stats socket. --&gt;
+                                &lt;key&gt;stats&lt;/key&gt;
+                                &lt;dict&gt;
+                                        &lt;key&gt;enabled&lt;/key&gt;
+                                        &lt;true/&gt;
+                                        &lt;key&gt;Port&lt;/key&gt;
+                                        &lt;integer&gt;8101&lt;/integer&gt;
+                                &lt;/dict&gt;
+                        &lt;/dict&gt;
+                &lt;/dict&gt;
+
+
+                &lt;!-- Configure Admin Web UI. --&gt;
+                &lt;key&gt;webadmin&lt;/key&gt;
+                &lt;dict&gt;
+                        &lt;key&gt;enabled&lt;/key&gt;
+                        &lt;true/&gt;
+
+                        &lt;key&gt;HTTPPort&lt;/key&gt;
+                        &lt;integer&gt;8080&lt;/integer&gt;
+                &lt;/dict&gt;
+
+                &lt;!--  Define whether client data should be re-used. It will always be saved to the specified path.--&gt;
+                &lt;key&gt;clientDataSerialization&lt;/key&gt;
+                &lt;dict&gt;
+                        &lt;key&gt;UseOldData&lt;/key&gt;
+                        &lt;true/&gt;
+                        &lt;key&gt;Path&lt;/key&gt;
+                        &lt;string&gt;/tmp/sim&lt;/string&gt;
+                &lt;/dict&gt;
+
+                &lt;!-- Define the credentials of the clients which will be used to load test
+                        the server. These credentials must already be valid on the server. --&gt;
+                &lt;key&gt;accounts&lt;/key&gt;
+                &lt;dict&gt;
+                        &lt;!-- The loader is the fully-qualified Python name of a callable which
+                                returns a list of directory service records defining all of the client accounts
+                                to use. clientsim.framework.sim.recordsFromCSVFile reads username,
+                                password, mailto triples from a CSV file and returns them as a list of faked
+                                directory service records. --&gt;
+                        &lt;key&gt;loader&lt;/key&gt;
+                        &lt;string&gt;clientsim.framework.sim.recordsFromCSVFile&lt;/string&gt;
+
+                        &lt;!-- Keyword arguments may be passed to the loader. --&gt;
+                        &lt;key&gt;params&lt;/key&gt;
+                        &lt;dict&gt;
+                                &lt;!-- recordsFromCSVFile interprets the path relative to the config.plist,
+                                        to make it independent of the script's working directory while still allowing
+                                        a relative path. This isn't a great solution. --&gt;
+                                &lt;key&gt;path&lt;/key&gt;
+                                &lt;string&gt;clientsim/framework/accounts.csv&lt;/string&gt;
+
+                                &lt;!-- When there are accounts for multiple pods, interleave the accounts for each
+                                        pod so that the arrival mechanism will cycle clients between each pod. --&gt;
+                                &lt;key&gt;interleavePods&lt;/key&gt;
+                                &lt;true/&gt;
+                        &lt;/dict&gt;
+                &lt;/dict&gt;
+
+                &lt;!-- Define how many clients will participate in the load test and how
+                        they will show up. --&gt;
+                &lt;key&gt;arrival&lt;/key&gt;
+                &lt;dict&gt;
+
+                        &lt;!-- Specify a class which creates new clients and introduces them into
+                                the test. clientsim.framework.population.SmoothRampUp introduces
+                                groups of new clients at fixed intervals up to a maximum. The size of the
+                                group, interval, and maximum are configured by the parameters below. The
+                                total number of clients is groups * groupSize, which needs to be no larger
+                                than the number of credentials created in the accounts section. --&gt;
+                        &lt;key&gt;factory&lt;/key&gt;
+                        &lt;string&gt;clientsim.framework.population.SmoothRampUp&lt;/string&gt;
+
+                        &lt;key&gt;params&lt;/key&gt;
+                        &lt;dict&gt;
+                                &lt;!-- groups gives the total number of groups of clients to introduce. --&gt;
+                                &lt;key&gt;groups&lt;/key&gt;
+                                &lt;integer&gt;10&lt;/integer&gt;
+
+                                &lt;!-- groupSize is the number of clients in each group of clients. It's
+                                        really only a &quot;smooth&quot; ramp up if this is pretty small. --&gt;
+                                &lt;key&gt;groupSize&lt;/key&gt;
+                                &lt;integer&gt;3&lt;/integer&gt;
+
+                                &lt;!-- Number of seconds between the introduction of each group. --&gt;
+                                &lt;key&gt;interval&lt;/key&gt;
+                                &lt;integer&gt;3&lt;/integer&gt;
+
+                                &lt;!-- Number of clients each user is assigned to. --&gt;
+                                &lt;!-- Set weight of clients to 1 if this is &gt; 1. Number of clients must match this value if &gt; 1. --&gt;
+                                &lt;key&gt;clientsPerUser&lt;/key&gt;
+                                &lt;integer&gt;1&lt;/integer&gt;
+                        &lt;/dict&gt;
+
+                &lt;/dict&gt;
+
+                &lt;!-- Define some log observers to report on the load test. --&gt;
+                &lt;key&gt;observers&lt;/key&gt;
+                &lt;array&gt;
+                        &lt;!-- ReportStatistics generates an end-of-run summary of the HTTP requests
+                                made, their timings, and their results. --&gt;
+                        &lt;dict&gt;
+                                &lt;key&gt;type&lt;/key&gt;
+                                &lt;string&gt;clientsim.framework.population.ReportStatistics&lt;/string&gt;
+                                &lt;key&gt;params&lt;/key&gt;
+                                &lt;dict&gt;
+                                        &lt;!-- The thresholds for each request type --&gt;
+                                        &lt;key&gt;thresholdsPath&lt;/key&gt;
+                                        &lt;string&gt;clientsim/framework/thresholds.json&lt;/string&gt;
+
+                                        &lt;!-- The benchmarks for overall QoS --&gt;
+                                        &lt;key&gt;benchmarksPath&lt;/key&gt;
+                                        &lt;string&gt;clientsim/framework/benchmarks.json&lt;/string&gt;
+
+                                        &lt;!-- The % of failures that constitute a failed test --&gt;
+                                        &lt;key&gt;failCutoff&lt;/key&gt;
+                                        &lt;real&gt;1.0&lt;/real&gt;
+                                &lt;/dict&gt;
+                        &lt;/dict&gt;
+
+                        &lt;!-- RequestLogger generates a realtime log of all HTTP requests made
+                                during the load test. --&gt;
+                        &lt;dict&gt;
+                                &lt;key&gt;type&lt;/key&gt;
+                                &lt;string&gt;clientsim.framework.baseclient.RequestLogger&lt;/string&gt;
+                                &lt;key&gt;params&lt;/key&gt;
+                                &lt;dict&gt;
+                                &lt;/dict&gt;
+                        &lt;/dict&gt;
+
+                        &lt;!-- OperationLogger generates an end-of-run summary of the gross operations
+                                performed (logical operations which may span more than one HTTP request,
+                                such as inviting an attendee to an event). --&gt;
+                        &lt;dict&gt;
+                                &lt;key&gt;type&lt;/key&gt;
+                                &lt;string&gt;clientsim.framework.baseprofile.OperationLogger&lt;/string&gt;
+                                &lt;key&gt;params&lt;/key&gt;
+                                &lt;dict&gt;
+                                        &lt;!-- The thresholds for each operation type --&gt;
+                                        &lt;key&gt;thresholdsPath&lt;/key&gt;
+                                        &lt;string&gt;clientsim/framework/thresholds.json&lt;/string&gt;
+
+                                        &lt;!-- The % of operations beyond the lag cut-off that constitute a failed test --&gt;
+                                        &lt;key&gt;lagCutoff&lt;/key&gt;
+                                        &lt;real&gt;1.0&lt;/real&gt;
+
+                                        &lt;!-- The % of failures that constitute a failed test --&gt;
+                                        &lt;key&gt;failCutoff&lt;/key&gt;
+                                        &lt;real&gt;1.0&lt;/real&gt;
+
+                                        &lt;!-- There must be at least one push operation --&gt;
+                                        &lt;key&gt;failIfNoPush&lt;/key&gt;
+                                        &lt;true/&gt;
+                                &lt;/dict&gt;
+                        &lt;/dict&gt;
+                &lt;/array&gt;
+        &lt;/dict&gt;
+&lt;/plist&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11Profile"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/Profile (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/Profile                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/Profile        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,267 @@
</span><ins>+PROPFIND ./well-known/caldav                                -&gt;        /principals/
+        current-user-principal
+        principal-URL
+        resourcetype
+
+PROPFIND /principals/                                                -&gt;
+        current-user-principal                                                /principals/__uids__/&lt;uid&gt;
+        principal-URL                                                                ----
+        resourcetype                                                                collection
+
+OPTIONS /principals/__uids__/&lt;uid&gt;/
+
+PROPFIND /principals/__uids__/&lt;uid&gt;/
+        calendar-home-set                                                        /calendars/__uids__/&lt;uid&gt;/
+        calendar-user-address-set                                        mailto:user#@example.com
+                                                                                                urn:uuid:&lt;uid&gt;
+                                                                                                urn:x-uid:&lt;uid&gt;
+        current-user-principal                                                /principals/__uids__/&lt;uid&gt;/
+        displayname                                                                        User #
+        dropbox-home-URL                                                        /calendars/__uids__/&lt;uid&gt;/dropbox/
+        email-address-set                                                        user#@example.com
+        notification-URL                                                        /calendars/__uids__/&lt;uid&gt;/notification/
+        principal-collection-set                                        /principals/
+        principal-URL                                                                /principals/__uids__/&lt;uid&gt;/
+        resource-id                                                                        urn:x-uid:&lt;uid&gt;
+        schedule-inbox-URL                                                        /calendars/__uids__/&lt;uid&gt;/inbox/
+        schedule-outbox-URL                                                        /calendars/__uids__/&lt;uid&gt;/outbox/
+        supported-report-set                                                acl-principal-prop-set
+                                                                                                principal-match
+                                                                                                principal-property-search
+                                                                                                expand-property
+                                                                                                calendarserver-principal-search
+
+OPTIONS /principals/__uids__/&lt;uid&gt;
+
+REPORT /principals/                                                        -&gt; 
+        principal-search-property-set                                displayname
+                                                                                                email-address-set
+                                                                                                calendar-user-address-set
+                                                                                                calendar-user-type 
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/inbox/        -&gt;        
+        calendar-availability                                                ???
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/
+Depth 1
+        add-member                                                                        
+        allowed-sharing-modes                                                                        
+        autoprovisioned                                                                        
+        bulk-requests                                                                        
+        calendar-alarm                                                                        
+        calendar-color                                                                        
+        calendar-description                                                                        
+        calendar-free-busy-set                                                                        
+        calendar-order                                                                        
+        calendar-timezone                                                                        
+        current-user-privilege-set                                        all/read/read-free-busy/write/write-properties/write-content/bind/unbind/unlock/read-acl/write-acl/read-current-user-privilege-set                                
+        default-alarm-vevent-date                                                                        
+        default-alarm-vevent-datetime                                                                        
+        displayname                                                                        User #
+        getctag                                                                        
+        invite                                                                        
+        language-code                                                                        
+        location-code                                                                        
+        owner                                                                                /principals/__uids__/&lt;uid&gt;/
+        pre-publish-url                                                                        
+        publish-url                                                                        
+        push-transports                                                                        
+        pushkey                                                                                /CalDAV/localhost/&lt;uid&gt;/
+        quota-available-bytes                                                104857600
+        quota-used-bytes                                                        0
+        refreshrate                                                                        
+        resource-id                                                                        
+        resourcetype                                                                collection        
+        schedule-calendar-transp                                                                        
+        schedule-default-calendar-URL                                                                        
+        source                                                                        
+        subscribed-strip-alarms                                                                        
+        subscribed-strip-attachments                                                                        
+        subscribed-strip-todos                                                                        
+        supported-calendar-component-set                        VEVENT/VTODO                                                
+        supported-calendar-component-sets                                                                        
+        supported-report-set                                                acl-principal-prop-set/principal-match/principal-property-search/expand-property/calendarserver-principal-search/calendar-query/calendar-multiget/free-busy-query/addressbook-query/addressbook-multiget/sync-collection                        
+        sync-token                                                                        data:,36_58/&lt;hex&gt;
+         ** and more **
+
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/                -&gt;                default-alarm-vevent-date
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/                -&gt;                default-alarm-vevent-datetime
+
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/calendar/        -&gt;                calendar-order
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/calendar/        -&gt;                displayname
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/calendar/        -&gt;                calendar-color
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/calendar/        -&gt;                calendar-order
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/calendar/        -&gt;                calendar-timezone
+
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/tasks/        -&gt;                calendar-order
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/tasks/        -&gt;                displayname
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/tasks/        -&gt;                calendar-color
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/tasks/        -&gt;                calendar-order
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/tasks/        -&gt;                calendar-timezone
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/calendar/-&gt;
+        getctag                                                                                37_63
+        sync-token                                                                        data:,37_63/&lt;hex&gt;
+
+REPORT /calendars/__uids__/&lt;uid&gt;/calendar/         -&gt;
+        getcontenttype
+        getetag
+REPORT /calendar/__uids__/&lt;uid&gt;/calendar/
+        getcontenttype
+        getetag
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/                        -&gt;
+        checksum-versions                                                        ???
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/calendar/        -&gt;
+        getctag                                                                                
+        sync-token                                                                                
+PROPFIND /calendars/__uids__/&lt;uid&gt;/calendar/
+        getcontenttype                                                                httpd/unix-directory
+        getetag                                                                                &quot;&lt;hex&gt;&quot;
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/                        -&gt; (again?) 
+        checksum-versions
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/tasks/        -&gt;
+        getctag
+        sync-token
+PROPFIND /calendars/__uids__/&lt;uid&gt;/tasks/        -&gt;
+        getcontenttype
+        getetag
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/inbox/        -&gt;
+        getctag
+        sync-token
+PROPFIND /calendars/__uids__/&lt;uid&gt;/inbox/        -&gt;
+        getcontenttype
+        getetag
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/tasks/        -&gt;
+        getctag
+        sync-token
+PROPFIND /calendars/__uids__/&lt;uid&gt;/tasks/        -&gt;
+        getcontenttype
+        getetag
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/notification/        -&gt;
+        getctag
+        sync-token
+PROPFIND /calendars/__uids__/&lt;uid&gt;/notification/        -&gt;
+        notificationtype
+        getetag
+
+REPORT /principals/__uids__/&lt;uid&gt;/
+        calendar-proxy-write-for
+                calendar-user-address-set
+                email-address-set
+                displayname
+        calendar-proxy-read-for
+                calendar-user-address-set
+                email-address-set
+                displayname
+
+REPORT /calendars/__uids__/&lt;uid&gt;/
+        sync-collection
+                sync-token
+                sync-level
+                *lots of properties*
+
+PROPFIND /calendars/__uids__/&lt;uid&gt;/inbox/
+        getctag
+        sync-token
+
+PROPFIND /principals/__uids__/&lt;uid&gt;/
+        calendar-proxy-write-for
+                calendar-user-address-set
+                email-address-set
+                displayname
+        calendar-proxy-read-for
+                calendar-user-address-set
+                email-address-set
+                displayname
+
+----------------------------------------------------------------
+Deep Refresh (CMD + SHIFT + R)
+
+PROPFIND /principals/__uids__/&lt;uid&gt;/
+        &lt;B:calendar-home-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:calendar-user-address-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:displayname/&gt;
+    &lt;C:dropbox-home-URL xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:email-address-set xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:notification-URL xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:principal-collection-set/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;B:schedule-inbox-URL xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:schedule-outbox-URL xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+
+OPTIONS /principals/__uids__/10000000-0000-0000-0000-000000000001/
+
+REPORT /principals/
+        principal-search-property-set
+
+PROPFIND /calendars/__uids__/10000000-0000-0000-0000-000000000001/inbox/
+        calendar-availability
+
+PROPFIND /calendars/__uids__/10000000-0000-0000-0000-000000000001/
+Depth 1
+        &lt;A:add-member/&gt;
+    &lt;C:allowed-sharing-modes xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;D:autoprovisioned xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;E:bulk-requests xmlns:E=&quot;http://me.com/_namespace/&quot;/&gt;
+    &lt;B:calendar-alarm xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;D:calendar-color xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;B:calendar-description xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:calendar-free-busy-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;D:calendar-order xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;B:calendar-timezone xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-privilege-set/&gt;
+    &lt;B:default-alarm-vevent-date xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:default-alarm-vevent-datetime xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:displayname/&gt;
+    &lt;C:getctag xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:invite xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;D:language-code xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;D:location-code xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;A:owner/&gt;
+    &lt;C:pre-publish-url xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:publish-url xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:push-transports xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:pushkey xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:quota-available-bytes/&gt;
+    &lt;A:quota-used-bytes/&gt;
+    &lt;D:refreshrate xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;A:resourcetype/&gt;
+    &lt;B:schedule-calendar-transp xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:schedule-default-calendar-URL xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:source xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-alarms xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-attachments xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-todos xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:supported-calendar-component-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:supported-calendar-component-sets xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+    &lt;A:sync-token/&gt;
+
+PROPFIND on calendar/tasks/inbox/notifications as before
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11StartupProfile"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/StartupProfile (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/StartupProfile                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/StartupProfile        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,71 @@
</span><ins>+PROPFIND  ./well-known/caldav                                        - startup_well_known_propfind
+
+PROPFIND  /principals/                                                        - startup_principal_initial_propfind
+
+PROPFIND  /principals/__uids__/&lt;uid&gt;/                        - startup_principal_propfind
+
+REPORT    /principals/                                                        - startup_principals_report
+
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/inbox/                - ???
+        calendar-availability                                                
+
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/                        - poll_calendar_home_depth1_propfind
+
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/                        - startup_calendarhome_default_alarm_date_proppatch
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/                        - startup_calendarhome_default_alarm_datetime_proppatch
+
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/calendar/        - startup_calendar_order_proppatch
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/calendar/        - startup_calendar_displayname_proppatch
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/calendar/        - startup_calendar_color_proppatch
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/calendar/        - startup_calendar_timezone_proppatch
+
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/tasks/                - startup_calendar_order_proppatch
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/tasks/                - startup_calendar_displayname_proppatch
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/tasks/                - startup_calendar_color_proppatch
+PROPPATCH /calendars/__uids__/&lt;uid&gt;/tasks/                - startup_calendar_timezone_proppatch
+
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/calendar/        - poll_calendar_propfind
+
+REPORT   /calendars/__uids__/&lt;uid&gt;/calendar/         - startup_query_events_depth1_report.request
+
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/calendar/        - poll_calendar_propfind
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/calendar/        - poll_calendar_depth1_propfind
+
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/tasks/                - poll_calendar_propfind
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/tasks/                - poll_calendar_depth1_propfind
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/inbox/                - poll_calendar_propfind
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/inbox/                - poll_calendar_depth1_propfind
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/tasks/                - poll_calendar_propfind
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/tasks/                - poll_calendar_depth1_propfind
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/notification/        - poll_calendar_propfind
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/notification/        - poll_notification_depth1_propfind
+
+REPORT    /principals/__uids__/&lt;uid&gt;/
+        calendar-proxy-write-for
+                calendar-user-address-set
+                email-address-set
+                displayname
+        calendar-proxy-read-for
+                calendar-user-address-set
+                email-address-set
+                displayname
+
+REPORT    /calendars/__uids__/&lt;uid&gt;/
+        sync-collection
+                sync-token
+                sync-level
+                *lots of properties*
+
+PROPFIND  /calendars/__uids__/&lt;uid&gt;/inbox/
+        getctag
+        sync-token
+
+PROPFIND  /principals/__uids__/&lt;uid&gt;/
+        calendar-proxy-write-for
+                calendar-user-address-set
+                email-address-set
+                displayname
+        calendar-proxy-read-for
+                calendar-user-address-set
+                email-address-set
+                displayname
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11notification_multiget_report_hrefsrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/notification_multiget_report_hrefs.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/notification_multiget_report_hrefs.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/notification_multiget_report_hrefs.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1 @@
</span><ins>+  &lt;A:href xmlns:A=&quot;DAV:&quot;&gt;%(href)s&lt;/A:href&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11notification_syncrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/notification_sync.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/notification_sync.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/notification_sync.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:sync-collection xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:sync-token&gt;%(sync-token)s&lt;/A:sync-token&gt;
+  &lt;A:sync-level&gt;1&lt;/A:sync-level&gt;
+  &lt;A:prop&gt;
+    &lt;C:notificationtype xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:getetag/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:sync-collection&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11poll_calendar_depth1_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendar_depth1_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendar_depth1_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendar_depth1_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:getcontenttype/&gt;
+    &lt;A:getetag/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11poll_calendar_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendar_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendar_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendar_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;C:getctag xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:sync-token/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11poll_calendarhome_depth1_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendarhome_depth1_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendarhome_depth1_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendarhome_depth1_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:add-member/&gt;
+    &lt;C:allowed-sharing-modes xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;D:autoprovisioned xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;E:bulk-requests xmlns:E=&quot;http://me.com/_namespace/&quot;/&gt;
+    &lt;B:calendar-alarm xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;D:calendar-color xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;B:calendar-description xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:calendar-free-busy-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;D:calendar-order xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;B:calendar-timezone xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-privilege-set/&gt;
+    &lt;B:default-alarm-vevent-date xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:default-alarm-vevent-datetime xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:displayname/&gt;
+    &lt;C:getctag xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:invite xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;D:language-code xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;D:location-code xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;A:owner/&gt;
+    &lt;C:pre-publish-url xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:publish-url xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:push-transports xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:pushkey xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:quota-available-bytes/&gt;
+    &lt;A:quota-used-bytes/&gt;
+    &lt;D:refreshrate xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;A:resourcetype/&gt;
+    &lt;B:schedule-calendar-transp xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:schedule-default-calendar-URL xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:source xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-alarms xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-attachments xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-todos xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:supported-calendar-component-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:supported-calendar-component-sets xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+    &lt;A:sync-token/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11poll_calendarhome_syncrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendarhome_sync.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendarhome_sync.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_calendarhome_sync.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:sync-collection xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:sync-token&gt;data:,30_1122/8bbf7c540e5fca2cc3220f114a8164f7&lt;/A:sync-token&gt;
+  &lt;A:sync-level&gt;1&lt;/A:sync-level&gt;
+  &lt;A:prop&gt;
+    &lt;C:publish-url xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:supported-calendar-component-sets xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:schedule-calendar-transp xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:source xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:calendar-description xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;D:location-code xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;D:autoprovisioned xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;A:quota-used-bytes/&gt;
+    &lt;C:pre-publish-url xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;D:calendar-order xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;D:refreshrate xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;C:subscribed-strip-attachments xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:push-transports xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:schedule-default-calendar-URL xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:calendar-alarm xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:supported-calendar-component-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:owner/&gt;
+    &lt;A:add-member/&gt;
+    &lt;C:invite xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;E:bulk-requests xmlns:E=&quot;http://me.com/_namespace/&quot;/&gt;
+    &lt;B:calendar-timezone xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+    &lt;A:displayname/&gt;
+    &lt;C:subscribed-strip-alarms xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;D:language-code xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;C:subscribed-strip-todos xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:allowed-sharing-modes xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:current-user-privilege-set/&gt;
+    &lt;B:calendar-free-busy-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:sync-token/&gt;
+    &lt;A:quota-available-bytes/&gt;
+    &lt;C:pushkey xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:default-alarm-vevent-date xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:resourcetype/&gt;
+    &lt;B:default-alarm-vevent-datetime xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;D:calendar-color xmlns:D=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;C:getctag xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:sync-collection&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11poll_notification_depth1_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_notification_depth1_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_notification_depth1_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/poll_notification_depth1_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:getetag/&gt;
+    &lt;C:notificationtype xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11post_freebusyrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/post_freebusy.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/post_freebusy.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/post_freebusy.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+BEGIN:VCALENDAR
+VERSION:2.0
+METHOD:REPLY
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+BEGIN:VFREEBUSY
+UID:4288F0F3-5C5B-4DF4-9AD8-B1E5FE3F5B97
+DTSTART:20150804T211500Z
+DTEND:20150804T231500Z
+ATTENDEE:urn:uuid:30000000-0000-0000-0000-000000000005
+DTSTAMP:20150727T203410Z
+ORGANIZER:mailto:user01@example.com
+END:VFREEBUSY
+END:VCALENDAR
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11principal_search_reportrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/principal_search_report.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/principal_search_report.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/principal_search_report.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;C:calendarserver-principal-search xmlns:C=&quot;http://calendarserver.org/ns/&quot; context=&quot;{context}&quot;&gt;
+  {searchTokens}
+  &lt;A:prop xmlns:A=&quot;DAV:&quot;&gt;
+    &lt;C:email-address-set/&gt;
+    &lt;B:calendar-user-type xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:calendar-user-address-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;C:last-name/&gt;
+    &lt;C:record-type/&gt;
+    &lt;A:displayname/&gt;
+    &lt;C:first-name/&gt;
+  &lt;/A:prop&gt;
+&lt;/C:calendarserver-principal-search&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11report_principal_searchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/report_principal_search.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/report_principal_search.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/report_principal_search.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;C:calendarserver-principal-search xmlns:C=&quot;http://calendarserver.org/ns/&quot; context=&quot;attendee&quot;&gt;
+  &lt;C:search-token&gt;%(search)s&lt;/C:search-token&gt;
+  &lt;A:prop xmlns:A=&quot;DAV:&quot;&gt;
+    &lt;B:calendar-user-type xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:email-address-set/&gt;
+    &lt;A:displayname/&gt;
+    &lt;C:first-name/&gt;
+    &lt;C:last-name/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;C:record-type/&gt;
+    &lt;B:calendar-user-address-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+  &lt;/A:prop&gt;
+&lt;/C:calendarserver-principal-search&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_color_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_color_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_color_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_color_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;D:calendar-color xmlns:D=&quot;http://apple.com/ns/ical/&quot; symbolic-color=&quot;orange&quot;&gt;#FD8208FF&lt;/D:calendar-color&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_description_proppatchrequestxml"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_description_proppatch.request.xml (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_description_proppatch.request.xml                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_description_proppatch.request.xml        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;B:calendar-description xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;some description&lt;/B:calendar-description&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_displayname_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_displayname_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_displayname_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_displayname_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;A:displayname&gt;calendar&lt;/A:displayname&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_order_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_order_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_order_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_order_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;D:calendar-order xmlns:D=&quot;http://apple.com/ns/ical/&quot;&gt;1&lt;/D:calendar-order&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_timezone_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_timezone_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_timezone_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_timezone_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;B:calendar-timezone xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;BEGIN:VCALENDAR&amp;#13;
+VERSION:2.0&amp;#13;
+PRODID:-//Apple Inc.//Mac OS X 10.11//EN&amp;#13;
+CALSCALE:GREGORIAN&amp;#13;
+BEGIN:VTIMEZONE&amp;#13;
+TZID:America/Los_Angeles&amp;#13;
+BEGIN:DAYLIGHT&amp;#13;
+TZOFFSETFROM:-0800&amp;#13;
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU&amp;#13;
+DTSTART:20070311T020000&amp;#13;
+TZNAME:PDT&amp;#13;
+TZOFFSETTO:-0700&amp;#13;
+END:DAYLIGHT&amp;#13;
+BEGIN:STANDARD&amp;#13;
+TZOFFSETFROM:-0700&amp;#13;
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU&amp;#13;
+DTSTART:20071104T020000&amp;#13;
+TZNAME:PST&amp;#13;
+TZOFFSETTO:-0800&amp;#13;
+END:STANDARD&amp;#13;
+END:VTIMEZONE&amp;#13;
+END:VCALENDAR&amp;#13;
+&lt;/B:calendar-timezone&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendar_transparent_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_transparent_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_transparent_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendar_transparent_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;B:schedule-calendar-transp xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;&lt;B:transparent/&gt;&lt;/B:schedule-calendar-transp&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
+
+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;B:schedule-calendar-transp xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;&lt;B:opaque/&gt;&lt;/B:schedule-calendar-transp&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendarhome_default_alarm_date_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendarhome_default_alarm_date_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendarhome_default_alarm_date_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendarhome_default_alarm_date_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;B:default-alarm-vevent-date xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;BEGIN:VALARM&amp;#13;
+X-WR-ALARMUID:49F29226-D2D7-4464-AE22-0147EDEFB2B4&amp;#13;
+UID:49F29226-D2D7-4464-AE22-0147EDEFB2B4&amp;#13;
+TRIGGER:-PT15H&amp;#13;
+ATTACH;VALUE=URI:Basso&amp;#13;
+ACTION:AUDIO&amp;#13;
+END:VALARM&amp;#13;
+&lt;/B:default-alarm-vevent-date&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_calendarhome_default_alarm_datetime_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendarhome_default_alarm_datetime_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendarhome_default_alarm_datetime_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_calendarhome_default_alarm_datetime_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;B:default-alarm-vevent-datetime xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;BEGIN:VALARM&amp;#13;
+X-WR-ALARMUID:4AD03A33-54A6-42BE-A157-47273DD60803&amp;#13;
+UID:4AD03A33-54A6-42BE-A157-47273DD60803&amp;#13;
+TRIGGER;VALUE=DATE-TIME:19760401T005545Z&amp;#13;
+ACTION:NONE&amp;#13;
+END:VALARM&amp;#13;
+&lt;/B:default-alarm-vevent-datetime&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_create_calendarrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_create_calendar.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_create_calendar.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_create_calendar.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;B:mkcalendar xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;
+  &lt;A:set xmlns:A=&quot;DAV:&quot;&gt;
+    &lt;A:prop&gt;
+      &lt;D:calendar-order xmlns:D=&quot;http://apple.com/ns/ical/&quot;&gt;{order}&lt;/D:calendar-order&gt;
+      &lt;B:supported-calendar-component-set&gt;
+        &lt;B:comp name=&quot;{component_type}&quot;/&gt;
+      &lt;/B:supported-calendar-component-set&gt;
+      &lt;D:calendar-color xmlns:D=&quot;http://apple.com/ns/ical/&quot; symbolic-color=&quot;custom&quot;&gt;#{color}&lt;/D:calendar-color&gt;
+      &lt;B:calendar-timezone&gt;BEGIN:VCALENDAR&amp;#13;
+VERSION:2.0&amp;#13;
+PRODID:-//Apple Inc.//Mac OS X 10.11//EN&amp;#13;
+CALSCALE:GREGORIAN&amp;#13;
+BEGIN:VTIMEZONE&amp;#13;
+TZID:America/Los_Angeles&amp;#13;
+BEGIN:DAYLIGHT&amp;#13;
+TZOFFSETFROM:-0800&amp;#13;
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU&amp;#13;
+DTSTART:20070311T020000&amp;#13;
+TZNAME:PDT&amp;#13;
+TZOFFSETTO:-0700&amp;#13;
+END:DAYLIGHT&amp;#13;
+BEGIN:STANDARD&amp;#13;
+TZOFFSETFROM:-0700&amp;#13;
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU&amp;#13;
+DTSTART:20071104T020000&amp;#13;
+TZNAME:PST&amp;#13;
+TZOFFSETTO:-0800&amp;#13;
+END:STANDARD&amp;#13;
+END:VTIMEZONE&amp;#13;
+END:VCALENDAR&amp;#13;
+&lt;/B:calendar-timezone&gt;
+      &lt;A:displayname&gt;{name}&lt;/A:displayname&gt;
+      &lt;B:schedule-calendar-transp&gt;
+        &lt;B:opaque/&gt;
+      &lt;/B:schedule-calendar-transp&gt;
+    &lt;/A:prop&gt;
+  &lt;/A:set&gt;
+&lt;/B:mkcalendar&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_delegate_principal_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_delegate_principal_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_delegate_principal_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_delegate_principal_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;B:allowed-calendar-component-set xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:calendar-home-set xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:calendar-user-address-set xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:displayname/&gt;
+    &lt;B:dropbox-home-URL xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:email-address-set xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:notification-URL xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:principal-collection-set/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;C:schedule-inbox-URL xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:schedule-outbox-URL xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_principal_expandrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_expand.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_expand.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_expand.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:expand-property xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:property name=&quot;calendar-proxy-read-for&quot; namespace=&quot;http://calendarserver.org/ns/&quot;&gt;
+    &lt;A:property name=&quot;calendar-user-address-set&quot; namespace=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:property name=&quot;email-address-set&quot; namespace=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:property name=&quot;displayname&quot; namespace=&quot;DAV:&quot;/&gt;
+  &lt;/A:property&gt;
+  &lt;A:property name=&quot;calendar-proxy-write-for&quot; namespace=&quot;http://calendarserver.org/ns/&quot;&gt;
+    &lt;A:property name=&quot;calendar-user-address-set&quot; namespace=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:property name=&quot;email-address-set&quot; namespace=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:property name=&quot;displayname&quot; namespace=&quot;DAV:&quot;/&gt;
+  &lt;/A:property&gt;
+&lt;/A:expand-property&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_principal_initial_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_initial_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_initial_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_initial_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resourcetype/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_principal_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principal_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;B:calendar-home-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:calendar-user-address-set xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:displayname/&gt;
+    &lt;C:dropbox-home-URL xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:email-address-set xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:notification-URL xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:principal-collection-set/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;B:schedule-inbox-URL xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:schedule-outbox-URL xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_principals_reportrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principals_report.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principals_report.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_principals_report.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:principal-search-property-set xmlns:A=&quot;DAV:&quot;/&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_query_events_depth1_reportrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_query_events_depth1_report.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_query_events_depth1_report.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_query_events_depth1_report.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;B:calendar-query xmlns:B=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;
+  &lt;A:prop xmlns:A=&quot;DAV:&quot;&gt;
+    &lt;A:getetag/&gt;
+    &lt;A:getcontenttype/&gt;
+  &lt;/A:prop&gt;
+  &lt;B:filter&gt;
+    &lt;B:comp-filter name=&quot;VCALENDAR&quot;&gt;
+      &lt;B:comp-filter name=&quot;VEVENT&quot;&gt;
+        &lt;B:time-range start=&quot;20150630T010101Z&quot; end=&quot;20150721T010101Z&quot;/&gt;
+      &lt;/B:comp-filter&gt;
+    &lt;/B:comp-filter&gt;
+  &lt;/B:filter&gt;
+&lt;/B:calendar-query&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_11startup_well_known_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_well_known_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_well_known_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_11/startup_well_known_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resourcetype/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6poll_calendar_multigetrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_multiget.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_multiget.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_multiget.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
+&lt;x0:calendar-multiget xmlns:x0=&quot;urn:ietf:params:xml:ns:caldav&quot; xmlns:x1=&quot;DAV:&quot;&gt;
+  &lt;x1:prop&gt;
+    &lt;x1:getetag/&gt;
+    &lt;x0:calendar-data/&gt;
+    &lt;x0:schedule-tag/&gt;
+  &lt;/x1:prop&gt;
+%(hrefs)s
+&lt;/x0:calendar-multiget&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6poll_calendar_multiget_hrefsrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_multiget_hrefs.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_multiget_hrefs.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_multiget_hrefs.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1 @@
</span><ins>+  &lt;x1:href&gt;%(href)s&lt;/x1:href&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6poll_calendar_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;B:getctag xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:sync-token/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6poll_calendar_propfind_d1request"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_propfind_d1.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_propfind_d1.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendar_propfind_d1.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;x0:propfind xmlns:x0=&quot;DAV:&quot; xmlns:x1=&quot;http://calendarserver.org/ns/&quot;&gt;
+ &lt;x0:prop&gt;
+  &lt;x0:getetag/&gt;
+  &lt;x0:resourcetype/&gt;
+  &lt;x1:notificationtype/&gt;
+ &lt;/x0:prop&gt;
+&lt;/x0:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6poll_calendarhome_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendarhome_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendarhome_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_calendarhome_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;x0:propfind xmlns:x0=&quot;DAV:&quot; xmlns:x3=&quot;http://apple.com/ns/ical/&quot; xmlns:x1=&quot;http://calendarserver.org/ns/&quot; xmlns:x2=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;
+ &lt;x0:prop&gt;
+  &lt;x1:xmpp-server/&gt;
+  &lt;x1:xmpp-uri/&gt;
+  &lt;x1:getctag/&gt;
+  &lt;x0:displayname/&gt;
+  &lt;x2:calendar-description/&gt;
+  &lt;x3:calendar-color/&gt;
+  &lt;x3:calendar-order/&gt;
+  &lt;x2:supported-calendar-component-set/&gt;
+  &lt;x0:resourcetype/&gt;
+  &lt;x0:owner/&gt;
+  &lt;x2:calendar-free-busy-set/&gt;
+  &lt;x2:schedule-calendar-transp/&gt;
+  &lt;x2:schedule-default-calendar-URL/&gt;
+  &lt;x0:quota-available-bytes/&gt;
+  &lt;x0:quota-used-bytes/&gt;
+  &lt;x2:calendar-timezone/&gt;
+  &lt;x0:current-user-privilege-set/&gt;
+  &lt;x1:source/&gt;
+  &lt;x1:subscribed-strip-alarms/&gt;
+  &lt;x1:subscribed-strip-attachments/&gt;
+  &lt;x1:subscribed-strip-todos/&gt;
+  &lt;x3:refreshrate/&gt;
+  &lt;x1:push-transports/&gt;
+  &lt;x1:pushkey/&gt;
+  &lt;x1:publish-url/&gt;
+ &lt;/x0:prop&gt;
+&lt;/x0:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6poll_notification_propfind_d1request"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_notification_propfind_d1.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_notification_propfind_d1.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/poll_notification_propfind_d1.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:getetag/&gt;
+    &lt;B:notificationtype xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6post_availabilityrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/post_availability.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/post_availability.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/post_availability.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+METHOD:REQUEST
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+BEGIN:VFREEBUSY
+UID:%(vfreebusy-uid)s
+DTEND:%(end)s
+%(attendees)sDTSTART:%(start)s
+%(event-mask)sDTSTAMP:%(now)s
+ORGANIZER:%(organizer)s
+SUMMARY:%(summary)s
+END:VFREEBUSY
+END:VCALENDAR
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6startup_calendar_color_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_color_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_color_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_color_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;E:calendar-color xmlns:E=&quot;http://apple.com/ns/ical/&quot;&gt;#882F00FF&lt;/E:calendar-color&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6startup_calendar_order_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_order_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_order_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_order_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;E:calendar-order xmlns:E=&quot;http://apple.com/ns/ical/&quot;&gt;1&lt;/E:calendar-order&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6startup_calendar_timezone_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_timezone_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_timezone_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_calendar_timezone_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;C:calendar-timezone xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;BEGIN:VCALENDAR&amp;#13;
+VERSION:2.0&amp;#13;
+PRODID:-//Apple Inc.//iCal 5.0.2//EN&amp;#13;
+CALSCALE:GREGORIAN&amp;#13;
+BEGIN:VTIMEZONE&amp;#13;
+TZID:America/New_York&amp;#13;
+BEGIN:DAYLIGHT&amp;#13;
+TZOFFSETFROM:-0500&amp;#13;
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU&amp;#13;
+DTSTART:20070311T020000&amp;#13;
+TZNAME:EDT&amp;#13;
+TZOFFSETTO:-0400&amp;#13;
+END:DAYLIGHT&amp;#13;
+BEGIN:STANDARD&amp;#13;
+TZOFFSETFROM:-0400&amp;#13;
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU&amp;#13;
+DTSTART:20071104T020000&amp;#13;
+TZNAME:EST&amp;#13;
+TZOFFSETTO:-0500&amp;#13;
+END:STANDARD&amp;#13;
+END:VTIMEZONE&amp;#13;
+END:VCALENDAR&amp;#13;
+&lt;/C:calendar-timezone&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6startup_notification_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_notification_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_notification_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_notification_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;x0:propfind xmlns:x0=&quot;DAV:&quot; xmlns:x1=&quot;http://calendarserver.org/ns/&quot;&gt;
+ &lt;x0:prop&gt;
+  &lt;x0:getetag/&gt;
+  &lt;x0:resourcetype/&gt;
+  &lt;x1:notificationtype/&gt;
+ &lt;/x0:prop&gt;
+&lt;/x0:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6startup_principal_expandrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_expand.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_expand.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_expand.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
+&lt;x0:expand-property xmlns:x0=&quot;DAV:&quot;&gt;&lt;x0:property name=&quot;calendar-proxy-write-for&quot; namespace=&quot;http://calendarserver.org/ns/&quot;&gt;&lt;x0:property name=&quot;displayname&quot;/&gt;&lt;x0:property name=&quot;principal-URL&quot;/&gt;&lt;x0:property name=&quot;calendar-user-address-set&quot; namespace=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;&lt;/x0:property&gt;&lt;x0:property name=&quot;calendar-proxy-read-for&quot; namespace=&quot;http://calendarserver.org/ns/&quot;&gt;&lt;x0:property name=&quot;displayname&quot;/&gt;&lt;x0:property name=&quot;principal-URL&quot;/&gt;&lt;x0:property name=&quot;calendar-user-address-set&quot; namespace=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;&lt;/x0:property&gt;&lt;/x0:expand-property&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6startup_principal_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;x0:propfind xmlns:x1=&quot;urn:ietf:params:xml:ns:caldav&quot; xmlns:x0=&quot;DAV:&quot; xmlns:x2=&quot;http://calendarserver.org/ns/&quot;&gt;
+ &lt;x0:prop&gt;
+  &lt;x0:principal-collection-set/&gt;
+  &lt;x1:calendar-home-set/&gt;
+  &lt;x1:calendar-user-address-set/&gt;
+  &lt;x1:schedule-inbox-URL/&gt;
+  &lt;x1:schedule-outbox-URL/&gt;
+  &lt;x2:dropbox-home-URL/&gt;
+  &lt;x2:xmpp-uri/&gt;
+  &lt;x2:notification-URL/&gt;
+  &lt;x0:displayname/&gt;
+  &lt;x0:principal-URL/&gt;
+  &lt;x0:supported-report-set/&gt;
+ &lt;/x0:prop&gt;
+&lt;/x0:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6startup_principal_propfind_initialrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_propfind_initial.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_propfind_initial.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principal_propfind_initial.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resourcetype/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6startup_principals_reportrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principals_report.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principals_report.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_principals_report.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
+&lt;x0:principal-search-property-set xmlns:x0=&quot;DAV:&quot;/&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6startup_well_knownrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_well_known.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_well_known.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/startup_well_known.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resourcetype/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_6user_list_principal_property_searchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_6/user_list_principal_property_search.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_6/user_list_principal_property_search.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_6/user_list_principal_property_search.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
+&lt;x0:principal-property-search xmlns:x2=&quot;urn:ietf:params:xml:ns:caldav&quot; xmlns:x0=&quot;DAV:&quot; xmlns:x1=&quot;http://calendarserver.org/ns/&quot; test=&quot;anyof&quot;&gt;&lt;x0:property-search&gt;&lt;x0:prop&gt;&lt;x0:displayname/&gt;&lt;/x0:prop&gt;&lt;x0:match match-type=&quot;starts-with&quot;&gt;%(displayname)s&lt;/x0:match&gt;&lt;/x0:property-search&gt;&lt;x0:property-search&gt;&lt;x0:prop&gt;&lt;x1:email-address-set/&gt;&lt;/x0:prop&gt;&lt;x0:match match-type=&quot;starts-with&quot;&gt;%(email)s&lt;/x0:match&gt;&lt;/x0:property-search&gt;&lt;x0:property-search&gt;&lt;x0:prop&gt;&lt;x1:first-name/&gt;&lt;/x0:prop&gt;&lt;x0:match match-type=&quot;starts-with&quot;&gt;%(firstname)s&lt;/x0:match&gt;&lt;/x0:property-search&gt;&lt;x0:property-search&gt;&lt;x0:prop&gt;&lt;x1:last-name/&gt;&lt;/x0:prop&gt;&lt;x0:match match-type=&quot;starts-with&quot;&gt;%(lastname)s&lt;/x0:match&gt;&lt;/x0:property-search&gt;&lt;x0:prop&gt;&lt;x1:email-address-set/&gt;&lt;x2
 :calendar-user-address-set/&gt;&lt;x2:calendar-user-type/&gt;&lt;x0:displayname/&gt;&lt;x1:last-name/&gt;&lt;x1:first-name/&gt;&lt;x1:record-type/&gt;&lt;x0:principal-URL/&gt;&lt;/x0:prop&gt;&lt;/x0:principal-property-search&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7Profile"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/Profile (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/Profile                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/Profile        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+** Initial account setup
+
+PROPFIND well-known unauthorized        - startup_well_known.request
+PROPFIND / unauthorized                    - startup_well_known.request
+HEAD well-known unauthorized
+PROPFIND / unauthorized                    - startup_well_known.request
+HEAD / unauthorized
+PROPFIND / unauthorized                                - startup_well_known.request
+PROPFIND /calendar/dav/user01/user/ unauthorized        - startup_principal_propfind_initial.request
+PROPFIND /principals/users/user01/ unauthorized                - startup_principal_propfind_initial.request
+PROPFIND /principals/users/user01/                                        - startup_principal_propfind_initial.request
+
+PROPFIND /principals/users/user01/ unauthorized                - startup_principal_propfind.request
+PROPFIND /principals/users/user01/                                        - startup_principal_propfind.request
+OPTIONS /principals/__uids__/user01/
+
+PROPFIND /principals/users/user01/                            - startup_principal_propfind.request
+OPTIONS /principals/__uids__/user01/
+
+REPORT /principals/ unauthorized                                        - startup_principals_report.request
+REPORT /principals/                                                                        - startup_principals_report.request
+
+PROPFIND /calendars/__uids__/user01/ unauthorized        - poll_calendarhome_propfind.request
+PROPFIND /calendars/__uids__/user01/                                - poll_calendarhome_propfind.request
+
+PROPPATCH /calendars/__uids__/user01/tasks/                 - startup_calendar_color_proppatch.request
+PROPPATCH /calendars/__uids__/user01/tasks/                 - startup_calendar_order_proppatch.request
+PROPPATCH /calendars/__uids__/user01/tasks/                 - startup_calendar_timezone_proppatch.request
+
+PROPPATCH /calendars/__uids__/user01/calendar/                 - startup_calendar_color_proppatch.request
+PROPPATCH /calendars/__uids__/user01/calendar/                 - startup_calendar_order_proppatch.request
+PROPPATCH /calendars/__uids__/user01/calendar/                 - startup_calendar_timezone_proppatch.request
+
+PROPFIND /calendars/__uids__/user01/tasks/                        - poll_calendar_propfind.request
+PROPFIND /calendars/__uids__/user01/tasks/                        - poll_calendar_propfind_d1.request
+
+PROPFIND /calendars/__uids__/user01/calendar/                - poll_calendar_propfind.request
+PROPFIND /calendars/__uids__/user01/calendar/                - poll_calendar_propfind_d1.request
+
+PROPFIND /calendars/__uids__/user01/inbox/                        - poll_calendar_propfind.request
+PROPFIND /calendars/__uids__/user01/inbox/                        - poll_calendar_propfind_d1.request
+
+PROPFIND /calendars/__uids__/user01/notification/        - poll_calendar_propfind.request
+PROPFIND /calendars/__uids__/user01/notification/        - poll_notification_propfind_d1.request
+
+REPORT /principals/__uids__/user01/                                        - startup_principal_expand.request
+
+        ** for each delegate
+        PROPFIND /principals/__uids__/resource10/                - startup_delegate_principal_propfind.request
+        OPTIONS /principals/__uids__/user01/
+        REPORT /principals/                                                                - startup_principals_report.request
+        
+** Polling - with sync
+PROPFIND /calendars/__uids__/user01/                                - poll_calendarhome_propfind.request
+REPORT /calendars/__uids__/user01/calendar/                        - poll_calendar_sync.request
+PROPFIND /calendars/__uids__/user01/calendar/                - poll_calendar_multiget.request
+        
+** Polling - without sync
+PROPFIND /calendars/__uids__/user01/                                - poll_calendarhome_propfind.request
+PROPFIND /calendars/__uids__/user01/calendar/                - poll_calendar_propfind.request
+PROPFIND /calendars/__uids__/user01/calendar/                - poll_calendar_propfind_d1.request
+REPORT /calendars/__uids__/user01/calendar/                        - poll_calendar_multiget.request
+PROPFIND /calendars/__uids__/user01/notification/        - poll_calendar_propfind.request
+PROPFIND /calendars/__uids__/user01/notification/        - poll_notification_propfind_d1.request
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendar_multigetrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_multiget.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_multiget.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_multiget.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;C:calendar-multiget xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;
+  &lt;A:prop xmlns:A=&quot;DAV:&quot;&gt;
+    &lt;A:getetag/&gt;
+    &lt;C:calendar-data/&gt;
+    &lt;C:schedule-tag/&gt;
+  &lt;/A:prop&gt;
+%(hrefs)s
+&lt;/C:calendar-multiget&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendar_multiget_hrefsrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_multiget_hrefs.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_multiget_hrefs.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_multiget_hrefs.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1 @@
</span><ins>+  &lt;A:href xmlns:A=&quot;DAV:&quot;&gt;%(href)s&lt;/A:href&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendar_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;B:getctag xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:sync-token/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendar_propfind_d1request"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_propfind_d1.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_propfind_d1.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_propfind_d1.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:getcontenttype/&gt;
+    &lt;A:getetag/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendar_syncrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_sync.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_sync.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendar_sync.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:sync-collection xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:sync-token&gt;%(sync-token)s&lt;/A:sync-token&gt;
+  &lt;A:prop&gt;
+    &lt;A:getetag/&gt;
+    &lt;A:getcontenttype/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:sync-collection&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7poll_calendarhome_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendarhome_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendarhome_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_calendarhome_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:add-member/&gt;
+    &lt;B:allowed-sharing-modes xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;D:bulk-requests xmlns:D=&quot;http://me.com/_namespace/&quot;/&gt;
+    &lt;E:calendar-color xmlns:E=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;C:calendar-description xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:calendar-free-busy-set xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;E:calendar-order xmlns:E=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;C:calendar-timezone xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-privilege-set/&gt;
+    &lt;A:displayname/&gt;
+    &lt;B:getctag xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;F:max-image-size xmlns:F=&quot;urn:ietf:params:xml:ns:carddav&quot;/&gt;
+    &lt;F:max-resource-size xmlns:F=&quot;urn:ietf:params:xml:ns:carddav&quot;/&gt;
+    &lt;B:me-card xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:owner/&gt;
+    &lt;B:publish-url xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:push-transports xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:pushkey xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:quota-available-bytes/&gt;
+    &lt;A:quota-used-bytes/&gt;
+    &lt;E:refreshrate xmlns:E=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;A:resourcetype/&gt;
+    &lt;C:schedule-calendar-transp xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:schedule-default-calendar-URL xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;B:source xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:subscribed-strip-alarms xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:subscribed-strip-attachments xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:subscribed-strip-todos xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:supported-calendar-component-set xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+    &lt;A:sync-token/&gt;
+    &lt;B:xmpp-server xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:xmpp-uri xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7poll_notification_propfind_d1request"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_notification_propfind_d1.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_notification_propfind_d1.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/poll_notification_propfind_d1.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:getetag/&gt;
+    &lt;B:notificationtype xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7post_availabilityrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/post_availability.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/post_availability.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/post_availability.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+METHOD:REQUEST
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+BEGIN:VFREEBUSY
+UID:%(vfreebusy-uid)s
+DTEND:%(end)s
+%(attendees)sDTSTART:%(start)s
+%(event-mask)sDTSTAMP:%(now)s
+ORGANIZER:%(organizer)s
+SUMMARY:%(summary)s
+END:VFREEBUSY
+END:VCALENDAR
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7startup_calendar_color_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_color_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_color_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_color_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;E:calendar-color xmlns:E=&quot;http://apple.com/ns/ical/&quot;&gt;#882F00FF&lt;/E:calendar-color&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7startup_calendar_order_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_order_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_order_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_order_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;E:calendar-order xmlns:E=&quot;http://apple.com/ns/ical/&quot;&gt;1&lt;/E:calendar-order&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7startup_calendar_timezone_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_timezone_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_timezone_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_calendar_timezone_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;C:calendar-timezone xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;BEGIN:VCALENDAR&amp;#13;
+VERSION:2.0&amp;#13;
+PRODID:-//Apple Inc.//iCal 5.0.2//EN&amp;#13;
+CALSCALE:GREGORIAN&amp;#13;
+BEGIN:VTIMEZONE&amp;#13;
+TZID:America/New_York&amp;#13;
+BEGIN:DAYLIGHT&amp;#13;
+TZOFFSETFROM:-0500&amp;#13;
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU&amp;#13;
+DTSTART:20070311T020000&amp;#13;
+TZNAME:EDT&amp;#13;
+TZOFFSETTO:-0400&amp;#13;
+END:DAYLIGHT&amp;#13;
+BEGIN:STANDARD&amp;#13;
+TZOFFSETFROM:-0400&amp;#13;
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU&amp;#13;
+DTSTART:20071104T020000&amp;#13;
+TZNAME:EST&amp;#13;
+TZOFFSETTO:-0500&amp;#13;
+END:STANDARD&amp;#13;
+END:VTIMEZONE&amp;#13;
+END:VCALENDAR&amp;#13;
+&lt;/C:calendar-timezone&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7startup_delegate_principal_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_delegate_principal_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_delegate_principal_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_delegate_principal_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;B:allowed-calendar-component-set xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:calendar-home-set xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:calendar-user-address-set xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:displayname/&gt;
+    &lt;B:dropbox-home-URL xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:email-address-set xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:notification-URL xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:principal-collection-set/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;C:schedule-inbox-URL xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:schedule-outbox-URL xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7startup_principal_expandrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_expand.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_expand.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_expand.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:expand-property xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:property name=&quot;calendar-proxy-read-for&quot; namespace=&quot;http://calendarserver.org/ns/&quot;&gt;
+    &lt;A:property name=&quot;calendar-user-address-set&quot; namespace=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:property name=&quot;email-address-set&quot; namespace=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:property name=&quot;displayname&quot; namespace=&quot;DAV:&quot;/&gt;
+  &lt;/A:property&gt;
+  &lt;A:property name=&quot;calendar-proxy-write-for&quot; namespace=&quot;http://calendarserver.org/ns/&quot;&gt;
+    &lt;A:property name=&quot;calendar-user-address-set&quot; namespace=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:property name=&quot;email-address-set&quot; namespace=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:property name=&quot;displayname&quot; namespace=&quot;DAV:&quot;/&gt;
+  &lt;/A:property&gt;
+&lt;/A:expand-property&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7startup_principal_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;B:allowed-calendar-component-set xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:calendar-home-set xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:calendar-user-address-set xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:displayname/&gt;
+    &lt;B:dropbox-home-URL xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:email-address-set xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:notification-URL xmlns:B=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:principal-collection-set/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;C:schedule-inbox-URL xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:schedule-outbox-URL xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7startup_principal_propfind_initialrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_propfind_initial.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_propfind_initial.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principal_propfind_initial.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resourcetype/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7startup_principals_reportrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principals_report.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principals_report.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_principals_report.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
+&lt;x0:principal-search-property-set xmlns:x0=&quot;DAV:&quot;/&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7startup_well_knownrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_well_known.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_well_known.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/startup_well_known.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resourcetype/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataOS_X_10_7user_list_principal_property_searchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/OS_X_10_7/user_list_principal_property_search.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/OS_X_10_7/user_list_principal_property_search.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/OS_X_10_7/user_list_principal_property_search.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
+&lt;x0:principal-property-search xmlns:x2=&quot;urn:ietf:params:xml:ns:caldav&quot; xmlns:x0=&quot;DAV:&quot; xmlns:x1=&quot;http://calendarserver.org/ns/&quot; test=&quot;anyof&quot;&gt;&lt;x0:property-search&gt;&lt;x0:prop&gt;&lt;x0:displayname/&gt;&lt;/x0:prop&gt;&lt;x0:match match-type=&quot;starts-with&quot;&gt;%(displayname)s&lt;/x0:match&gt;&lt;/x0:property-search&gt;&lt;x0:property-search&gt;&lt;x0:prop&gt;&lt;x1:email-address-set/&gt;&lt;/x0:prop&gt;&lt;x0:match match-type=&quot;starts-with&quot;&gt;%(email)s&lt;/x0:match&gt;&lt;/x0:property-search&gt;&lt;x0:property-search&gt;&lt;x0:prop&gt;&lt;x1:first-name/&gt;&lt;/x0:prop&gt;&lt;x0:match match-type=&quot;starts-with&quot;&gt;%(firstname)s&lt;/x0:match&gt;&lt;/x0:property-search&gt;&lt;x0:property-search&gt;&lt;x0:prop&gt;&lt;x1:last-name/&gt;&lt;/x0:prop&gt;&lt;x0:match match-type=&quot;starts-with&quot;&gt;%(lastname)s&lt;/x0:match&gt;&lt;/x0:property-search&gt;&lt;x0:prop&gt;&lt;x1:email-address-set/&gt;&lt;x2
 :calendar-user-address-set/&gt;&lt;x2:calendar-user-type/&gt;&lt;x0:displayname/&gt;&lt;x1:last-name/&gt;&lt;x1:first-name/&gt;&lt;x1:record-type/&gt;&lt;x0:principal-URL/&gt;&lt;/x0:prop&gt;&lt;/x0:principal-property-search&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5Profile"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/Profile (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/Profile                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/Profile        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+** Initial account setup
+
+PROPFIND well-known unauthorized        - startup_well_known.request
+PROPFIND / unauthorized                    - startup_well_known.request
+PROPFIND /principals/ unauthorized                    - startup_principal_propfind_initial.request
+PROPFIND /principals/ authorized                    - startup_principal_propfind_initial.request
+
+OPTIONS /principals/__uids__/user01/ unauthorized
+OPTIONS /principals/__uids__/user01/ authorized
+
+PROPFIND /principals/users/user01/ unauthorized                - startup_principal_propfind.request
+PROPFIND /principals/users/user01/                                        - startup_principal_propfind.request
+
+REPORT /principals/ unauthorized                                        - startup_principals_report.request
+REPORT /principals/                                                                        - startup_principals_report.request
+
+PROPFIND /calendars/__uids__/user01/ unauthorized        - poll_calendarhome_propfind.request
+PROPFIND /calendars/__uids__/user01/                                - poll_calendarhome_propfind.request
+
+PROPPATCH /calendars/__uids__/user01/tasks/                 - startup_calendar_color_proppatch.request
+PROPPATCH /calendars/__uids__/user01/tasks/                 - startup_calendar_order_proppatch.request
+
+PROPPATCH /calendars/__uids__/user01/calendar/                 - startup_calendar_color_proppatch.request
+PROPPATCH /calendars/__uids__/user01/calendar/                 - startup_calendar_order_proppatch.request
+
+PROPFIND /calendars/__uids__/user01/tasks/                        - poll_calendar_propfind.request
+PROPFIND /calendars/__uids__/user01/tasks/                        - poll_calendar_vtodo_query.request
+
+PROPFIND /calendars/__uids__/user01/calendar/                - poll_calendar_propfind.request
+PROPFIND /calendars/__uids__/user01/calendar/                - poll_calendar_vevent_tr_query.request
+
+PROPFIND /calendars/__uids__/user01/inbox/                        - poll_calendar_propfind.request
+PROPFIND /calendars/__uids__/user01/inbox/                        - poll_calendar_propfind_d1.request
+        
+** Polling - without sync
+PROPFIND /calendars/__uids__/user01/                                - poll_calendarhome_propfind.request
+
+PROPFIND /calendars/__uids__/user01/calendar/                - poll_calendar_propfind.request
+REPORT /calendars/__uids__/user01/calendar/                        - poll_calendar_propfind_d1.request
+REPORT /calendars/__uids__/user01/calendar/                        - poll_calendar_multiget.request
+
+PROPFIND /calendars/__uids__/user01/calendar/                - poll_calendar_propfind.request
+REPORT /calendars/__uids__/user01/tasks/                        - poll_calendar_vevent_tr_query.request
+REPORT /calendars/__uids__/user01/tasks/                        - poll_calendar_vtodo_query.request
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_multigetrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_multiget.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_multiget.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_multiget.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;G:calendar-multiget xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;
+  &lt;A:prop xmlns:A=&quot;DAV:&quot;&gt;
+    &lt;A:getetag/&gt;
+    &lt;G:calendar-data/&gt;
+    &lt;G:schedule-tag/&gt;
+  &lt;/A:prop&gt;
+%(hrefs)s
+&lt;/G:calendar-multiget&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_multiget_hrefsrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_multiget_hrefs.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_multiget_hrefs.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_multiget_hrefs.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1 @@
</span><ins>+  &lt;A:href xmlns:A=&quot;DAV:&quot;&gt;%(href)s&lt;/A:href&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;C:getctag xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:sync-token/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_propfind_d1request"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_propfind_d1.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_propfind_d1.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_propfind_d1.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:getcontenttype/&gt;
+    &lt;A:getetag/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_vevent_tr_queryrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_vevent_tr_query.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_vevent_tr_query.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_vevent_tr_query.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;G:calendar-query xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;
+  &lt;A:prop xmlns:A=&quot;DAV:&quot;&gt;
+    &lt;A:getetag/&gt;
+    &lt;A:getcontenttype/&gt;
+  &lt;/A:prop&gt;
+  &lt;G:filter&gt;
+    &lt;G:comp-filter name=&quot;VCALENDAR&quot;&gt;
+      &lt;G:comp-filter name=&quot;VEVENT&quot;&gt;
+        &lt;G:time-range start=&quot;%(start-date)sT000000Z&quot;/&gt;
+      &lt;/G:comp-filter&gt;
+    &lt;/G:comp-filter&gt;
+  &lt;/G:filter&gt;
+&lt;/G:calendar-query&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5poll_calendar_vtodo_queryrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_vtodo_query.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_vtodo_query.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendar_vtodo_query.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;G:calendar-query xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;
+  &lt;A:prop xmlns:A=&quot;DAV:&quot;&gt;
+    &lt;A:getetag/&gt;
+    &lt;A:getcontenttype/&gt;
+  &lt;/A:prop&gt;
+  &lt;G:filter&gt;
+    &lt;G:comp-filter name=&quot;VCALENDAR&quot;&gt;
+      &lt;G:comp-filter name=&quot;VTODO&quot;/&gt;
+    &lt;/G:comp-filter&gt;
+  &lt;/G:filter&gt;
+&lt;/G:calendar-query&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5poll_calendarhome_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendarhome_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendarhome_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/poll_calendarhome_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:add-member/&gt;
+    &lt;C:allowed-sharing-modes xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;E:bulk-requests xmlns:E=&quot;http://me.com/_namespace/&quot;/&gt;
+    &lt;H:calendar-color xmlns:H=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;G:calendar-description xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;G:calendar-free-busy-set xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;H:calendar-order xmlns:H=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;G:calendar-timezone xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-privilege-set/&gt;
+    &lt;A:displayname/&gt;
+    &lt;C:getctag xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;B:max-image-size xmlns:B=&quot;urn:ietf:params:xml:ns:carddav&quot;/&gt;
+    &lt;B:max-resource-size xmlns:B=&quot;urn:ietf:params:xml:ns:carddav&quot;/&gt;
+    &lt;C:me-card xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:owner/&gt;
+    &lt;C:publish-url xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:push-transports xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:pushkey xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:quota-available-bytes/&gt;
+    &lt;A:quota-used-bytes/&gt;
+    &lt;H:refreshrate xmlns:H=&quot;http://apple.com/ns/ical/&quot;/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;A:resourcetype/&gt;
+    &lt;G:schedule-calendar-transp xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;G:schedule-default-calendar-URL xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;C:source xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-alarms xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-attachments xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:subscribed-strip-todos xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;G:supported-calendar-component-set xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+    &lt;A:sync-token/&gt;
+    &lt;C:xmpp-server xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:xmpp-uri xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5startup_calendar_color_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/startup_calendar_color_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/startup_calendar_color_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/startup_calendar_color_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;H:calendar-color xmlns:H=&quot;http://apple.com/ns/ical/&quot;&gt;#711A76&lt;/H:calendar-color&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5startup_calendar_order_proppatchrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/startup_calendar_order_proppatch.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/startup_calendar_order_proppatch.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/startup_calendar_order_proppatch.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propertyupdate xmlns:A=&quot;DAV:&quot;&gt;&lt;A:set&gt;&lt;A:prop&gt;&lt;H:calendar-order xmlns:H=&quot;http://apple.com/ns/ical/&quot;&gt;0&lt;/H:calendar-order&gt;&lt;/A:prop&gt;&lt;/A:set&gt;&lt;/A:propertyupdate&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5startup_principal_propfindrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principal_propfind.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principal_propfind.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principal_propfind.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;C:allowed-calendar-component-set xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;G:calendar-home-set xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;G:calendar-user-address-set xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:displayname/&gt;
+    &lt;C:dropbox-home-URL xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:email-address-set xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;C:notification-URL xmlns:C=&quot;http://calendarserver.org/ns/&quot;/&gt;
+    &lt;A:principal-collection-set/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resource-id/&gt;
+    &lt;G:schedule-inbox-URL xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;G:schedule-outbox-URL xmlns:G=&quot;urn:ietf:params:xml:ns:caldav&quot;/&gt;
+    &lt;A:supported-report-set/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5startup_principal_propfind_initialrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principal_propfind_initial.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principal_propfind_initial.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principal_propfind_initial.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resourcetype/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5startup_principals_reportrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principals_report.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principals_report.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/startup_principals_report.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:principal-search-property-set xmlns:A=&quot;DAV:&quot;/&gt;
</ins></span></pre></div>
<a id="CalendarServertrunksimpluginrequestdataiOS_5startup_well_knownrequest"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/simplugin/request-data/iOS_5/startup_well_known.request (0 => 15430)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/simplugin/request-data/iOS_5/startup_well_known.request                                (rev 0)
+++ CalendarServer/trunk/simplugin/request-data/iOS_5/startup_well_known.request        2016-01-08 21:03:23 UTC (rev 15430)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;A:propfind xmlns:A=&quot;DAV:&quot;&gt;
+  &lt;A:prop&gt;
+    &lt;A:current-user-principal/&gt;
+    &lt;A:principal-URL/&gt;
+    &lt;A:resourcetype/&gt;
+  &lt;/A:prop&gt;
+&lt;/A:propfind&gt;
</ins></span></pre>
</div>
</div>

</body>
</html>