[CalendarServer-changes] [15404] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Fri Dec 18 12:02:35 PST 2015
Revision: 15404
http://trac.calendarserver.org//changeset/15404
Author: cdaboo at apple.com
Date: 2015-12-18 12:02:34 -0800 (Fri, 18 Dec 2015)
Log Message:
-----------
New tool to dump the default config to a plist file, preserving key order and comments from the Python source.
Modified Paths:
--------------
CalendarServer/trunk/conf/caldavd-stdconfig.plist
CalendarServer/trunk/twistedcaldav/stdconfig.py
Added Paths:
-----------
CalendarServer/trunk/twistedcaldav/dumpconfig.py
CalendarServer/trunk/twistedcaldav/test/test_dumpconfig.py
Modified: CalendarServer/trunk/conf/caldavd-stdconfig.plist
===================================================================
--- CalendarServer/trunk/conf/caldavd-stdconfig.plist 2015-12-17 20:18:32 UTC (rev 15403)
+++ CalendarServer/trunk/conf/caldavd-stdconfig.plist 2015-12-18 20:02:34 UTC (rev 15404)
@@ -19,180 +19,337 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <!-- Public network address information -->
+ <!-- Public network address information
+
+ This is the server's public network address, which is provided to clients
+ in URLs and the like. It may or may not be the network address that the
+ server is listening to directly, though it is by default. For example, it
+ may be the address of a load balancer or proxy which forwards connections
+ to the server. -->
+
+ <!-- Network host name. -->
<key>ServerHostName</key>
<string></string>
+
+ <!-- HTTP port (0 to disable HTTP) -->
<key>HTTPPort</key>
<integer>0</integer>
+
+ <!-- SSL port (0 to disable HTTPS) -->
<key>SSLPort</key>
<integer>0</integer>
+
+ <!-- Whether to listen on SSL port(s) -->
<key>EnableSSL</key>
<false/>
+
+ <!-- If True, all nonSSL requests redirected to an SSL Port -->
<key>RedirectHTTPToHTTPS</key>
<false/>
+
+ <!-- SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD -->
<key>SSLMethod</key>
<string>SSLv23_METHOD</string>
+
<key>SSLCiphers</key>
<string>RC4-SHA:HIGH:!ADH</string>
+ <!-- Max-age value for Strict-Transport-Security header; set to 0 to disable
+ header. -->
<key>StrictTransportSecuritySeconds</key>
<integer>604800</integer>
- <!-- Network address configuration information -->
+ <!-- Network address configuration information.
+
+ This configures the actual network address that the server binds to. -->
+
<key>SocketFiles</key>
<dict>
<key>Enabled</key>
<false/>
+
+ <!-- Socket file to listen for secure requests on -->
+ <key>Secured</key>
+ <string>secured.sock</string>
+
+ <!-- Socket file to listen for insecure requests on -->
+ <key>Unsecured</key>
+ <string>unsecured.sock</string>
+
+ <key>Owner</key>
+ <string></string>
+
<key>Group</key>
<string></string>
- <key>Owner</key>
- <string></string>
+
<key>Permissions</key>
<integer>504</integer>
- <key>Secured</key>
- <string>secured.sock</string>
- <key>Unsecured</key>
- <string>unsecured.sock</string>
</dict>
+
<key>SocketRoot</key>
<string>/tmp/calendarserver</string>
+ <!-- List of IP addresses to bind to [empty = all] -->
<key>BindAddresses</key>
<array>
</array>
+
+ <!-- List of port numbers to bind to for HTTP [empty = same as "Port"] -->
<key>BindHTTPPorts</key>
<array>
</array>
+
+ <!-- List of port numbers to bind to for SSL [empty = same as "SSLPort"] -->
<key>BindSSLPorts</key>
<array>
</array>
+
+ <!-- File descriptors to inherit for HTTP requests [empty = don't inherit] -->
<key>InheritFDs</key>
<array>
</array>
+
+ <!-- File descriptors to inherit for HTTPS requests [empty = don't inherit] -->
<key>InheritSSLFDs</key>
<array>
</array>
+
+ <!-- Inherited file descriptor to call recvmsg() on to receive sockets (none =
+ don't inherit) -->
<key>MetaFD</key>
<integer>0</integer>
+
+ <!-- Use a 'meta' FD, i.e. an FD to transmit other FDs to slave processes. -->
<key>UseMetaFD</key>
<true/>
- <!-- Database configuration -->
+ <!-- True: database; False: files -->
<key>UseDatabase</key>
<true/>
+ <!-- Timeout transactions that take longer than the specified number of
+ seconds. Zero means no timeouts. 5 minute default. -->
<key>TransactionTimeoutSeconds</key>
<integer>300</integer>
+ <!-- When a transactions times out tell HTTP clients clients to retry after
+ this amount of time -->
<key>TransactionHTTPRetrySeconds</key>
<integer>300</integer>
+ <!-- 2 possible values: empty, meaning 'spawn postgres yourself', or
+ 'postgres', meaning 'connect to a postgres database as specified by the
+ 'DSN' configuration key. Will support more values in the future. -->
<key>DBType</key>
<string></string>
+ <!-- The username to use when DBType is empty -->
<key>SpawnedDBUser</key>
<string>caldav</string>
+ <!-- Used to connect to an external database if DBType is non-empty -->
<key>DatabaseConnection</key>
<dict>
+ <!-- Database connection endpoint -->
+ <key>endpoint</key>
+ <string></string>
+
+ <!-- Name of database or Oracle SID -->
<key>database</key>
<string></string>
- <key>endpoint</key>
+
+ <!-- User name to connect as -->
+ <key>user</key>
<string></string>
+
+ <!-- Password to use -->
<key>password</key>
<string></string>
- <key>user</key>
- <string></string>
</dict>
+ <!-- Internally used by database to tell slave processes to inherit a file
+ descriptor and use it as an AMP connection over a UNIX socket; see
+ twext.enterprise.adbapi2.ConnectionPoolConnection -->
<key>DBAMPFD</key>
<integer>0</integer>
+ <!-- Use a shared database connection pool in the master process, rather than
+ having each client make its connections directly. -->
<key>SharedConnectionPool</key>
<false/>
+ <!-- Set to True to prevent the server or utility tools from running if the
+ database needs a schema upgrade. -->
<key>FailIfUpgradeNeeded</key>
<true/>
+ <!-- Set to True to check the current database schema against the schema file
+ matching the database schema version. -->
+ <key>CheckExistingSchema</key>
+ <false/>
+
+ <!-- When upgrading, only upgrade homes where the owner UID starts with the
+ specified prefix. The upgrade will only be partial and only apply to
+ upgrade pieces that affect entire homes. The upgrade will need to be run
+ again without this prefix set to complete the overall upgrade. -->
<key>UpgradeHomePrefix</key>
<string></string>
<!-- Work queue configuration information -->
+
<key>WorkQueue</key>
<dict>
+ <!-- Interval in seconds for job queue polling -->
+ <key>queuePollInterval</key>
+ <real>0.1</real>
+
+ <!-- Number of seconds before an assigned job is considered overdue -->
+ <key>queueOverdueTimeout</key>
+ <integer>300</integer>
+
+ <!-- Array of array that describe the threshold and new polling interval for
+ job queue polling back off -->
+ <key>queuePollingBackoff</key>
+ <array>
+ <array>
+ <integer>60</integer>
+ <integer>60</integer>
+ </array>
+ <array>
+ <integer>5</integer>
+ <integer>1</integer>
+ </array>
+ </array>
+
+ <!-- Queue capacity (percentage) which causes job processing to halt -->
+ <key>overloadLevel</key>
+ <integer>95</integer>
+
+ <!-- Queue capacity (percentage) at which only high priority items are run -->
+ <key>highPriorityLevel</key>
+ <integer>80</integer>
+
+ <!-- Queue capacity (percentage) at which only high/medium priority items are
+ run -->
+ <key>mediumPriorityLevel</key>
+ <integer>50</integer>
+
+ <!-- When a job fails, reschedule it this number of seconds in the future -->
<key>failureRescheduleInterval</key>
<integer>60</integer>
- <key>highPriorityLevel</key>
- <integer>80</integer>
+
+ <!-- When a job can't run because of a lock, reschedule it this number of
+ seconds in the future -->
<key>lockRescheduleInterval</key>
<integer>60</integer>
- <key>mediumPriorityLevel</key>
- <integer>50</integer>
- <key>overloadLevel</key>
- <integer>95</integer>
- <key>queueOverdueTimeout</key>
- <integer>300</integer>
- <key>queuePollInterval</key>
- <real>0.1</real>
+
+ <!-- dict of work table name's, whose values are dicts containing "priority"
+ and "weight" items to use for newly created work. -->
+ <key>workParameters</key>
+ <dict>
+ </dict>
</dict>
<!-- Types of service provided -->
+
+ <!-- Enable CalDAV service -->
<key>EnableCalDAV</key>
<true/>
+
+ <!-- Enable CardDAV service -->
<key>EnableCardDAV</key>
<true/>
+
+ <!-- When True override all other services and set the server into podding-only
+ mode -->
<key>MigrationOnly</key>
<false/>
<!-- Data store -->
+
<key>ServerRoot</key>
<string>/var/db/caldavd</string>
+
<key>DataRoot</key>
<string>Data</string>
+
<key>DatabaseRoot</key>
<string>Database</string>
+
<key>AttachmentsRoot</key>
<string>Attachments</string>
+
<key>DocumentRoot</key>
<string>Documents</string>
+
<key>ConfigRoot</key>
<string>Config</string>
+
<key>LogRoot</key>
<string>/var/log/caldavd</string>
+
<key>RunRoot</key>
<string>/var/run/caldavd</string>
+
<key>WebCalendarRoot</key>
<string>/Applications/Server.app/Contents/ServerRoot/usr/share/collabd/webcal/public</string>
- <!-- Quotas -->
+ <!-- Quotas -->
+
+ <!-- Attachments -->
+ <!-- User attachment quota (in bytes - default 100MB) -->
<key>UserQuota</key>
<integer>104857600</integer>
+
+ <!-- Maximum size for a single attachment (in bytes - default 10MB) -->
<key>MaximumAttachmentSize</key>
<integer>10485760</integer>
+ <!-- Resource data -->
+ <!-- Maximum number of calendars/address books allowed in a home -->
<key>MaxCollectionsPerHome</key>
<integer>50</integer>
+
+ <!-- Maximum number of resources in a calendar/address book -->
<key>MaxResourcesPerCollection</key>
<integer>10000</integer>
+
+ <!-- Maximum resource size (in bytes) -->
<key>MaxResourceSize</key>
<integer>1048576</integer>
+
+ <!-- Maximum number of unique attendees -->
<key>MaxAttendeesPerInstance</key>
<integer>100</integer>
+
+ <!-- Maximum number of instances the server will index -->
<key>MaxAllowedInstances</key>
<integer>3000</integer>
+ <!-- Set to URL path of wiki authentication service, e.g. "/auth", in order to
+ use javascript authentication dialog. Empty string indicates standard
+ browser authentication dialog should be used. -->
<key>WebCalendarAuthPath</key>
<string></string>
+ <!-- Define mappings of URLs to file system objects (directories or files) -->
<key>Aliases</key>
<array>
</array>
- <!-- Directory service -->
+ <!-- Directory service
+
+ A directory service provides information about principals (e.g. users,
+ groups, locations and resources) to the server. -->
+
<key>DirectoryService</key>
<dict>
<key>Enabled</key>
<true/>
+
+ <key>type</key>
+ <string>xml</string>
+
<key>params</key>
<dict>
<key>recordTypes</key>
@@ -200,24 +357,33 @@
<string>users</string>
<string>groups</string>
</array>
+
<key>xmlFile</key>
<string>accounts.xml</string>
</dict>
- <key>type</key>
- <string>xml</string>
</dict>
<key>DirectoryRealmName</key>
<string></string>
+ <!-- Apply an additional filter for attendee lookups where names must start
+ with the search tokens rather than just contain them. -->
<key>DirectoryFilterStartsWith</key>
<false/>
- <!-- Locations and Resources service -->
+ <!-- Locations and Resources service
+
+ Supplements the directory service with information about locations and
+ resources. -->
+
<key>ResourceService</key>
<dict>
<key>Enabled</key>
<true/>
+
+ <key>type</key>
+ <string>xml</string>
+
<key>params</key>
<dict>
<key>recordTypes</key>
@@ -226,141 +392,217 @@
<string>resources</string>
<string>addresses</string>
</array>
+
<key>xmlFile</key>
<string>resources.xml</string>
</dict>
- <key>type</key>
- <string>xml</string>
</dict>
- <!-- Augment service -->
+ <!-- Augment service
+
+ Augments for the directory service records to add calendar specific
+ attributes. -->
+
<key>AugmentService</key>
<dict>
+ <key>type</key>
+ <string>twistedcaldav.directory.augment.AugmentXMLDB</string>
+
<key>params</key>
<dict>
- <key>statSeconds</key>
- <integer>15</integer>
<key>xmlFiles</key>
<array>
<string>augments.xml</string>
</array>
+
+ <key>statSeconds</key>
+ <integer>15</integer>
</dict>
- <key>type</key>
- <string>twistedcaldav.directory.augment.AugmentXMLDB</string>
</dict>
<!-- Proxies -->
+
+ <!-- Allows for initialization of the proxy database from an XML file -->
<key>ProxyLoadFromFile</key>
<string></string>
<!-- Special principals -->
+
+ <!-- Principals with "DAV:all" access (relative URLs) -->
<key>AdminPrincipals</key>
<array>
</array>
+
+ <!-- Principals with "DAV:read" access (relative URLs) -->
<key>ReadPrincipals</key>
<array>
</array>
+
+ <!-- Create "proxy access" principals -->
<key>EnableProxyPrincipals</key>
<true/>
<!-- Permissions -->
+
+ <!-- Allow unauthenticated read access to / -->
<key>EnableAnonymousReadRoot</key>
<true/>
+
+ <!-- Allow unauthenticated read access to hierarchy -->
<key>EnableAnonymousReadNav</key>
<false/>
+
+ <!-- Allow listing of principal collections -->
<key>EnablePrincipalListings</key>
<true/>
+
+ <!-- Render calendar collections as a monolithic iCalendar object -->
<key>EnableMonolithicCalendars</key>
<true/>
<!-- Client controls -->
+
+ <!-- List of regexes for clients to disallow -->
<key>RejectClients</key>
<array>
</array>
<!-- Authentication -->
+
<key>Authentication</key>
<dict>
+ <!-- Clear text; best avoided -->
<key>Basic</key>
<dict>
+ <key>Enabled</key>
+ <true/>
+
+ <!-- Advertised over non-SSL? -->
<key>AllowedOverWireUnencrypted</key>
<false/>
- <key>Enabled</key>
- <true/>
</dict>
+
+ <!-- Digest challenge/response -->
<key>Digest</key>
<dict>
+ <key>Enabled</key>
+ <true/>
+
<key>Algorithm</key>
<string>md5</string>
+
+ <key>Qop</key>
+ <string></string>
+
+ <!-- Advertised over non-SSL? -->
<key>AllowedOverWireUnencrypted</key>
<true/>
- <key>Enabled</key>
- <true/>
- <key>Qop</key>
- <string></string>
</dict>
+
+ <!-- Kerberos/SPNEGO -->
<key>Kerberos</key>
<dict>
- <key>AllowedOverWireUnencrypted</key>
- <true/>
<key>Enabled</key>
<false/>
+
<key>ServicePrincipal</key>
<string></string>
+
+ <!-- Advertised over non-SSL? -->
+ <key>AllowedOverWireUnencrypted</key>
+ <true/>
</dict>
+
+ <!-- TLS Client Certificate -->
<key>ClientCertificate</key>
<dict>
+ <key>Enabled</key>
+ <false/>
+
+ <!-- Advertised over non-SSL? -->
<key>AllowedOverWireUnencrypted</key>
<true/>
+
+ <!-- Always require a client cert -->
+ <key>Required</key>
+ <true/>
+
+ <!-- Array of acceptable client cert CA file names -->
<key>CAFiles</key>
<array>
</array>
- <key>Enabled</key>
- <false/>
- <key>Required</key>
- <true/>
+
+ <!-- Send the list of acceptable CAs to the client -->
<key>SendCAsToClient</key>
<true/>
</dict>
+
<key>Wiki</key>
<dict>
+ <key>Enabled</key>
+ <false/>
+
<key>Cookie</key>
<string>cc.collabd_session_guid</string>
- <key>Enabled</key>
- <false/>
+
<key>EndpointDescriptor</key>
<string>unix:path=/var/run/collabd</string>
</dict>
</dict>
<!-- Logging -->
+
+ <!-- Apache-style access log -->
<key>AccessLogFile</key>
<string>access.log</string>
+
+ <!-- Server activity log -->
<key>ErrorLogFile</key>
<string>error.log</string>
+
+ <!-- Agent activity log -->
<key>AgentLogFile</key>
<string>agent.log</string>
+
+ <!-- Utility log - name will be dynamically changed to executable name -->
<key>UtilityLogFile</key>
- <string>.log</string>
+ <string>utility.log</string>
+
+ <!-- True = use log file, False = stdout -->
<key>ErrorLogEnabled</key>
<true/>
+
+ <!-- Rotate error log after so many megabytes -->
<key>ErrorLogRotateMB</key>
<integer>10</integer>
+
+ <!-- Retain this many error log files -->
<key>ErrorLogMaxRotatedFiles</key>
<integer>5</integer>
+
+ <!-- Rotate error log when service starts -->
+ <key>ErrorLogRotateOnStart</key>
+ <false/>
+
<key>PIDFile</key>
<string>caldavd.pid</string>
+
<key>RotateAccessLog</key>
<false/>
+
<key>EnableExtendedAccessLog</key>
<true/>
+
<key>EnableExtendedTimingAccessLog</key>
<false/>
+
<key>DefaultLogLevel</key>
<string></string>
+
<key>LogLevels</key>
<dict>
</dict>
+
<key>LogID</key>
<string></string>
@@ -368,194 +610,304 @@
<dict>
<key>HTTP</key>
<false/>
+
<key>iTIP</key>
<false/>
+
<key>iTIP-VFREEBUSY</key>
<false/>
+
<key>Implicit Errors</key>
<false/>
+
<key>AutoScheduling</key>
<false/>
+
<key>iSchedule</key>
<false/>
+
<key>migration</key>
<false/>
</dict>
+
<key>AccountingPrincipals</key>
<array>
</array>
+
<key>AccountingLogRoot</key>
<string>accounting</string>
<key>Stats</key>
<dict>
+ <key>EnableUnixStatsSocket</key>
+ <false/>
+
+ <key>UnixStatsSocket</key>
+ <string>caldavd-stats.sock</string>
+
<key>EnableTCPStatsSocket</key>
<false/>
- <key>EnableUnixStatsSocket</key>
- <false/>
+
<key>TCPStatsPort</key>
<integer>8100</integer>
- <key>UnixStatsSocket</key>
- <string>caldavd-stats.sock</string>
</dict>
<key>LogDatabase</key>
<dict>
<key>LabelsInSQL</key>
<false/>
- <key>SQLStatements</key>
- <false/>
+
<key>Statistics</key>
<false/>
+
<key>StatisticsLogFile</key>
<string>sqlstats.log</string>
+
+ <key>SQLStatements</key>
+ <false/>
+
<key>TransactionWaitSeconds</key>
<integer>0</integer>
</dict>
<!-- SSL/TLS -->
+
+ <!-- Public key -->
<key>SSLCertificate</key>
<string></string>
+
+ <!-- Private key -->
<key>SSLPrivateKey</key>
<string></string>
+
+ <!-- Certificate Authority Chain -->
<key>SSLAuthorityChain</key>
<string></string>
+
<key>SSLPassPhraseDialog</key>
<string>/etc/apache2/getsslpassphrase</string>
+
<key>SSLCertAdmin</key>
<string>/Applications/Server.app/Contents/ServerRoot/usr/sbin/certadmin</string>
+ <!-- Keychain identity to use in place of cert files -->
+ <key>SSLKeychainIdentity</key>
+ <string></string>
+
<!-- Process management -->
+
+ <!-- Username and Groupname to drop privileges to, if empty privileges will not
+ be dropped. -->
<key>UserName</key>
<string></string>
+
<key>GroupName</key>
<string></string>
+
+ <!-- Multi-process -->
<key>ProcessType</key>
<string>Combined</string>
+
<key>MultiProcess</key>
<dict>
+ <key>ProcessCount</key>
+ <integer>0</integer>
+
<key>MinProcessCount</key>
<integer>2</integer>
+
<key>PerCPU</key>
<integer>1</integer>
+
<key>PerGB</key>
<integer>1</integer>
- <key>ProcessCount</key>
- <integer>0</integer>
+
<key>StaggeredStartup</key>
<dict>
<key>Enabled</key>
<false/>
+
<key>Interval</key>
<integer>15</integer>
</dict>
</dict>
+ <!-- How large a spawned process is allowed to get before it's stopped -->
<key>MemoryLimiter</key>
<dict>
+ <key>Enabled</key>
+ <true/>
+
+ <!-- How often to check memory sizes (in seconds) -->
+ <key>Seconds</key>
+ <integer>60</integer>
+
+ <!-- Memory limit (RSS in bytes) -->
<key>Bytes</key>
<integer>2147483648</integer>
- <key>Enabled</key>
- <true/>
+
+ <!-- True: only take into account resident memory; False: include virtual
+ memory -->
<key>ResidentOnly</key>
<true/>
- <key>Seconds</key>
- <integer>60</integer>
</dict>
<!-- Service ACLs -->
<key>EnableSACLs</key>
<false/>
+ <!-- Make all data read-only -->
<key>EnableReadOnlyServer</key>
<false/>
<!-- Standard (or draft) WebDAV extensions -->
+
+ <!-- POST ;add-member extension -->
<key>EnableAddMember</key>
<true/>
+
+ <!-- REPORT collection-sync -->
<key>EnableSyncReport</key>
<true/>
+
+ <!-- REPORT collection-sync on home collections -->
<key>EnableSyncReportHome</key>
<true/>
+
+ <!-- Sync token includes config component -->
<key>EnableConfigSyncToken</key>
<true/>
+
+ <!-- /.well-known resource -->
<key>EnableWellKnown</key>
<true/>
+
+ <!-- Extended calendar-query REPORT -->
<key>EnableCalendarQueryExtended</key>
<true/>
+ <!-- Support Managed Attachments -->
<key>EnableManagedAttachments</key>
<false/>
+ <!-- server-info document -->
+ <key>EnableServerInfo</key>
+ <false/>
+
<!-- Generic CalDAV/CardDAV extensions -->
+
+ <!-- Allow clients to send/receive JSON jCal and jCard format data -->
<key>EnableJSONData</key>
<true/>
<!-- Non-standard CalDAV extensions -->
+
+ <!-- Calendar Drop Box -->
<key>EnableDropBox</key>
<false/>
+
+ <!-- Private Events -->
<key>EnablePrivateEvents</key>
<false/>
+
+ <!-- Old Timezone service -->
<key>EnableTimezoneService</key>
<false/>
+ <!-- New standard timezone service -->
<key>TimezoneService</key>
<dict>
- <key>BasePath</key>
- <string></string>
+ <!-- Overall on/off switch -->
<key>Enabled</key>
<true/>
+
+ <!-- URI where service is hosted -->
+ <key>URI</key>
+ <string>/stdtimezones</string>
+
+ <!-- Can be "primary" or "secondary" -->
<key>Mode</key>
<string>primary</string>
+
+ <!-- Path to directory containing a zoneinfo - if None use default package
+ path secondary service MUST define its own writable path -->
+ <key>BasePath</key>
+ <string></string>
+
+ <!-- Path to db cache info - if None use default package path secondary
+ service MUST define its own writable path if not None -->
+ <key>XMLInfoPath</key>
+ <string></string>
+
+ <!-- User friendly JSON output -->
<key>PrettyPrintJSON</key>
<true/>
+
<key>SecondaryService</key>
<dict>
+ <!-- Only one of these should be used when a secondary service is used -->
+ <!-- Domain/IP of secondary service to discover -->
<key>Host</key>
<string></string>
+
+ <!-- HTTP(s) URI to secondary service -->
<key>URI</key>
<string></string>
+
<key>UpdateIntervalMinutes</key>
<integer>1440</integer>
</dict>
- <key>URI</key>
- <string>/stdtimezones</string>
- <key>XMLInfoPath</key>
- <string></string>
</dict>
+ <!-- Strip out VTIMEZONES that are known -->
<key>EnableTimezonesByReference</key>
<true/>
+
+ <!-- Use timezone data from twistedcaldav.zoneinfo - don't copy to Data
+ directory -->
<key>UsePackageTimezones</key>
<false/>
+ <!-- POST batch uploads -->
<key>EnableBatchUpload</key>
<true/>
+
+ <!-- Maximum number of resources in a batch POST -->
<key>MaxResourcesBatchUpload</key>
<integer>100</integer>
+
+ <!-- Maximum size of a batch POST (10 MB) -->
<key>MaxBytesBatchUpload</key>
<integer>10485760</integer>
<key>Sharing</key>
<dict>
+ <!-- Overall on/off switch -->
<key>Enabled</key>
<true/>
+
+ <!-- External (non-principal) sharees allowed -->
<key>AllowExternalUsers</key>
<false/>
<key>Calendars</key>
<dict>
+ <!-- Calendar on/off switch -->
<key>Enabled</key>
<true/>
+
<key>IgnorePerUserProperties</key>
<array>
<string>X-APPLE-STRUCTURED-LOCATION</string>
</array>
+
<key>CollectionProperties</key>
<dict>
- <key>Global</key>
+ <key>Shadowable</key>
<array>
+ <string>{urn:ietf:params:xml:ns:caldav}calendar-description</string>
</array>
+
<key>ProxyOverride</key>
<array>
<string>{urn:ietf:params:xml:ns:caldav}calendar-description</string>
@@ -563,15 +915,18 @@
<string>{http://apple.com/ns/ical/}calendar-color</string>
<string>{http://apple.com/ns/ical/}calendar-order</string>
</array>
- <key>Shadowable</key>
+
+ <key>Global</key>
<array>
- <string>{urn:ietf:params:xml:ns:caldav}calendar-description</string>
</array>
</dict>
+
<key>Groups</key>
<dict>
+ <!-- Calendar sharing to groups on/off switch -->
<key>Enabled</key>
<true/>
+
<key>ReconciliationDelaySeconds</key>
<integer>5</integer>
</dict>
@@ -579,92 +934,135 @@
<key>AddressBooks</key>
<dict>
+ <!-- Address Book sharing on/off switch -->
<key>Enabled</key>
<false/>
+
<key>CollectionProperties</key>
<dict>
- <key>Global</key>
+ <key>Shadowable</key>
<array>
+ <string>{urn:ietf:params:xml:ns:carddav}addressbook-description</string>
</array>
+
<key>ProxyOverride</key>
<array>
</array>
- <key>Shadowable</key>
+
+ <key>Global</key>
<array>
- <string>{urn:ietf:params:xml:ns:carddav}addressbook-description</string>
</array>
</dict>
+
<key>Groups</key>
<dict>
+ <!-- Address Book Group sharing on/off switch -->
<key>Enabled</key>
<false/>
</dict>
</dict>
</dict>
+ <!-- Only allow calendars to be created with a single component type If this is
+ on, it will also trigger an upgrade behavior that will split existing
+ calendars into multiples based on component type. If on, it will also
+ cause new accounts to provision with separate calendars for events and
+ tasks. -->
<key>RestrictCalendarsToOneComponentType</key>
<true/>
+ <!-- Set of supported iCalendar components -->
<key>SupportedComponents</key>
<array>
<string>VEVENT</string>
<string>VTODO</string>
</array>
+ <!-- Enable Trash Collection -->
<key>EnableTrashCollection</key>
<false/>
+
+ <!-- Expose Trash Collection as a resource -->
<key>ExposeTrashCollection</key>
<false/>
+ <!-- Perform upgrades - currently only the database to filesystem migration -
+ but in the future, hopefully all relevant upgrades - in parallel in
+ subprocesses. -->
<key>ParallelUpgrades</key>
<false/>
+ <!-- During the upgrade phase of startup, rather than skipping homes found both
+ on the filesystem and in the database, merge the data from the filesystem
+ into the database homes. -->
<key>MergeUpgrades</key>
<false/>
+ <!-- Support for default alarms generated by the server -->
<key>EnableDefaultAlarms</key>
<true/>
+
+ <!-- Remove duplicate alarms on PUT -->
<key>RemoveDuplicateAlarms</key>
<true/>
+ <!-- Remove duplicate private comments on PUT -->
<key>RemoveDuplicatePrivateComments</key>
<false/>
<key>HostedStatus</key>
<dict>
+ <!-- Decorate ATTENDEEs with the following parameter to indicate where the
+ ATTENDEE is hosted, locally or externally. It's configurable and
+ extensible in case we want to add more values. A value of empty string
+ means no decoration. -->
<key>Enabled</key>
<false/>
+
<key>Parameter</key>
<string>X-APPLE-HOSTED-STATUS</string>
+
<key>Values</key>
<dict>
+ <key>local</key>
+ <string></string>
+
<key>external</key>
<string>EXTERNAL</string>
- <key>local</key>
- <string></string>
</dict>
</dict>
<key>RevisionCleanup</key>
<dict>
- <key>CleanupPeriodDays</key>
- <real>2.0</real>
<key>Enabled</key>
<true/>
+
+ <!-- Number of days that a client sync report token is valid -->
<key>SyncTokenLifetimeDays</key>
<real>14.0</real>
+
+ <!-- Number of days between revision cleanups -->
+ <key>CleanupPeriodDays</key>
+ <real>2.0</real>
</dict>
<key>InboxCleanup</key>
<dict>
- <key>CleanupPeriodDays</key>
- <real>2.0</real>
<key>Enabled</key>
<true/>
+
+ <!-- Number of days before deleting a new inbox item -->
+ <key>ItemLifetimeDays</key>
+ <real>14.0</real>
+
+ <!-- Number of days to keep an inbox item past the time when its referenced
+ event ends -->
<key>ItemLifeBeyondEventEndDays</key>
<real>14.0</real>
- <key>ItemLifetimeDays</key>
- <real>14.0</real>
+
+ <!-- Number of days between inbox cleanups -->
+ <key>CleanupPeriodDays</key>
+ <real>2.0</real>
</dict>
<!-- CardDAV Features -->
@@ -672,57 +1070,83 @@
<dict>
<key>Enabled</key>
<true/>
- <key>MaxQueryResults</key>
- <integer>1000</integer>
- <key>name</key>
- <string>directory</string>
+
+ <key>type</key>
+ <string>twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService</string>
+
<key>params</key>
<dict>
- <key>addDSAttrXProperties</key>
- <false/>
- <key>additionalAttributes</key>
- <array>
- </array>
- <key>allowedAttributes</key>
- <array>
- </array>
- <key>appleInternalServer</key>
- <false/>
- <key>cacheQuery</key>
- <false/>
- <key>cacheTimeout</key>
- <integer>30</integer>
- <key>dsLocalCacheTimeout</key>
- <integer>30</integer>
- <key>fakeETag</key>
+ <key>queryPeopleRecords</key>
<true/>
- <key>ignoreSystemRecords</key>
+
+ <key>peopleNode</key>
+ <string>/Search/Contacts</string>
+
+ <key>queryUserRecords</key>
<true/>
- <key>liveQuery</key>
- <true/>
+
+ <key>userNode</key>
+ <string>/Search/Contacts</string>
+
<key>maxDSQueryRecords</key>
<integer>0</integer>
- <key>peopleNode</key>
- <string>/Search/Contacts</string>
+
<key>queryDSLocal</key>
<false/>
- <key>queryPeopleRecords</key>
+
+ <key>ignoreSystemRecords</key>
<true/>
- <key>queryUserRecords</key>
+
+ <key>dsLocalCacheTimeout</key>
+ <integer>30</integer>
+
+ <key>liveQuery</key>
<true/>
+
+ <key>fakeETag</key>
+ <true/>
+
+ <key>cacheQuery</key>
+ <false/>
+
+ <key>cacheTimeout</key>
+ <integer>30</integer>
+
<key>standardizeSyntheticUIDs</key>
<false/>
- <key>userNode</key>
- <string>/Search/Contacts</string>
+
+ <key>addDSAttrXProperties</key>
+ <false/>
+
+ <key>appleInternalServer</key>
+ <false/>
+
+ <key>additionalAttributes</key>
+ <array>
+ </array>
+
+ <key>allowedAttributes</key>
+ <array>
+ </array>
</dict>
- <key>type</key>
- <string>twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService</string>
+
+ <key>name</key>
+ <string>directory</string>
+
+ <key>MaxQueryResults</key>
+ <integer>1000</integer>
</dict>
+
+ <!-- /directory resource exists -->
<key>EnableSearchAddressBook</key>
<false/>
+
+ <!-- Anonymous users may access directory address book -->
<key>AnonymousDirectoryAddressBookAccess</key>
<false/>
+ <!-- /XXX CardDAV -->
+
<!-- Web-based administration -->
<key>EnableWebAdmin</key>
<true/>
@@ -732,23 +1156,38 @@
<false/>
<!-- Scheduling related options -->
+
<key>Scheduling</key>
<dict>
<key>CalDAV</key>
<dict>
+ <!-- Domain for mailto calendar user addresses on this server -->
<key>EmailDomain</key>
<string></string>
+
+ <!-- Domain for http calendar user addresses on this server -->
<key>HTTPDomain</key>
<string></string>
+
+ <!-- Regex patterns to match local calendar user addresses -->
<key>AddressPatterns</key>
<array>
</array>
+
+ <!-- Whether to maintain compatibility with non-implicit mode -->
<key>OldDraftCompatibility</key>
<true/>
+
+ <!-- Whether to support older clients that do not use Schedule-Tag feature -->
<key>ScheduleTagCompatibility</key>
<true/>
+
+ <!-- Private comments from attendees to organizer -->
<key>EnablePrivateComments</key>
<true/>
+
+ <!-- Names of iCalendar properties that are preserved when an Attendee does
+ an invite PUT -->
<key>PerAttendeeProperties</key>
<array>
<string>X-APPLE-NEEDS-REPLY</string>
@@ -757,177 +1196,346 @@
<string>X-APPLE-TRAVEL-RETURN-DURATION</string>
<string>X-APPLE-TRAVEL-RETURN</string>
</array>
+
+ <!-- Names of X- iCalendar properties that are sent from ORGANIZER to
+ ATTENDEE -->
<key>OrganizerPublicProperties</key>
<array>
<string>X-APPLE-DROPBOX</string>
<string>X-APPLE-STRUCTURED-LOCATION</string>
</array>
+
+ <!-- Names of X- iCalendar parameters that are sent from ORGANIZER to
+ ATTENDEE -->
+ <key>OrganizerPublicParameters</key>
+ <array>
+ </array>
+
+ <!-- Names of X- iCalendar properties that are sent from ATTENDEE to
+ ORGANIZER These are also implicitly added to OrganizerPublicProperties -->
+ <key>AttendeePublicProperties</key>
+ <array>
+ </array>
+
+ <!-- Names of X- iCalendar parameters that are sent from ATTENDEE to
+ ORGANIZER These are also implicitly added to OrganizerPublicParameters -->
+ <key>AttendeePublicParameters</key>
+ <array>
+ </array>
</dict>
+
<key>iSchedule</key>
<dict>
+ <!-- iSchedule protocol -->
<key>Enabled</key>
<false/>
+
+ <!-- Reg-ex patterns to match iSchedule-able calendar user addresses -->
<key>AddressPatterns</key>
<array>
</array>
+
+ <!-- iSchedule server configurations -->
<key>RemoteServers</key>
<string>remoteservers.xml</string>
+
+ <!-- Capabilities serial number -->
<key>SerialNumber</key>
<integer>1</integer>
+
+ <!-- File where a fake Bind zone exists for creating fake DNS results -->
<key>DNSDebug</key>
<string></string>
+
+ <!-- DKIM options -->
<key>DKIM</key>
<dict>
+ <!-- DKIM signing/verification enabled -->
<key>Enabled</key>
<true/>
+
+ <!-- Domain for DKIM (defaults to ServerHostName) -->
<key>Domain</key>
<string></string>
+
+ <!-- Selector for public key -->
<key>KeySelector</key>
<string>ischedule</string>
+
+ <!-- Signature algorithm (one of rsa-sha1 or rsa-sha256) -->
<key>SignatureAlgorithm</key>
<string>rsa-sha256</string>
+
+ <!-- This server's public key stored in DNS -->
<key>UseDNSKey</key>
<true/>
+
+ <!-- This server's public key stored in HTTP /.well-known -->
<key>UseHTTPKey</key>
<true/>
+
+ <!-- This server's public key manually exchanged with others -->
<key>UsePrivateExchangeKey</key>
<true/>
+
+ <!-- Expiration time for signature verification -->
<key>ExpireSeconds</key>
<integer>3600</integer>
+
+ <!-- File where private key is stored -->
<key>PrivateKeyFile</key>
<string></string>
+
+ <!-- File where public key is stored -->
<key>PublicKeyFile</key>
<string></string>
+
+ <!-- Directory where private exchange public keys are stored -->
<key>PrivateExchanges</key>
<string></string>
+
+ <!-- Turn on protocol level debugging to return detailed information to the
+ requestor -->
<key>ProtocolDebug</key>
<false/>
</dict>
</dict>
+
<key>iMIP</key>
<dict>
+ <!-- Server-to-iMIP protocol -->
<key>Enabled</key>
<false/>
+
<key>Sending</key>
<dict>
- <key>Address</key>
+ <!-- SMTP server to relay messages through -->
+ <key>Server</key>
<string></string>
- <key>Password</key>
- <string></string>
+
+ <!-- SMTP server port to relay messages through -->
<key>Port</key>
<integer>587</integer>
- <key>Server</key>
+
+ <!-- 'From' address for server -->
+ <key>Address</key>
<string></string>
- <key>SuppressionDays</key>
- <integer>7</integer>
+
<key>UseSSL</key>
<true/>
+
+ <!-- For account sending mail -->
<key>Username</key>
<string></string>
+
+ <!-- For account sending mail -->
+ <key>Password</key>
+ <string></string>
+
+ <!-- Messages for events older than this may days are not sent -->
+ <key>SuppressionDays</key>
+ <integer>7</integer>
</dict>
+
<key>Receiving</key>
<dict>
- <key>Password</key>
+ <!-- Server to retrieve email messages from -->
+ <key>Server</key>
<string></string>
- <key>PollingSeconds</key>
- <integer>30</integer>
+
+ <!-- Server port to retrieve email messages from -->
<key>Port</key>
<integer>0</integer>
- <key>Server</key>
- <string></string>
+
+ <key>UseSSL</key>
+ <true/>
+
+ <!-- Type of message access server: 'pop' or 'imap' -->
<key>Type</key>
<string></string>
- <key>UseSSL</key>
- <true/>
+
+ <!-- How often to fetch mail -->
+ <key>PollingSeconds</key>
+ <integer>30</integer>
+
+ <!-- For account receiving mail -->
<key>Username</key>
<string></string>
+
+ <!-- For account receiving mail -->
+ <key>Password</key>
+ <string></string>
</dict>
+
+ <!-- Regex patterns to match iMIP-able calendar user addresses -->
<key>AddressPatterns</key>
<array>
</array>
+
+ <!-- Directory containing HTML templates for email invitations (invite.html,
+ cancel.html) -->
<key>MailTemplatesDirectory</key>
<string>/Applications/Server.app/Contents/ServerRoot/usr/share/caldavd/share/email_templates</string>
+
+ <!-- Directory containing language-specific subdirectories containing date-
+ specific icons for email invitations -->
<key>MailIconsDirectory</key>
<string>/Applications/Server.app/Contents/ServerRoot/usr/share/caldavd/share/date_icons</string>
+
+ <!-- How many days invitations are valid -->
<key>InvitationDaysToLive</key>
<integer>90</integer>
</dict>
+
<key>Options</key>
<dict>
+ <!-- Allow groups to be Organizers -->
<key>AllowGroupAsOrganizer</key>
<false/>
+
+ <!-- Allow locations to be Organizers -->
<key>AllowLocationAsOrganizer</key>
<false/>
+
+ <!-- Allow resources to be Organizers -->
+ <key>AllowResourceAsOrganizer</key>
+ <false/>
+
+ <!-- Allow locations to have events without an Organizer -->
<key>AllowLocationWithoutOrganizer</key>
<true/>
- <key>AllowResourceAsOrganizer</key>
- <false/>
+
+ <!-- Allow resources to have events without an Organizer -->
<key>AllowResourceWithoutOrganizer</key>
<true/>
+
+ <!-- Track who the last modifier of an unscheduled location event is -->
+ <key>TrackUnscheduledLocationData</key>
+ <true/>
+
+ <!-- Track who the last modifier of an unscheduled resource event is -->
+ <key>TrackUnscheduledResourceData</key>
+ <true/>
+
+ <!-- Maximum number of attendees to request freebusy for -->
+ <key>LimitFreeBusyAttendees</key>
+ <integer>30</integer>
+
+ <!-- Number of attendees to do batched refreshes: 0 - no batching -->
<key>AttendeeRefreshBatch</key>
<integer>5</integer>
+
+ <!-- Number of attendees above which attendee refreshes are suppressed: 0 -
+ no limit -->
<key>AttendeeRefreshCountLimit</key>
<integer>50</integer>
+
+ <!-- Time for implicit UID lock timeout -->
+ <key>UIDLockTimeoutSeconds</key>
+ <integer>60</integer>
+
+ <!-- Expiration time for UID lock, -->
+ <key>UIDLockExpirySeconds</key>
+ <integer>300</integer>
+
+ <!-- Host names matched in http(s) CUAs -->
+ <key>PrincipalHostAliases</key>
+ <array>
+ </array>
+
+ <!-- Add a time stamp when an Attendee changes their PARTSTAT -->
+ <key>TimestampAttendeePartStatChanges</key>
+ <true/>
+
+ <!-- Delegates can get extra info in a freebusy request -->
+ <key>DelegeteRichFreeBusy</key>
+ <true/>
+
+ <!-- Any user can get extra info for rooms/resources in a freebusy request -->
+ <key>RoomResourceRichFreeBusy</key>
+ <true/>
+
<key>AutoSchedule</key>
<dict>
+ <!-- Auto-scheduling will never occur if set to False -->
<key>Enabled</key>
<true/>
+
+ <!-- Override augments setting and always auto-schedule -->
+ <key>Always</key>
+ <false/>
+
+ <!-- Allow auto-schedule for users -->
<key>AllowUsers</key>
<false/>
- <key>Always</key>
- <false/>
+
+ <!-- Default mode for auto-schedule processing, one of: "none" -
+ no auto-scheduling "accept-always" - always accept, ignore busy time
+ "decline-always" - always decline, ignore free time "accept-if-free"
+ - accept if free, do nothing if busy "decline-if-busy" - decline if
+ busy, do nothing if free "automatic" - accept if free, decline if
+ busy -->
<key>DefaultMode</key>
<string>automatic</string>
+
+ <!-- How far into the future to check for booking conflicts -->
<key>FutureFreeBusyDays</key>
<integer>1095</integer>
</dict>
- <key>DelegeteRichFreeBusy</key>
- <true/>
- <key>LimitFreeBusyAttendees</key>
- <integer>30</integer>
- <key>PrincipalHostAliases</key>
- <array>
- </array>
- <key>RoomResourceRichFreeBusy</key>
- <true/>
- <key>Splitting</key>
- <dict>
- <key>Enabled</key>
- <false/>
- <key>Delay</key>
- <integer>60</integer>
- <key>PastDays</key>
- <integer>14</integer>
- <key>Size</key>
- <integer>102400</integer>
- </dict>
- <key>TimestampAttendeePartStatChanges</key>
- <true/>
- <key>TrackUnscheduledLocationData</key>
- <true/>
- <key>TrackUnscheduledResourceData</key>
- <true/>
- <key>UIDLockExpirySeconds</key>
- <integer>300</integer>
- <key>UIDLockTimeoutSeconds</key>
- <integer>60</integer>
+
<key>WorkQueues</key>
<dict>
+ <!-- Work queues for scheduling enabled -->
<key>Enabled</key>
<true/>
+
+ <!-- Number of seconds delay for a queued scheduling request/cancel -->
+ <key>RequestDelaySeconds</key>
+ <integer>5</integer>
+
+ <!-- Number of seconds delay for a queued scheduling reply -->
+ <key>ReplyDelaySeconds</key>
+ <integer>1</integer>
+
+ <!-- Time delay for sending an auto reply iTIP message -->
+ <key>AutoReplyDelaySeconds</key>
+ <integer>5</integer>
+
+ <!-- Time after an iTIP REPLY for first batched attendee refresh -->
<key>AttendeeRefreshBatchDelaySeconds</key>
<integer>5</integer>
+
+ <!-- Time between attendee batch refreshes -->
<key>AttendeeRefreshBatchIntervalSeconds</key>
<integer>5</integer>
- <key>AutoReplyDelaySeconds</key>
- <integer>5</integer>
+
+ <!-- Delay in seconds before a work item is executed again after a temp
+ failure -->
+ <key>TemporaryFailureDelay</key>
+ <integer>60</integer>
+
+ <!-- Max number of temp failure retries before treating as a permanent
+ failure -->
<key>MaxTemporaryFailures</key>
<integer>10</integer>
- <key>ReplyDelaySeconds</key>
- <integer>1</integer>
- <key>RequestDelaySeconds</key>
- <integer>5</integer>
- <key>TemporaryFailureDelay</key>
+ </dict>
+
+ <key>Splitting</key>
+ <dict>
+ <!-- False for now whilst we experiment with this -->
+ <key>Enabled</key>
+ <false/>
+
+ <!-- Consider splitting when greater than 100KB -->
+ <key>Size</key>
+ <integer>102400</integer>
+
+ <!-- Number of days in the past where the split will occur -->
+ <key>PastDays</key>
+ <integer>14</integer>
+
+ <!-- How many seconds to delay the split work item -->
+ <key>Delay</key>
<integer>60</integer>
</dict>
</dict>
@@ -935,86 +1543,137 @@
<key>FreeBusyURL</key>
<dict>
- <key>AnonymousAccess</key>
- <false/>
+ <!-- Per-user free-busy-url protocol -->
<key>Enabled</key>
<false/>
+
+ <!-- Number of days into the future to generate f-b data if no explicit time-
+ range is specified -->
<key>TimePeriod</key>
<integer>14</integer>
+
+ <!-- Allow anonymous read access to free-busy URL -->
+ <key>AnonymousAccess</key>
+ <false/>
</dict>
<!-- Notifications -->
+
<key>Notifications</key>
<dict>
+ <key>Enabled</key>
+ <false/>
+
<key>CoalesceSeconds</key>
<integer>3</integer>
- <key>Enabled</key>
- <false/>
+
<key>Services</key>
<dict>
<key>APNS</key>
<dict>
<key>Enabled</key>
<false/>
+
<key>SubscriptionURL</key>
<string>apns</string>
+
+ <!-- How often the client should re-register (2 days) -->
<key>SubscriptionRefreshIntervalSeconds</key>
<integer>172800</integer>
+
+ <!-- How often a purge is done (12 hours) -->
<key>SubscriptionPurgeIntervalSeconds</key>
<integer>43200</integer>
+
+ <!-- How old a subscription must be before it's purged (14 days) -->
<key>SubscriptionPurgeSeconds</key>
<integer>1209600</integer>
+
<key>ProviderHost</key>
<string>gateway.push.apple.com</string>
+
<key>ProviderPort</key>
<integer>2195</integer>
+
<key>FeedbackHost</key>
<string>feedback.push.apple.com</string>
+
<key>FeedbackPort</key>
<integer>2196</integer>
+
+ <!-- 8 hours -->
<key>FeedbackUpdateSeconds</key>
<integer>28800</integer>
+
<key>Environment</key>
<string>PRODUCTION</string>
+
<key>EnableStaggering</key>
<false/>
+
<key>StaggerSeconds</key>
<integer>3</integer>
+
<key>CalDAV</key>
<dict>
+ <key>Enabled</key>
+ <false/>
+
+ <key>CertificatePath</key>
+ <string>Certificates/apns:com.apple.calendar.cert.pem</string>
+
+ <key>PrivateKeyPath</key>
+ <string>Certificates/apns:com.apple.calendar.key.pem</string>
+
<key>AuthorityChainPath</key>
<string>Certificates/apns:com.apple.calendar.chain.pem</string>
- <key>CertificatePath</key>
- <string>Certificates/apns:com.apple.calendar.cert.pem</string>
+
<key>Passphrase</key>
<string></string>
- <key>PrivateKeyPath</key>
- <string>Certificates/apns:com.apple.calendar.key.pem</string>
+
+ <key>KeychainIdentity</key>
+ <string>apns:com.apple.calendar</string>
+
<key>Topic</key>
<string></string>
</dict>
+
<key>CardDAV</key>
<dict>
+ <key>Enabled</key>
+ <false/>
+
+ <key>CertificatePath</key>
+ <string>Certificates/apns:com.apple.contact.cert.pem</string>
+
+ <key>PrivateKeyPath</key>
+ <string>Certificates/apns:com.apple.contact.key.pem</string>
+
<key>AuthorityChainPath</key>
<string>Certificates/apns:com.apple.contact.chain.pem</string>
- <key>CertificatePath</key>
- <string>Certificates/apns:com.apple.contact.cert.pem</string>
+
<key>Passphrase</key>
<string></string>
- <key>PrivateKeyPath</key>
- <string>Certificates/apns:com.apple.contact.key.pem</string>
+
+ <key>KeychainIdentity</key>
+ <string>apns:com.apple.contact</string>
+
<key>Topic</key>
<string></string>
</dict>
</dict>
+
<key>AMP</key>
<dict>
<key>Enabled</key>
<false/>
+
<key>Port</key>
<integer>62311</integer>
+
<key>EnableStaggering</key>
<false/>
+
<key>StaggerSeconds</key>
<integer>3</integer>
</dict>
@@ -1023,47 +1682,74 @@
<key>DirectoryProxy</key>
<dict>
+ <key>SocketPath</key>
+ <string>directory-proxy.sock</string>
+
<key>InProcessCachingSeconds</key>
<integer>60</integer>
+
<key>InSidecarCachingSeconds</key>
<integer>120</integer>
- <key>SocketPath</key>
- <string>directory-proxy.sock</string>
</dict>
<!-- Support multiple hosts within a domain -->
+
<key>Servers</key>
<dict>
+ <!-- Multiple servers enabled or not -->
<key>Enabled</key>
<false/>
- <key>ConduitName</key>
- <string>conduit</string>
+
+ <!-- File path for server information -->
<key>ConfigFile</key>
<string>localservers.xml</string>
+
+ <!-- Pool size for connections between servers -->
+ <key>MaxClients</key>
+ <integer>5</integer>
+
+ <!-- Name for top-level inbox resource -->
<key>InboxName</key>
<string>podding</string>
- <key>MaxClients</key>
- <integer>5</integer>
+
+ <!-- Name for top-level cross-pod resource -->
+ <key>ConduitName</key>
+ <string>conduit</string>
</dict>
<!-- Performance tuning -->
+
+ <!-- Set the maximum number of outstanding requests to this server. -->
<key>MaxRequests</key>
<integer>3</integer>
+
<key>MaxAccepts</key>
<integer>1</integer>
+ <!-- The maximum number of outstanding database connections per database
+ connection pool. When SharedConnectionPool (see above) is set to True,
+ this is the total number of outgoing database connections allowed to the
+ entire server; when SharedConnectionPool is False - this is the default -
+ this is the number of database connections used per worker process. -->
<key>MaxDBConnectionsPerPool</key>
<integer>10</integer>
<key>ListenBacklog</key>
<integer>2024</integer>
+ <!-- Max. time between request lines -->
<key>IncomingDataTimeOut</key>
<integer>60</integer>
+
+ <!-- Max. time between pipelined requests -->
<key>PipelineIdleTimeOut</key>
<integer>15</integer>
+
+ <!-- Max. time for response processing -->
<key>IdleConnectionTimeOut</key>
<integer>360</integer>
+
+ <!-- Max. time for client close -->
<key>CloseConnectionTimeOut</key>
<integer>15</integer>
@@ -1072,59 +1758,81 @@
<key>MaxMultigetWithDataHrefs</key>
<integer>5000</integer>
+
<key>MaxQueryWithDataResults</key>
<integer>1000</integer>
+ <!-- How many results to return for principal-property-search REPORT requests -->
<key>MaxPrincipalSearchReportResults</key>
<integer>500</integer>
<!-- Client fixes per user-agent match -->
+
<key>ClientFixes</key>
<dict>
<key>ForceAttendeeTRANSP</key>
<array>
- <string>iOS/8\.0(\..*)?</string>
- <string>iOS/8\.1(\..*)?</string>
- <string>iOS/8\.2(\..*)?</string>
+ <string>iOS/8\\.0(\\..*)?</string>
+ <string>iOS/8\\.1(\\..*)?</string>
+ <string>iOS/8\\.2(\\..*)?</string>
</array>
</dict>
<!-- Localization -->
+
<key>Localization</key>
<dict>
+ <key>TranslationsDirectory</key>
+ <string>/Applications/Server.app/Contents/ServerRoot/usr/share/caldavd/share/translations</string>
+
+ <key>LocalesDirectory</key>
+ <string>/Applications/Server.app/Contents/ServerRoot/usr/share/caldavd/share/locales</string>
+
<key>Language</key>
<string></string>
- <key>LocalesDirectory</key>
- <string>/Applications/Server.app/Contents/ServerRoot/usr/share/caldavd/share/locales</string>
- <key>TranslationsDirectory</key>
- <string>/Applications/Server.app/Contents/ServerRoot/usr/share/caldavd/share/translations</string>
</dict>
- <!-- Implementation details -->
+ <!-- Implementation details
+
+ The following are specific to how the server is built, and useful for
+ development, but shouldn't be needed by users. -->
+
+ <!-- Twisted -->
<key>Twisted</key>
<dict>
<key>reactor</key>
<string>select</string>
</dict>
+
+ <!-- Umask -->
<key>umask</key>
<integer>18</integer>
+ <!-- A TCP port used for communication between the child and master processes
+ (bound to 127.0.0.1). Specify 0 to let OS assign a port. -->
<key>ControlPort</key>
<integer>0</integer>
+ <!-- A unix socket used for communication between the child and master
+ processes. If blank, then an AF_INET socket is used instead. -->
<key>ControlSocket</key>
<string>caldavd.sock</string>
+ <!-- Support for Content-Encoding compression options as specified in RFC2616
+ Section 3.5 Defaults off, because it weakens TLS (CRIME attack). -->
<key>ResponseCompression</key>
<false/>
+ <!-- The retry-after value (in seconds) to return with a 503 error -->
<key>HTTPRetryAfter</key>
<integer>180</integer>
+ <!-- Profiling options -->
<key>Profiling</key>
<dict>
<key>Enabled</key>
<false/>
+
<key>BaseDirectory</key>
<string>/tmp/stats</string>
</dict>
@@ -1133,88 +1841,136 @@
<dict>
<key>MaxClients</key>
<integer>5</integer>
+
<key>Pools</key>
<dict>
<key>Default</key>
<dict>
+ <!-- A unix socket used for communication with memcached. If MemcacheSocket
+ is empty string, an AF_INET socket is used. -->
+ <key>MemcacheSocket</key>
+ <string>memcache.sock</string>
+
+ <key>ClientEnabled</key>
+ <true/>
+
+ <key>ServerEnabled</key>
+ <true/>
+
<key>BindAddress</key>
<string>127.0.0.1</string>
- <key>ClientEnabled</key>
- <true/>
+
+ <key>Port</key>
+ <integer>11311</integer>
+
+ <!-- Possible types: "OpenDirectoryBacker", "ImplicitUIDLock",
+ "RefreshUIDLock", "DIGESTCREDENTIALS", "resourceInfoDB", "pubsubnodes",
+ "FBCache", "ScheduleAddressMapper", "SQL.props", "SQL.calhome",
+ "SQL.adbkhome", -->
<key>HandleCacheTypes</key>
<array>
<string>Default</string>
</array>
- <key>MemcacheSocket</key>
- <string>memcache.sock</string>
- <key>Port</key>
- <integer>11311</integer>
- <key>ServerEnabled</key>
- <true/>
</dict>
+
+ <!-- "Shared": { "ClientEnabled": True, "ServerEnabled": True, "BindAddress":
+ "127.0.0.1", "Port": 11211, "HandleCacheTypes": [ "ProxyDB",
+ "DelegatesDB", "PrincipalToken", ] }, -->
</dict>
+
+ <!-- Find in PATH -->
<key>memcached</key>
<string>memcached</string>
+
+ <!-- Megabytes -->
<key>MaxMemory</key>
<integer>0</integer>
+
<key>Options</key>
<array>
</array>
+
<key>ProxyDBKeyNormalization</key>
<true/>
</dict>
<key>Postgres</key>
<dict>
- <key>BuffersToConnectionsRatio</key>
- <real>1.5</real>
+ <key>DatabaseName</key>
+ <string>caldav</string>
+
<key>ClusterName</key>
<string>cluster</string>
- <key>Ctl</key>
- <string>pg_ctl</string>
- <key>DatabaseName</key>
- <string>caldav</string>
- <key>ExtraConnections</key>
- <integer>3</integer>
- <key>Init</key>
- <string>initdb</string>
- <key>ListenAddresses</key>
- <array>
- </array>
+
<key>LogFile</key>
<string>postgres.log</string>
+
<key>LogRotation</key>
<false/>
+
+ <key>SocketDirectory</key>
+ <string></string>
+
+ <key>SocketName</key>
+ <string></string>
+
+ <key>ListenAddresses</key>
+ <array>
+ </array>
+
+ <!-- BuffersToConnectionsRatio * MaxConnections Note: don't set this, it will
+ be computed dynamically See _updateMultiProcess( ) below for details -->
+ <key>SharedBuffers</key>
+ <integer>0</integer>
+
+ <!-- Dynamically computed based on ProcessCount, etc. Note: don't set this, it
+ will be computed dynamically See _updateMultiProcess( ) below for details -->
<key>MaxConnections</key>
<integer>0</integer>
+
+ <!-- how many extra connections to leave for utilities -->
+ <key>ExtraConnections</key>
+ <integer>3</integer>
+
+ <key>BuffersToConnectionsRatio</key>
+ <real>1.5</real>
+
<key>Options</key>
<array>
<string>-c standard_conforming_strings=on</string>
</array>
- <key>SharedBuffers</key>
- <integer>0</integer>
- <key>SocketDirectory</key>
- <string></string>
- <key>SocketName</key>
- <string></string>
+
+ <!-- If the DBType is '', and we're spawning postgres ourselves, where is the
+ pg_ctl tool to spawn it with? -->
+ <key>Ctl</key>
+ <string>pg_ctl</string>
+
+ <!-- If the DBType is '', and we're spawning postgres ourselves, where is the
+ initdb tool to create its database cluster with? -->
+ <key>Init</key>
+ <string>initdb</string>
</dict>
<key>QueryCaching</key>
<dict>
<key>Enabled</key>
<true/>
+
+ <key>MemcachedPool</key>
+ <string>Default</string>
+
<key>ExpireSeconds</key>
<integer>3600</integer>
- <key>MemcachedPool</key>
- <string>Default</string>
</dict>
<key>GroupCaching</key>
<dict>
<key>Enabled</key>
<true/>
+
<key>UpdateSeconds</key>
<integer>300</integer>
+
<key>UseDirectoryBasedDelegates</key>
<false/>
</dict>
@@ -1223,36 +1979,51 @@
<dict>
<key>Enabled</key>
<true/>
+
+ <key>ReconciliationDelaySeconds</key>
+ <integer>5</integer>
+
+ <!-- 1 hour -->
<key>AutoUpdateSecondsFromNow</key>
<integer>3600</integer>
- <key>ReconciliationDelaySeconds</key>
- <integer>5</integer>
</dict>
<key>AutomaticPurging</key>
<dict>
<key>Enabled</key>
<true/>
+
+ <!-- 7 days -->
+ <key>PollingIntervalSeconds</key>
+ <integer>604800</integer>
+
+ <!-- No staggering -->
<key>CheckStaggerSeconds</key>
<integer>0</integer>
- <key>GroupPurgeIntervalSeconds</key>
+
+ <!-- 7 days -->
+ <key>PurgeIntervalSeconds</key>
<integer>604800</integer>
+
<key>HomePurgeDelaySeconds</key>
<integer>60</integer>
- <key>PollingIntervalSeconds</key>
+
+ <!-- 7 days -->
+ <key>GroupPurgeIntervalSeconds</key>
<integer>604800</integer>
- <key>PurgeIntervalSeconds</key>
- <integer>604800</integer>
</dict>
<key>Manhole</key>
<dict>
<key>Enabled</key>
<false/>
+
<key>StartingPortNumber</key>
<integer>5000</integer>
+
<key>DPSPortNumber</key>
<integer>4999</integer>
+
<key>PasswordFilePath</key>
<string></string>
</dict>
@@ -1262,55 +2033,86 @@
<key>EnableResponseCache</key>
<true/>
+
+ <!-- Minutes -->
<key>ResponseCacheTimeout</key>
<integer>30</integer>
<key>EnableFreeBusyCache</key>
<true/>
+
<key>FreeBusyCacheDaysBack</key>
<integer>7</integer>
+
<key>FreeBusyCacheDaysForward</key>
<integer>84</integer>
<key>FreeBusyIndexLowerLimitDays</key>
<integer>365</integer>
+
<key>FreeBusyIndexExpandAheadDays</key>
<integer>365</integer>
+
<key>FreeBusyIndexExpandMaxDays</key>
<integer>1825</integer>
+
<key>FreeBusyIndexDelayedExpand</key>
<false/>
+
<key>FreeBusyIndexSmartUpdate</key>
<true/>
+ <!-- The RootResource uses a twext property store. Specify the class here -->
<key>RootResourcePropStoreClass</key>
<string>txweb2.dav.xattrprops.xattrPropertyStore</string>
+ <!-- Used in the command line utilities to specify which service class to use
+ to carry out work. -->
<key>UtilityServiceClass</key>
<string></string>
+ <!-- Inbox items created more than MigratedInboxDaysCutoff days in the past are
+ removed during migration -->
<key>MigratedInboxDaysCutoff</key>
<integer>60</integer>
+ <!-- The default timezone for the server; on OS X you can leave this empty and
+ the system's timezone will be used. If empty and not on OS X it will
+ default to America/Los_Angeles. -->
<key>DefaultTimezone</key>
<string></string>
+ <!-- After this many seconds of no admin requests, shutdown the agent. Zero
+ means no automatic shutdown. -->
<key>AgentInactivityTimeoutSeconds</key>
<integer>300</integer>
+ <!-- Program to execute if the service cannot start; for example in OS X we
+ want to call serveradmin to disable the service so launchd does not keep
+ respawning it. Empty string to disable this feature. -->
<key>ServiceDisablingProgram</key>
<string></string>
+ <!-- Program to execute to post an alert to the administrator; for example in
+ OS X we want to call calendarserver_alert <alert-type> <args> -->
<key>AlertPostingProgram</key>
<string></string>
+ <!-- These three keys are relative to ConfigRoot: -->
+
+ <!-- Config to read first and merge -->
<key>ImportConfig</key>
<string></string>
+ <!-- Other plists to parse after this one; note that an Include can change the
+ ServerRoot and/or ConfigRoot, thereby affecting the locations of the
+ following Includes in the list. (Useful for service directory relocation) -->
<key>Includes</key>
<array>
</array>
+ <!-- Which config file calendarserver_config should write to for changes;
+ empty string means the main config file -->
<key>WritableConfigFile</key>
<string></string>
</dict>
Added: CalendarServer/trunk/twistedcaldav/dumpconfig.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/dumpconfig.py (rev 0)
+++ CalendarServer/trunk/twistedcaldav/dumpconfig.py 2015-12-18 20:02:34 UTC (rev 15404)
@@ -0,0 +1,284 @@
+##
+# Copyright (c) 2015 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from cStringIO import StringIO
+from collections import OrderedDict
+from json.encoder import encode_basestring
+from plistlib import PlistWriter, _escapeAndEncode
+import json
+import os
+import re
+import textwrap
+
+def parseConfigItem(item):
+ """
+ Read the definition of a "DEFAULT_*" value from the stdconfig.py file so that we get
+ the literal Python source as a L{str} that we then then process into JSON.
+
+ @param item: the "DEFAULT_*" item to read
+ @type item: L{str}
+
+ @return: the "DEFAULT_*" value
+ @rtype: L{str}
+ """
+ with open(os.path.join(os.path.dirname(__file__), "stdconfig.py")) as f:
+ # Read up to the first line containing DEFAULT_*
+ while f.readline() != "{} = {{\n".format(item):
+ continue
+
+ # Build list of all lines up to the end of the DEFAULT_* definition and
+ # make it look like a JSON object
+ lines = ['{']
+ line = f.readline()
+ while line != "}\n":
+ lines.append(line[:-1])
+ line = f.readline()
+ lines.append('}')
+
+ return "\n".join(lines)
+
+
+
+def processConfig(configlines, with_comments=False, verbose=False, substitutions=None):
+ """
+ Process the "raw" config lines from stdconfig.py into a JSON object
+ (a Python L{dict}) that is ordered and contains commentary based on
+ the Python comments.
+
+ @param configlines: config data lines
+ @type configlines: L{list} of L{str}
+ @param with_comments: whether to include comments or not
+ @type with_comments: L{bool}
+ @param verbose: print out intermediate state
+ @type verbose: L{bool}
+
+ @return: the serialized JSON object
+ @rtype: L{OrderedDict}
+ """
+
+ # Comments will either be "block" (as in section dividers) or "inline"
+ # (as in appended to the end of the line). We treat these slightly
+ # differently wrt to whitespace and where they appear.
+ lines = []
+ ctr = 0
+ block_comment = []
+ inline_comment = []
+
+ # Regular expression to match an inline comment and a
+ # value containing a numeric expression that needs to be
+ # evaluated (e.g. "60 * 60")
+ comments = re.compile("([ ]*.*?,?)[ ]*#[ ]*(.*)[ ]*$")
+ value = re.compile("([^:]+:[ ]+)([0-9 \*]+)(.*)")
+
+ for line in configlines.splitlines():
+
+ if line.strip() and line.strip()[0] == "#":
+ # Line with just a comment is a block comment unless the
+ # previous comment was inline (in which case it is a multi-line
+ # inline). Aggregate block and inline comments into one overall
+ # comment.
+ comment = line.strip()[1:].strip()
+ if len(comment) == 0 and len(block_comment) == 0 and len(inline_comment) == 0:
+ pass
+ elif inline_comment:
+ inline_comment.append(comment if comment else "\n")
+ else:
+ block_comment.append(comment if comment else "\n")
+ continue
+ elif block_comment:
+ # Generate a block comment JSON member
+ if with_comments:
+ comment_type = "comment_" if line.strip() and block_comment[-1] != "\n" else "section_"
+ while block_comment[-1] == "\n":
+ block_comment.pop()
+ lines.append("\"{}{}\": {},".format(comment_type, ctr, encode_basestring(" ".join(block_comment))))
+ ctr += 1
+ block_comment = []
+ elif inline_comment:
+ # Generate an inline comment JSON member
+ if with_comments:
+ lines.insert(-1, "\"comment_{}\": {},".format(ctr, encode_basestring(" ".join(inline_comment))))
+ ctr += 1
+ inline_comment = []
+
+ # Check if the current line contains an inline comment, if so extract
+ # the comment and add to the current inline comments list
+ m = comments.match(line)
+ if m:
+ inline_comment.append(m.group(2))
+ append = m.group(1)
+ else:
+ append = line
+
+ # Do some simple value conversions
+ append = append.rstrip().replace(" None", ' ""').replace(" True", " true").replace(" False", " false").replace("\\", "\\\\")
+
+ # Look for special substitutions
+ if substitutions:
+ for subskey in substitutions.keys():
+ pos = append.find(subskey)
+ if pos >= 0:
+ actual = append[pos + len(subskey) + 2:]
+ comma = ""
+ if actual[-1] == ",":
+ actual = actual[:-1]
+ comma = ","
+ actual = actual[:-2]
+ append = "{}{}{}".format(
+ append[:pos],
+ json.dumps(substitutions[subskey][actual]),
+ comma,
+ )
+ break
+
+
+ # Look for numeric expressions in the value and eval() those to get a value
+ # that is compatible with JSON
+ m = value.match(append)
+ if m:
+ expression = eval(m.group(2))
+ append = "{}{}{}".format(m.group(1), expression, m.group(3))
+
+ # Remove trailing commas for the last items in an array
+ # or object as JSON does not like that
+ if append.strip() and append.strip()[0] in ("]", "}"):
+ if lines[-1][-1] == ",":
+ lines[-1] = lines[-1][:-1]
+
+ # Line is ready to use
+ lines.append(append)
+
+ newj = "\n".join(lines)
+ if verbose:
+ print(newj)
+
+ # Created an ordered JSON object
+ j = json.loads(newj, object_pairs_hook=OrderedDict)
+ return j
+
+
+
+class OrderedPlistWriter(PlistWriter):
+ """
+ L{PlistWriter} that maintains the order of dict items. It also handles special keys
+ "section_" and "comment_" which are used to insert XML comments in the plist output.
+ Some additional blank lines are also added for readability of the plist.
+ """
+
+ def writeDict(self, d):
+ """
+ Basically a copy of L{PlistWriter.writeDict} that does not sort the dict keys
+ if the dict type is L{OrderedDict}.
+ """
+ self.beginElement("dict")
+ items = d.items()
+ if not isinstance(d, OrderedDict):
+ items.sort()
+ newline = False
+ for key, value in items:
+ if not isinstance(key, (str, unicode)):
+ raise TypeError("keys must be strings")
+ if newline:
+ self.writeln("")
+ if key.startswith("section_"):
+ self.writeComment(value)
+ newline = True
+ elif key.startswith("comment_"):
+ self.writeComment(value)
+ newline = False
+ else:
+ self.simpleElement("key", key)
+ self.writeValue(value)
+ newline = True
+ self.endElement("dict")
+
+
+ def writeComment(self, comment):
+
+ indent = self.indentLevel * self.indent
+
+ paragraphs = comment.splitlines()
+ for ctr, paragraph in enumerate(comment.splitlines()):
+ line = _escapeAndEncode(paragraph).strip()
+ initial_indent = ("{}<!-- " if ctr == 0 else "{} ").format(indent)
+ subsequent_indent = "{} ".format(indent)
+
+ line = textwrap.fill(
+ line,
+ width=80,
+ initial_indent=initial_indent,
+ subsequent_indent=subsequent_indent,
+ )
+
+ if ctr == len(paragraphs) - 1:
+ self.file.write("{} -->\n".format(line))
+ else:
+ self.file.write("{}\n\n".format(line))
+
+
+
+def writeOrderedPlist(rootObject, pathOrFile):
+ """
+ A copy of L{plistlib.writePlist} that uses an L{OrderedPlistWriter} to
+ write the plist.
+ """
+
+ """Write 'rootObject' to a .plist file. 'pathOrFile' may either be a
+ file name or a (writable) file object.
+ """
+ didOpen = 0
+ if isinstance(pathOrFile, (str, unicode)):
+ pathOrFile = open(pathOrFile, "w")
+ didOpen = 1
+ writer = OrderedPlistWriter(pathOrFile)
+ writer.writeln("<plist version=\"1.0\">")
+ writer.writeValue(rootObject)
+ writer.writeln("</plist>")
+ if didOpen:
+ pathOrFile.close()
+
+
+
+def writeOrderedPlistToString(rootObject):
+ """
+ A copy of L{plistlib.writePlistToString} that uses an L{writeOrderedPlist} to
+ write the plist.
+ """
+
+ """Return 'rootObject' as a plist-formatted string.
+ """
+ f = StringIO()
+ writeOrderedPlist(rootObject, f)
+ return f.getvalue()
+
+if __name__ == '__main__':
+
+ # Generate a set of serialized JSON objects for the *_PARAMS config items
+ maps = {
+ "DEFAULT_SERVICE_PARAMS": "",
+ "DEFAULT_RESOURCE_PARAMS": "",
+ "DEFAULT_AUGMENT_PARAMS": "",
+ "DEFAULT_DIRECTORY_ADDRESSBOOK_PARAMS": "",
+ }
+
+ for item in maps.keys():
+ lines = parseConfigItem(item)
+ maps[item] = processConfig(lines, with_comments=True, verbose=False)
+
+ # Generate the plist for the default config, substituting for the *_PARAMS items
+ lines = parseConfigItem("DEFAULT_CONFIG")
+ j = processConfig(lines, with_comments=True, verbose=False, substitutions=maps)
+ print(writeOrderedPlistToString(j))
Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/stdconfig.py 2015-12-17 20:18:32 UTC (rev 15403)
+++ CalendarServer/trunk/twistedcaldav/stdconfig.py 2015-12-18 20:02:34 UTC (rev 15404)
@@ -57,15 +57,15 @@
DEFAULT_SERVICE_PARAMS = {
"xml": {
- "recordTypes": ("users", "groups"),
+ "recordTypes": ["users", "groups"],
"xmlFile": "accounts.xml",
},
"opendirectory": {
- "recordTypes": ("users", "groups"),
+ "recordTypes": ["users", "groups"],
"node": "/Search",
},
"ldap": {
- "recordTypes": ("users", "groups"),
+ "recordTypes": ["users", "groups"],
"uri": "ldap://localhost/",
"credentials": {
"dn": None,
@@ -80,17 +80,17 @@
"addresses": "cn=addresses",
},
"mapping": {
- "uid": ["apple-generateduid", ],
- "guid": ["apple-generateduid", ],
- "shortNames": ["uid", ],
- "fullNames": ["cn", ],
- "emailAddresses": ["mail", ],
- "memberDNs": ["uniqueMember", ],
+ "uid": ["apple-generateduid"],
+ "guid": ["apple-generateduid"],
+ "shortNames": ["uid"],
+ "fullNames": ["cn"],
+ "emailAddresses": ["mail"],
+ "memberDNs": ["uniqueMember"],
"hasCalendars": [],
"autoScheduleMode": [],
"autoAcceptGroup": [],
- "readWriteProxy": ["icsContact", ],
- "readOnlyProxy": ["icsSecondaryOwners", ],
+ "readWriteProxy": ["icsContact"],
+ "readOnlyProxy": ["icsSecondaryOwners"],
"serviceNodeUID": [],
},
"extraFilters": {
@@ -106,18 +106,18 @@
DEFAULT_RESOURCE_PARAMS = {
"xml": {
- "recordTypes": ("locations", "resources", "addresses"),
+ "recordTypes": ["locations", "resources", "addresses"],
"xmlFile": "resources.xml",
},
"opendirectory": {
- "recordTypes": ("locations", "resources", "addresses"),
+ "recordTypes": ["locations", "resources", "addresses"],
"node": "/Search",
},
}
DEFAULT_AUGMENT_PARAMS = {
"twistedcaldav.directory.augment.AugmentXMLDB": {
- "xmlFiles": ["augments.xml", ],
+ "xmlFiles": ["augments.xml"],
"statSeconds": 15,
},
"twistedcaldav.directory.augment.AugmentSqliteDB": {
@@ -132,7 +132,7 @@
}
-directoryAddressBookBackingServiceDefaultParams = {
+DEFAULT_DIRECTORY_ADDRESSBOOK_PARAMS = {
"twistedcaldav.directory.xmlfile.XMLDirectoryService": {
"xmlFile": "/etc/carddavd/accounts.xml",
},
@@ -157,9 +157,8 @@
},
}
+# Note: Don't use None values below; that confuses the command-line parser.
DEFAULT_CONFIG = {
- # Note: Don't use None values below; that confuses the command-line parser.
-
#
# Public network address information
#
@@ -169,6 +168,7 @@
# default. For example, it may be the address of a load balancer or
# proxy which forwards connections to the server.
#
+
"ServerHostName": "", # Network host name.
"HTTPPort": 0, # HTTP port (0 to disable HTTP)
"SSLPort": 0, # SSL port (0 to disable HTTPS)
@@ -177,12 +177,11 @@
"SSLMethod": "SSLv23_METHOD", # SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
"SSLCiphers": "RC4-SHA:HIGH:!ADH",
- # Max-age value for Strict-Transport-Security header; set to 0 to
- # disable header.
+ # Max-age value for Strict-Transport-Security header; set to 0 to disable header.
"StrictTransportSecuritySeconds": 7 * 24 * 60 * 60,
#
- # Network address configuration information
+ # Network address configuration information.
#
# This configures the actual network address that the server binds to.
#
@@ -200,17 +199,12 @@
"BindAddresses": [], # List of IP addresses to bind to [empty = all]
"BindHTTPPorts": [], # List of port numbers to bind to for HTTP
# [empty = same as "Port"]
- "BindSSLPorts": [], # List of port numbers to bind to for SSL
- # [empty = same as "SSLPort"]
- "InheritFDs": [], # File descriptors to inherit for HTTP requests
- # (empty = don't inherit)
- "InheritSSLFDs": [], # File descriptors to inherit for HTTPS requests
- # (empty = don't inherit)
- "MetaFD": 0, # Inherited file descriptor to call recvmsg() on to
- # receive sockets (none = don't inherit)
+ "BindSSLPorts": [], # List of port numbers to bind to for SSL [empty = same as "SSLPort"]
+ "InheritFDs": [], # File descriptors to inherit for HTTP requests [empty = don't inherit]
+ "InheritSSLFDs": [], # File descriptors to inherit for HTTPS requests [empty = don't inherit]
+ "MetaFD": 0, # Inherited file descriptor to call recvmsg() on to receive sockets (none = don't inherit)
- "UseMetaFD": True, # Use a 'meta' FD, i.e. an FD to transmit other FDs
- # to slave processes.
+ "UseMetaFD": True, # Use a 'meta' FD, i.e. an FD to transmit other FDs to slave processes.
"UseDatabase": True, # True: database; False: files
@@ -261,11 +255,13 @@
#
# Work queue configuration information
#
+
"WorkQueue": {
"queuePollInterval": 0.1, # Interval in seconds for job queue polling
"queueOverdueTimeout": 300, # Number of seconds before an assigned job is considered overdue
"queuePollingBackoff": [ # Array of array that describe the threshold and new polling interval
- [60, 60], [5, 1] # for job queue polling back off
+ # for job queue polling back off
+ [60, 60], [5, 1]
],
"overloadLevel": 95, # Queue capacity (percentage) which causes job processing to halt
@@ -426,7 +422,7 @@
"AccessLogFile" : "access.log", # Apache-style access log
"ErrorLogFile" : "error.log", # Server activity log
"AgentLogFile" : "agent.log", # Agent activity log
- "UtilityLogFile" : "{}.log".format(basename(sys.argv[0])), # Command line utility log
+ "UtilityLogFile" : "utility.log", # Utility log - name will be dynamically changed to executable name
"ErrorLogEnabled" : True, # True = use log file, False = stdout
"ErrorLogRotateMB" : 10, # Rotate error log after so many megabytes
"ErrorLogMaxRotatedFiles" : 5, # Retain this many error log files
@@ -480,11 +476,11 @@
# Process management
#
- # Username and Groupname to drop privileges to, if empty privileges will
- # not be dropped.
-
+ # Username and Groupname to drop privileges to, if empty privileges will not be dropped.
"UserName": "",
"GroupName": "",
+
+ # Multi-process
"ProcessType": "Combined",
"MultiProcess": {
"ProcessCount": 0,
@@ -502,14 +498,10 @@
"Enabled" : True,
"Seconds" : 60, # How often to check memory sizes (in seconds)
"Bytes" : 2 * 1024 * 1024 * 1024, # Memory limit (RSS in bytes)
- "ResidentOnly" : True, # True: only take into account resident memory;
- # False: include virtual memory
+ "ResidentOnly" : True, # True: only take into account resident memory; False: include virtual memory
},
- #
- # Service ACLs
- #
- "EnableSACLs": False,
+ "EnableSACLs": False, # Service ACLs
"EnableReadOnlyServer": False, # Make all data read-only
@@ -616,17 +608,16 @@
# If on, it will also cause new accounts to provision with separate
# calendars for events and tasks.
- "SupportedComponents" : [ # Set of supported iCalendar components
+ "SupportedComponents" : [ # Set of supported iCalendar components
"VEVENT",
"VTODO",
- # "VPOLL",
],
"EnableTrashCollection": False, # Enable Trash Collection
"ExposeTrashCollection": False, # Expose Trash Collection as a resource
"ParallelUpgrades": False, # Perform upgrades - currently only the
- # database -> filesystem migration - but in
+ # database to filesystem migration - but in
# the future, hopefully all relevant
# upgrades - in parallel in subprocesses.
@@ -670,7 +661,7 @@
"DirectoryAddressBook": {
"Enabled": True,
"type": "twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService",
- "params": directoryAddressBookBackingServiceDefaultParams["twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService"],
+ "params": DEFAULT_DIRECTORY_ADDRESSBOOK_PARAMS["twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService"],
"name": "directory",
"MaxQueryResults": 1000,
},
@@ -679,14 +670,10 @@
# /XXX CardDAV
- #
# Web-based administration
- #
"EnableWebAdmin" : True,
- #
# JSON control API - only for testing
- #
"EnableControlAPI" : False,
#
@@ -974,8 +961,7 @@
# processes. If blank, then an AF_INET socket is used instead.
"ControlSocket": "caldavd.sock",
- # Support for Content-Encoding compression options as specified in
- # RFC2616 Section 3.5
+ # Support for Content-Encoding compression options as specified in RFC2616 Section 3.5
# Defaults off, because it weakens TLS (CRIME attack).
"ResponseCompression": False,
@@ -999,8 +985,7 @@
"ServerEnabled": True,
"BindAddress": "127.0.0.1",
"Port": 11311,
- "HandleCacheTypes": [
- "Default",
+ "HandleCacheTypes": [ # Possible types:
# "OpenDirectoryBacker",
# "ImplicitUIDLock",
# "RefreshUIDLock",
@@ -1012,6 +997,7 @@
# "SQL.props",
# "SQL.calhome",
# "SQL.adbkhome",
+ "Default",
]
},
# "Shared": {
@@ -1051,9 +1037,9 @@
"Options": [
"-c standard_conforming_strings=on",
],
- "Ctl": "pg_ctl", # Iff the DBType is '', and we're spawning postgres
+ "Ctl": "pg_ctl", # If the DBType is '', and we're spawning postgres
# ourselves, where is the pg_ctl tool to spawn it with?
- "Init": "initdb", # Iff the DBType is '', and we're spawning postgres
+ "Init": "initdb", # If the DBType is '', and we're spawning postgres
# ourselves, where is the initdb tool to create its
# database cluster with?
},
@@ -1110,12 +1096,10 @@
# The RootResource uses a twext property store. Specify the class here
"RootResourcePropStoreClass": "txweb2.dav.xattrprops.xattrPropertyStore",
- # Used in the command line utilities to specify which service class to
- # use to carry out work.
+ # Used in the command line utilities to specify which service class to use to carry out work.
"UtilityServiceClass": "",
- # Inbox items created more than MigratedInboxDaysCutoff days in the past are removed
- # during migration
+ # Inbox items created more than MigratedInboxDaysCutoff days in the past are removed during migration
"MigratedInboxDaysCutoff": 60,
# The default timezone for the server; on OS X you can leave this empty and the
@@ -1496,19 +1480,19 @@
newParams = items["DirectoryAddressBook"].get("params", {})
mergeData(oldParams, newParams)
else:
- if dsType in directoryAddressBookBackingServiceDefaultParams:
- configDict.DirectoryAddressBook.params = copy.deepcopy(directoryAddressBookBackingServiceDefaultParams[dsType])
+ if dsType in DEFAULT_DIRECTORY_ADDRESSBOOK_PARAMS:
+ configDict.DirectoryAddressBook.params = copy.deepcopy(DEFAULT_DIRECTORY_ADDRESSBOOK_PARAMS[dsType])
else:
configDict.DirectoryAddressBook.params = {}
for param in items.get("DirectoryAddressBook", {}).get("params", {}):
- if param not in directoryAddressBookBackingServiceDefaultParams[dsType]:
+ if param not in DEFAULT_DIRECTORY_ADDRESSBOOK_PARAMS[dsType]:
raise ConfigurationError("Parameter %s is not supported by service %s" % (param, dsType))
mergeData(configDict, items)
for param in tuple(configDict.DirectoryAddressBook.params):
- if param not in directoryAddressBookBackingServiceDefaultParams[configDict.DirectoryAddressBook.type]:
+ if param not in DEFAULT_DIRECTORY_ADDRESSBOOK_PARAMS[configDict.DirectoryAddressBook.type]:
del configDict.DirectoryAddressBook.params[param]
@@ -1642,6 +1626,11 @@
+def _updateUtilityLog(configDict, reloading=False):
+ configDict["UtilityLogFile"] = "{}.log".format(basename(sys.argv[0])), # Command line utility log
+
+
+
def _updateLogLevels(configDict, reloading=False):
log.levels().clearLogLevels()
@@ -1787,12 +1776,12 @@
_updateACLs,
_updateRejectClients,
_updateClientFixes,
+ _updateUtilityLog,
_updateLogLevels,
_updateNotifications,
_updateICalendar,
_updateScheduling,
_updateSharing,
- # _updateServers,
_updateCompliance,
)
Added: CalendarServer/trunk/twistedcaldav/test/test_dumpconfig.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_dumpconfig.py (rev 0)
+++ CalendarServer/trunk/twistedcaldav/test/test_dumpconfig.py 2015-12-18 20:02:34 UTC (rev 15404)
@@ -0,0 +1,135 @@
+##
+# Copyright (c) 2015 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from unittest.case import TestCase
+from twistedcaldav.dumpconfig import parseConfigItem, processConfig, \
+ writeOrderedPlistToString
+from collections import OrderedDict
+
+class TestDumpConfig (TestCase):
+
+ def test_parseConfigItem(self):
+ """
+ Make sure L{parseConfigItem} can parse the DEFAULT_* items
+ """
+
+ items = {
+ "DEFAULT_SERVICE_PARAMS",
+ "DEFAULT_RESOURCE_PARAMS",
+ "DEFAULT_AUGMENT_PARAMS",
+ "DEFAULT_DIRECTORY_ADDRESSBOOK_PARAMS",
+ "DEFAULT_CONFIG",
+ }
+
+ for item in items:
+ lines = parseConfigItem(item)
+ self.assertNotEqual(len(lines), 0, msg="Failed {}".format(item))
+
+
+ def test_writeOrderedPlistToString(self):
+ """
+ Make sure L{writeOrderedPlistToString} preserves key order
+ """
+
+ data = OrderedDict()
+ data["KeyB"] = "1"
+ data["KeyA"] = "2"
+ data["KeyC"] = "3"
+ data["KeyE"] = "4"
+ data["KeyD"] = "5"
+
+ plist = writeOrderedPlistToString(data)
+ self.assertEqual(plist, """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+\t<key>KeyB</key>
+\t<string>1</string>
+
+\t<key>KeyA</key>
+\t<string>2</string>
+
+\t<key>KeyC</key>
+\t<string>3</string>
+
+\t<key>KeyE</key>
+\t<string>4</string>
+
+\t<key>KeyD</key>
+\t<string>5</string>
+</dict>
+</plist>
+""")
+
+
+ def test_plistWithComments(self):
+ """
+ Make sure L{writeOrderedPlistToString} preserves key order
+ """
+
+ data = OrderedDict()
+ data["comment_1"] = "All about KeyB"
+ data["KeyB"] = "1"
+ data["section_2"] = "Details on KeyA & KeyC"
+ data["comment_3"] = "All about KeyA"
+ data["KeyA"] = "2"
+ data["comment_4"] = "All about KeyC"
+ data["KeyC"] = "3"
+
+ plist = writeOrderedPlistToString(data)
+ self.assertEqual(plist, """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+\t<!-- All about KeyB -->
+\t<key>KeyB</key>
+\t<string>1</string>
+
+\t<!-- Details on KeyA & KeyC -->
+
+\t<!-- All about KeyA -->
+\t<key>KeyA</key>
+\t<string>2</string>
+
+\t<!-- All about KeyC -->
+\t<key>KeyC</key>
+\t<string>3</string>
+</dict>
+</plist>
+""")
+
+
+ def test_fullPlistDump(self):
+ """
+ Make sure a full dump of DEFAULT_CONFIG works
+ """
+
+ maps = {
+ "DEFAULT_SERVICE_PARAMS": "",
+ "DEFAULT_RESOURCE_PARAMS": "",
+ "DEFAULT_AUGMENT_PARAMS": "",
+ "DEFAULT_DIRECTORY_ADDRESSBOOK_PARAMS": "",
+ }
+
+ for item in maps.keys():
+ lines = parseConfigItem(item)
+ maps[item] = processConfig(lines, with_comments=True, verbose=False)
+
+ # Generate the plist for the default config, substituting for the *_PARAMS items
+ lines = parseConfigItem("DEFAULT_CONFIG")
+ j = processConfig(lines, with_comments=True, verbose=False, substitutions=maps)
+ result = writeOrderedPlistToString(j)
+ self.assertIn('<plist version="1.0">', result)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20151218/3fa312bc/attachment-0001.html>
More information about the calendarserver-changes
mailing list