[CalendarServer-changes] [9133] CalendarServer/branches/users/gaya/ldapdirectorybacker
source_changes at macosforge.org
source_changes at macosforge.org
Mon Apr 16 16:10:11 PDT 2012
Revision: 9133
http://trac.macosforge.org/projects/calendarserver/changeset/9133
Author: gaya at apple.com
Date: 2012-04-16 16:10:10 -0700 (Mon, 16 Apr 2012)
Log Message:
-----------
support ldap group vCards
Modified Paths:
--------------
CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest.plist
CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectorybacker.py
CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
Added Paths:
-----------
CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest2.plist
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest.plist
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest.plist 2012-04-16 22:38:03 UTC (rev 9132)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest.plist 2012-04-16 23:10:10 UTC (rev 9133)
@@ -1269,39 +1269,6 @@
<string>EMailAddress</string>
</dict>
</dict>
- <!-- people vCards for another server. Unused
- <dict>
- <key>ldapAttrToDSAttrMap</key>
- <dict>
- <key>givenName</key>
- <string>FirstName</string>
- <key>sn</key>
- <string>LastName</string>
- <key>cn</key>
- <array>
- <string>RealName</string>
- <string>RecordName</string>
- </array>
- <key>mail</key>
- <string>EMailAddress</string>
- <key>uid</key>
- <string>GeneratedUID</string>
- </dict>
- <key>rdn</key>
- <string>ou=People</string>
- <key>filter</key>
- <string></string>
- <key>vcardPropToLdapAttrMap</key>
- <dict>
- <key>FN</key>
- <string>cn</string>
- <key>EMAIL</key>
- <string>mail</string>
- <key>UID</key>
- <string>uid</string>
- </dict>
- </dict>
- -->
</array>
</dict>
</dict>
Added: CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest2.plist
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest2.plist (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest2.plist 2012-04-16 23:10:10 UTC (rev 9133)
@@ -0,0 +1,1277 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Copyright (c) 2006-2012 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.
+ -->
+
+<!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
+
+ 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 [empty = system host name] -->
+ <key>ServerHostName</key>
+ <string></string> <!-- The hostname clients use when connecting -->
+
+ <!-- Enable Calendars -->
+ <key>EnableCalDAV</key>
+ <true/>
+
+ <!-- Enable AddressBooks -->
+ <key>EnableCardDAV</key>
+ <true/>
+
+ <!-- HTTP port [0 = disable HTTP] -->
+ <key>HTTPPort</key>
+ <integer>8008</integer>
+
+ <!-- SSL port [0 = disable HTTPS] -->
+ <!-- (Must also configure SSLCertificate and SSLPrivateKey below) -->
+ <key>SSLPort</key>
+ <integer>8443</integer>
+
+ <!-- Enable listening on SSL port(s) -->
+ <key>EnableSSL</key>
+ <true/>
+
+ <!-- Redirect non-SSL ports to an SSL port (if configured for SSL) -->
+ <key>RedirectHTTPToHTTPS</key>
+ <false/>
+
+
+ <!--
+ Network address configuration information
+
+ This configures the actual network address that the server binds to.
+ -->
+
+ <!-- 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>
+ <integer>8008</integer>
+ <integer>8800</integer>
+ </array>
+
+ <!-- List of port numbers to bind to for SSL [empty = same as "SSLPort"] -->
+ <key>BindSSLPorts</key>
+ <array>
+ <integer>8443</integer>
+ <integer>8843</integer>
+ </array>
+
+
+ <!--
+ Data Store
+ -->
+
+ <!-- Server root -->
+ <key>ServerRoot</key>
+ <string>./data</string>
+
+ <!-- Database connection -->
+ <!--
+ <key>DBType</key>
+ <string>postgres</string>
+ <key>DSN</key>
+ <string>:caldav:caldav:::</string>
+ -->
+
+ <!-- Data root -->
+ <key>DataRoot</key>
+ <string>Data</string>
+
+ <!-- Database root -->
+ <key>DatabaseRoot</key>
+ <string>Database</string>
+
+ <!-- Document root -->
+ <key>DocumentRoot</key>
+ <string>Documents</string>
+
+ <!-- Configuration root -->
+ <key>ConfigRoot</key>
+ <string>./conf</string>
+
+ <!-- Run root -->
+ <key>RunRoot</key>
+ <string>Logs/state</string>
+
+ <!-- Child aliases -->
+ <key>Aliases</key>
+ <dict>
+ <!--
+ <key>foo</key>
+ <dict>
+ <key>path</key>
+ <string>/path/to/foo</string>
+ </dict>
+ -->
+ </dict>
+
+
+ <!--
+ Quotas and limits
+ -->
+
+ <!-- User quota (in bytes) [0 = no quota] applies to attachments only -->
+ <key>UserQuota</key>
+ <integer>104857600</integer><!-- 100Mb -->
+
+ <!-- Maximum number of calendars/address books allowed in a home -->
+ <!-- 0 for no limit -->
+ <key>MaxCollectionsPerHome</key>
+ <integer>50</integer>
+
+ <!-- Maximum number of resources in a calendar/address book -->
+ <!-- 0 for no limit -->
+ <key>MaxResourcesPerCollection</key>
+ <integer>10000</integer>
+
+ <!-- Maximum resource size (in bytes) -->
+ <key>MaxResourceSize</key>
+ <integer>1048576</integer> <!-- 1Mb -->
+
+ <!-- Maximum number of unique attendees per entire event -->
+ <!-- 0 for no limit -->
+ <key>MaxAttendeesPerInstance</key>
+ <integer>100</integer>
+
+ <!-- Maximum number of instances allowed during expansion -->
+ <!-- 0 for no limit -->
+ <key>MaxAllowedInstances</key>
+ <integer>3000</integer>
+
+ <!-- Maximum number of instances allowed for a single RRULE -->
+ <!-- 0 for no limit -->
+ <key>MaxInstancesForRRULE</key>
+ <integer>400</integer>
+
+ <!--
+ Directory service
+
+ A directory service provides information about principals (eg.
+ users, groups, locations and resources) to the server.
+
+ A variety of directory services are available for use.
+ -->
+
+ <!-- XML File Directory Service -->
+ <key>DirectoryService</key>
+ <dict>
+ <key>type</key>
+ <string>twistedcaldav.directory.xmlfile.XMLDirectoryService</string>
+
+ <key>params</key>
+ <dict>
+ <key>xmlFile</key>
+ <string>./conf/auth/accounts-test.xml</string>
+ </dict>
+ </dict>
+
+ <!-- Open Directory Service (Mac OS X) -->
+ <!--
+ <key>DirectoryService</key>
+ <dict>
+ <key>type</key>
+ <string>twistedcaldav.directory.appleopendirectory.OpenDirectoryService</string>
+
+ <key>params</key>
+ <dict>
+ <key>node</key>
+ <string>/Search</string>
+ <key>cacheTimeout</key>
+ <integer>10</integer>
+ </dict>
+ </dict>
+ -->
+
+ <!-- OpenLDAP Directory Service -->
+ <!--
+ <key>DirectoryService</key>
+ <dict>
+ <key>type</key>
+ <string>twistedcaldav.directory.ldapdirectory.LdapDirectoryService</string>
+
+ <key>params</key>
+ <dict>
+ <key>restrictEnabledRecords</key>
+ <false/>
+ <key>restrictToGroup</key>
+ <string>odtestgrouptop</string>
+ <key>cacheTimeout</key>
+ <integer>30</integer>
+ <key>uri</key>
+ <string>ldap://example.com/</string>
+ <key>tls</key>
+ <false/>
+ <key>tlsCACertFile</key>
+ <string></string>
+ <key>tlsCACertDir</key>
+ <string></string>
+ <key>tlsRequireCert</key>
+ <string>never</string>
+ <key>credentials</key>
+ <dict>
+ <key>dn</key>
+ <string></string>
+ <key>password</key>
+ <string></string>
+ </dict>
+ <key>authMethod</key>
+ <string>LDAP</string>
+ <key>rdnSchema</key>
+ <dict>
+ <key>base</key>
+ <string>dc=example,dc=com</string>
+ <key>guidAttr</key>
+ <string>apple-generateduid</string>
+ <key>users</key>
+ <dict>
+ <key>rdn</key>
+ <string>cn=users</string>
+ <key>attr</key>
+ <string>uid</string>
+ <key>emailSuffix</key>
+ <string></string>
+ <key>filter</key>
+ <string></string>
+ <key>loginEnabledAttr</key>
+ <string></string>
+ <key>loginEnabledValue</key>
+ <string>yes</string>
+ <key>mapping</key>
+ <dict>
+ <key>recordName</key>
+ <string>uid</string>
+ <key>fullName</key>
+ <string>cn</string>
+ <key>emailAddresses</key>
+ <string>mail</string>
+ <key>firstName</key>
+ <string>givenName</string>
+ <key>lastName</key>
+ <string>sn</string>
+ </dict>
+ </dict>
+ <key>groups</key>
+ <dict>
+ <key>rdn</key>
+ <string>cn=groups</string>
+ <key>attr</key>
+ <string>cn</string>
+ <key>emailSuffix</key>
+ <string></string>
+ <key>filter</key>
+ <string></string>
+ <key>mapping</key>
+ <dict>
+ <key>recordName</key>
+ <string>cn</string>
+ <key>fullName</key>
+ <string>cn</string>
+ <key>emailAddresses</key>
+ <string>mail</string>
+ <key>firstName</key>
+ <string>givenName</string>
+ <key>lastName</key>
+ <string>sn</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>groupSchema</key>
+ <dict>
+ <key>membersAttr</key>
+ <string>apple-group-memberguid</string>
+ <key>nestedGroupsAttr</key>
+ <string>apple-group-nestedgroup</string>
+ <key>memberIdAttr</key>
+ <string>apple-generateduid</string>
+ </dict>
+ <key>resourceSchema</key>
+ <dict>
+ <key>resourceInfoAttr</key>
+ <string>apple-resource-info</string>
+ <key>autoScheduleAttr</key>
+ <string></string>
+ <key>autoScheduleEnabledValue</key>
+ <string>yes</string>
+ <key>proxyAttr</key>
+ <string></string>
+ <key>readOnlyProxyAttr</key>
+ <string></string>
+ </dict>
+ </dict>
+ </dict>
+ -->
+
+ <!-- Resource and Location Service -->
+ <key>ResourceService</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>type</key>
+ <string>twistedcaldav.directory.xmlfile.XMLDirectoryService</string>
+
+ <key>params</key>
+ <dict>
+ <key>xmlFile</key>
+ <string>./conf/auth/resources-test.xml</string>
+ </dict>
+ </dict>
+
+ <!-- XML File Augment Service -->
+ <key>AugmentService</key>
+ <dict>
+ <key>type</key>
+ <string>twistedcaldav.directory.augment.AugmentXMLDB</string>
+
+ <key>params</key>
+ <dict>
+ <key>xmlFiles</key>
+ <array>
+ <string>./conf/auth/augments-test.xml</string>
+ </array>
+ </dict>
+ </dict>
+
+ <!-- Sqlite Augment Service -->
+ <!--
+ <key>AugmentService</key>
+ <dict>
+ <key>type</key>
+ <string>twistedcaldav.directory.augment.AugmentSqliteDB</string>
+
+ <key>params</key>
+ <dict>
+ <key>dbpath</key>
+ <string>./conf/auth/augments.sqlite</string>
+ </dict>
+ </dict>
+ -->
+
+ <!-- PostgreSQL Augment Service -->
+ <!--
+ <key>AugmentService</key>
+ <dict>
+ <key>type</key>
+ <string>twistedcaldav.directory.augment.AugmentPostgreSQLDB</string>
+
+ <key>params</key>
+ <dict>
+ <key>host</key>
+ <string>localhost</string>
+ <key>database</key>
+ <string>augments</string>
+ </dict>
+ </dict>
+ -->
+
+ <!-- Sqlite ProxyDB Service -->
+ <key>ProxyDBService</key>
+ <dict>
+ <key>type</key>
+ <string>twistedcaldav.directory.calendaruserproxy.ProxySqliteDB</string>
+
+ <key>params</key>
+ <dict>
+ <key>dbpath</key>
+ <string>proxies.sqlite</string>
+ </dict>
+ </dict>
+
+ <!-- PostgreSQL ProxyDB Service -->
+ <!--
+ <key>ProxyDBService</key>
+ <dict>
+ <key>type</key>
+ <string>twistedcaldav.directory.calendaruserproxy.ProxyPostgreSQLDB</string>
+
+ <key>params</key>
+ <dict>
+ <key>host</key>
+ <string>localhost</string>
+ <key>database</key>
+ <string>proxies</string>
+ </dict>
+ </dict>
+ -->
+
+ <key>ProxyLoadFromFile</key>
+ <string>./conf/auth/proxies-test.xml</string>
+
+
+ <!--
+ Special principals
+
+ These principals are granted special access and/or perform
+ special roles on the server.
+ -->
+
+ <!-- Principals with "DAV:all" access (relative URLs) -->
+ <key>AdminPrincipals</key>
+ <array>
+ <string>/principals/__uids__/admin/</string>
+ </array>
+
+ <!-- Principals with "DAV:read" access (relative URLs) -->
+ <key>ReadPrincipals</key>
+ <array>
+ <!-- <string>/principals/__uids__/983C8238-FB6B-4D92-9242-89C0A39E5F81/</string> -->
+ </array>
+
+ <!-- Create "proxy access" principals -->
+ <key>EnableProxyPrincipals</key>
+ <true/>
+
+
+ <!--
+ Permissions
+ -->
+
+ <!-- Anonymous read access for root resource -->
+ <key>EnableAnonymousReadRoot</key>
+ <true/>
+
+ <!-- Anonymous read access for resource hierarchy -->
+ <key>EnableAnonymousReadNav</key>
+ <false/>
+
+ <!-- Enables directory listings for principals -->
+ <key>EnablePrincipalListings</key>
+ <true/>
+
+ <!-- Render calendar collections as a monolithic iCalendar object -->
+ <key>EnableMonolithicCalendars</key>
+ <true/>
+
+
+ <!--
+ Authentication
+ -->
+
+ <key>Authentication</key>
+ <dict>
+
+ <!-- Clear text; best avoided -->
+ <key>Basic</key>
+ <dict>
+ <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>
+ </dict>
+
+ <!-- Kerberos/SPNEGO -->
+ <key>Kerberos</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>ServicePrincipal</key>
+ <string></string>
+ </dict>
+
+ <!-- Wikiserver authentication (Mac OS X) -->
+ <key>Wiki</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>Cookie</key>
+ <string>sessionID</string>
+ <key>URL</key>
+ <string>http://127.0.0.1/RPC2</string>
+ <key>UserMethod</key>
+ <string>userForSession</string>
+ <key>WikiMethod</key>
+ <string>accessLevelForUserWikiCalendar</string>
+ </dict>
+
+ </dict>
+
+
+ <!--
+ Logging
+ -->
+
+ <!-- Log root -->
+ <key>LogRoot</key>
+ <string>Logs</string>
+
+ <!-- Apache-style access log -->
+ <key>AccessLogFile</key>
+ <string>access.log</string>
+ <key>RotateAccessLog</key>
+ <false/>
+
+ <!-- Server activity log -->
+ <key>ErrorLogFile</key>
+ <string>error.log</string>
+
+ <!-- Log levels -->
+ <key>DefaultLogLevel</key>
+ <string>debug</string> <!-- debug, info, warn, error -->
+
+ <!-- Log level overrides for specific functionality -->
+ <key>LogLevels</key>
+ <dict>
+ <!--
+ <key>twistedcaldav.directory.appleopendirectory.OpenDirectoryService</key>
+ <string>debug</string>
+ -->
+ </dict>
+
+ <!-- Server process ID file -->
+ <key>PIDFile</key>
+ <string>caldavd.pid</string>
+
+
+ <!--
+ Accounting
+ -->
+
+ <!-- Enable accounting for certain operations -->
+ <key>AccountingCategories</key>
+ <dict>
+ <key>iTIP</key>
+ <false/>
+ <key>HTTP</key>
+ <false/>
+ </dict>
+
+ <!-- Enable accounting for specific principals -->
+ <key>AccountingPrincipals</key>
+ <array>
+ <!-- <string>/principals/__uids__/454D85C0-09F0-4DC6-A3C6-97DFEB4622CD/</string> -->
+ </array>
+
+
+ <!--
+ SSL/TLS
+ -->
+
+ <!-- Public key -->
+ <key>SSLCertificate</key>
+ <string>twistedcaldav/test/data/server.pem</string>
+
+ <!-- SSL authority chain (for intermediate certs) -->
+ <key>SSLAuthorityChain</key>
+ <string></string>
+
+ <!-- Private key -->
+ <key>SSLPrivateKey</key>
+ <string>twistedcaldav/test/data/server.pem</string>
+
+
+ <!--
+ Process management
+ -->
+
+ <key>UserName</key>
+ <string></string>
+
+ <key>GroupName</key>
+ <string></string>
+
+ <key>ProcessType</key>
+ <string>Combined</string>
+
+ <key>MultiProcess</key>
+ <dict>
+ <key>ProcessCount</key>
+ <integer>2</integer> <!-- 0 = automatic -->
+ </dict>
+
+
+ <!--
+ Notifications
+ -->
+
+ <key>Notifications</key>
+ <dict>
+ <!-- Time spent coalescing notifications before delivery -->
+ <key>CoalesceSeconds</key>
+ <integer>3</integer>
+
+ <key>InternalNotificationHost</key>
+ <string>localhost</string>
+
+ <key>InternalNotificationPort</key>
+ <integer>62309</integer>
+
+ <key>Services</key>
+ <dict>
+ <key>SimpleLineNotifier</key>
+ <dict>
+ <!-- Simple line notification service (for testing) -->
+ <key>Service</key>
+ <string>twistedcaldav.notify.SimpleLineNotifierService</string>
+ <key>Enabled</key>
+ <false/>
+ <key>Port</key>
+ <integer>62308</integer>
+ </dict>
+
+ <key>XMPPNotifier</key>
+ <dict>
+ <!-- XMPP notification service -->
+ <key>Service</key>
+ <string>twistedcaldav.notify.XMPPNotifierService</string>
+ <key>Enabled</key>
+ <false/>
+
+ <!-- XMPP host and port to contact -->
+ <key>Host</key>
+ <string>xmpp.host.name</string>
+ <key>Port</key>
+ <integer>5222</integer>
+
+ <!-- Jabber ID and password for the server -->
+ <key>JID</key>
+ <string>jid at xmpp.host.name/resource</string>
+ <key>Password</key>
+ <string>password_goes_here</string>
+
+ <!-- PubSub service address -->
+ <key>ServiceAddress</key>
+ <string>pubsub.xmpp.host.name</string>
+
+ <!-- Apple-specific config -->
+ <key>CalDAV</key>
+ <dict>
+ <key>APSBundleID</key>
+ <string></string>
+ <key>SubscriptionURL</key>
+ <string></string>
+ </dict>
+ <key>CardDAV</key>
+ <dict>
+ <key>APSBundleID</key>
+ <string></string>
+ <key>SubscriptionURL</key>
+ <string></string>
+ </dict>
+
+ <key>NodeConfiguration</key>
+ <dict>
+ <key>pubsub#deliver_payloads</key>
+ <string>1</string>
+ <key>pubsub#persist_items</key>
+ <string>1</string>
+ </dict>
+
+ <!-- Sends a presence notification to XMPP server at this interval (prevents disconnect) -->
+ <key>KeepAliveSeconds</key>
+ <integer>120</integer>
+
+ <!-- Sends a pubsub publish to a particular heartbeat node at this interval -->
+ <key>HeartbeatMinutes</key>
+ <integer>30</integer>
+
+ <!-- List of glob-like expressions defining which XMPP JIDs can converse with the server (for debugging) -->
+ <key>AllowedJIDs</key>
+ <array>
+ <!--
+ <string>*.example.com</string>
+ -->
+ </array>
+ </dict>
+ </dict>
+ </dict>
+
+
+ <!--
+ Server-to-server protocol
+ -->
+
+ <key>Scheduling</key>
+ <dict>
+
+ <!-- CalDAV protocol options -->
+ <key>CalDAV</key>
+ <dict>
+ <key>EmailDomain</key>
+ <string></string>
+ <key>HTTPDomain</key>
+ <string></string>
+ <key>AddressPatterns</key>
+ <array>
+ </array>
+ <key>OldDraftCompatibility</key>
+ <true/>
+ <key>ScheduleTagCompatibility</key>
+ <true/>
+ <key>EnablePrivateComments</key>
+ <true/>
+ </dict>
+
+ <!-- iSchedule protocol options -->
+ <key>iSchedule</key>
+ <dict>
+ <key>Enabled</key>
+ <false/>
+ <key>AddressPatterns</key>
+ <array>
+ </array>
+ <key>Servers</key>
+ <string>servertoserver-test.xml</string>
+ </dict>
+
+ <!-- iMIP protocol options -->
+ <key>iMIP</key>
+ <dict>
+ <key>Enabled</key>
+ <false/>
+ <key>MailGatewayServer</key>
+ <string>localhost</string>
+ <key>MailGatewayPort</key>
+ <integer>62310</integer>
+ <key>Sending</key>
+ <dict>
+ <key>Server</key>
+ <string></string>
+ <key>Port</key>
+ <integer>587</integer>
+ <key>UseSSL</key>
+ <true/>
+ <key>Username</key>
+ <string></string>
+ <key>Password</key>
+ <string></string>
+ <key>Address</key>
+ <string></string> <!-- Address email will be sent from -->
+ <key>SupressionDays</key>
+ <integer>7</integer> <!-- Don't send messages for events earlier than this many days in the past -->
+ </dict>
+ <key>Receiving</key>
+ <dict>
+ <key>Server</key>
+ <string></string>
+ <key>Port</key>
+ <integer>995</integer>
+ <key>Type</key>
+ <string></string> <!-- Either "pop" or "imap" -->
+ <key>UseSSL</key>
+ <true/>
+ <key>Username</key>
+ <string></string>
+ <key>Password</key>
+ <string></string>
+ <key>PollingSeconds</key>
+ <integer>30</integer>
+ </dict>
+ <key>AddressPatterns</key>
+ <array>
+ <string>mailto:.*</string>
+ </array>
+ </dict>
+
+ <!-- General options for scheduling -->
+ <key>Options</key>
+ <dict>
+ <key>AllowGroupAsOrganizer</key>
+ <false/>
+ <key>AllowLocationAsOrganizer</key>
+ <false/>
+ <key>AllowResourceAsOrganizer</key>
+ <false/>
+ <key>AttendeeRefreshBatch</key>
+ <integer>0</integer>
+ <key>V1Compatibility</key> <!-- Allow /path-based CUAs in scheduling replies -->
+ <false/>
+
+ <key>AutoSchedule</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <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>
+ </dict>
+ </dict>
+ </dict>
+
+
+ <!--
+ Free-busy URL protocol
+ -->
+
+ <key>FreeBusyURL</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>TimePeriod</key>
+ <integer>14</integer>
+ <key>AnonymousAccess</key>
+ <false/>
+ </dict>
+
+
+ <!--
+ Non-standard CalDAV extensions
+ -->
+
+ <!-- Calendar Drop Box -->
+ <key>EnableDropBox</key>
+ <true/>
+
+ <!-- Private Events -->
+ <key>EnablePrivateEvents</key>
+ <true/>
+
+ <!-- Timezone Service -->
+ <key>EnableTimezoneService</key>
+ <true/>
+
+ <!-- Batch Upload via POST -->
+ <key>EnableBatchUpload</key>
+ <true/>
+
+ <!-- Shared Calendars & Address Books -->
+ <key>Sharing</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>AllowExternalUsers</key>
+ <false/>
+ <key>Calendars</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ </dict>
+ <key>AddressBooks</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ </dict>
+ </dict>
+
+ <!--
+ Miscellaneous items
+ -->
+
+ <!-- Service ACLs (Mac OS X) -->
+ <key>EnableSACLs</key>
+ <false/>
+
+ <!-- Make entire server read-only -->
+ <key>EnableReadOnlyServer</key>
+ <false/>
+
+ <!-- Web-based administration -->
+ <key>EnableWebAdmin</key>
+ <true/>
+
+ <!-- Support for Content-Encoding compression options as specified in RFC2616 Section 3.5 -->
+ <key>ResponseCompression</key>
+ <false/>
+
+ <!-- The retry-after value (in seconds) to return with a 503 error. -->
+ <key>HTTPRetryAfter</key>
+ <integer>180</integer>
+
+ <!-- For child-master IPC. [empty = use tcp] -->
+ <key>ControlSocket</key>
+ <string>caldavd.sock</string>
+
+ <!-- Support for Memcached -->
+ <key>Memcached</key>
+ <dict>
+ <key>MaxClients</key>
+ <integer>5</integer>
+ <key>memcached</key>
+ <string>memcached</string> <!-- Find in PATH -->
+ <key>Options</key>
+ <array>
+ <!--<string>-vv</string>--> <!-- Be very verbose -->
+ </array>
+ </dict>
+
+ <!-- Response Caching -->
+ <key>EnableResponseCache</key>
+ <true/>
+ <key>ResponseCacheTimeout</key>
+ <integer>30</integer> <!-- in minutes -->
+
+ <!-- Support for Postgres -->
+ <key>Postgres</key>
+ <dict>
+ <key>Options</key>
+ <array>
+ <!-- Optional extra logging for posgres -->
+ <!-- <string>-c log_lock_waits=TRUE</string> -->
+ <!-- <string>-c log_statement=all</string> -->
+ <!-- <string>-c log_line_prefix='%t [%p]: [%l] '</string> -->
+ </array>
+ </dict>
+
+ <!-- SQL Query Caching -->
+ <key>QueryCaching</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>MemcachedPool</key>
+ <string>Default</string>
+ <key>ExpireSeconds</key>
+ <integer>3600</integer>
+ </dict>
+
+ <!-- Group Membership Caching -->
+ <key>GroupCaching</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>EnableUpdater</key>
+ <true/>
+ <key>MemcachedPool</key>
+ <string>Default</string>
+ <key>UpdateSeconds</key>
+ <integer>300</integer>
+ <key>ExpireSeconds</key>
+ <integer>3600</integer>
+ <key>LockSeconds</key>
+ <integer>300</integer>
+ <key>UseExternalProxies</key>
+ <false/>
+ </dict>
+
+ <!-- Maximum number of results returned by principal-property-search REPORT -->
+ <key>MaxPrincipalSearchReportResults</key>
+ <integer>500</integer>
+
+ <!--
+ Twisted
+ -->
+
+ <key>Twisted</key>
+ <dict>
+ <key>twistd</key>
+ <string>../Twisted/bin/twistd</string>
+ </dict>
+
+
+ <key>Localization</key>
+ <dict>
+ <key>TranslationsDirectory</key>
+ <string>locales</string>
+ <key>LocalesDirectory</key>
+ <string>locales</string>
+ <key>Language</key>
+ <string>English</string>
+ </dict>
+
+ <!--
+ Directory Address Book
+ -->
+
+ <!-- Disable Directory Address Book -->
+ <!--
+ <key>DirectoryAddressBook</key>
+ <false/>
+ -->
+
+ <!-- Open Directory-backed Directory Address Book -->
+ <key>EnableSearchAddressBook</key>
+ <true/>
+ <key>DirectoryAddressBook</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <!-- twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService ->
+ <key>type</key>
+ <string>twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService</string>
+ <key>params</key>
+ <dict>
+ <!- - Search for people records ->
+ <key>queryPeopleRecords</key>
+ <true/>
+ <!- Search for people records in this directory service node ->
+ <key>peopleNode</key>
+ <string>/Search/Contacts</string>
+ <!- Search for user records ->
+ <key>queryUserRecords</key>
+ <true/>
+ <key>userNode</key>
+ <!- Search for user records in this directory service node ->
+ <string>/Search</string>
+ <!- query in directory service local node ->
+ <key>queryDSLocal</key>
+ <false/>
+ <!- minutes to keep directory service local node in memory before refresh ->
+ <key>dsLocalCacheTimeout</key>
+ <integer>30</integer>
+ <!- approx. maximum number of records returned from a directory service query ->
+ <key>maxDSQueryRecords</key>
+ <integer>0</integer> <!- use 0 to have server calculate the maximum based on MaxAddressBookQueryResults, MaxAddressBookMultigetHrefs keys ->
+ <!- ignore system records like "root" when creating vCards ->
+ <key>ignoreSystemRecords</key>
+ <true/>
+ <!- fake the eTag. If false all directory service attributes are used to calculate the eTag ->
+ <key>fakeETag</key>
+ <true/>
+ <key>generateSimpleUIDs</key>
+ <true/>
+ <key>appleInternalServer</key>
+ <false/>
+ <key>addDSAttrXProperties</key>
+ <false/>
+ <!- add this key to use additional directory service attributes in queries. Needed for some queries with directory service templates.
+ <key>additionalAttributes</key>
+ <array>
+ <string>dsAttrTypeNative:appleAIMPreferred</string>
+ <string>dsAttrTypeNative:appleManager</string>
+ </array>
+ ->
+ <!- add this key to limit directory service attributes used to make vCard properties
+ When using directory service templates, list should include only mapped attributes.
+ <key>allowedAttributes</key>
+ <array>
+ <string>dsAttrTypeStandard:AddressLine1</string>
+ <string>dsAttrTypeStandard:AddressLine2</string>
+ <string>dsAttrTypeStandard:AddressLine3</string>
+ <string>dsAttrTypeStandard:Birthday</string>
+ <string>dsAttrTypeStandard:Building</string>
+ <string>dsAttrTypeStandard:City</string>
+ <string>dsAttrTypeStandard:Comment</string>
+ <string>dsAttrTypeStandard:Country</string>
+ <string>dsAttrTypeStandard:CreationTimestamp</string>
+ <string>dsAttrTypeStandard:Department</string>
+ <string>dsAttrTypeStandard:EMailAddress</string>
+ <string>dsAttrTypeStandard:EMailContacts</string>
+ <string>dsAttrTypeStandard:FirstName</string>
+ <string>dsAttrTypeStandard:HomePhoneNumber</string>
+ <string>dsAttrTypeStandard:IMHandle</string>
+ <string>dsAttrTypeStandard:JPEGPhoto</string>
+ <string>dsAttrTypeStandard:JobTitle</string>
+ <string>dsAttrTypeStandard:LastName</string>
+ <string>dsAttrTypeStandard:MapCoordinates</string>
+ <string>dsAttrTypeStandard:MiddleName</string>
+ <string>dsAttrTypeStandard:MobileNumber</string>
+ <string>dsAttrTypeStandard:ModificationTimestamp</string>
+ <string>dsAttrTypeStandard:NamePrefix</string>
+ <string>dsAttrTypeStandard:NameSuffix</string>
+ <string>dsAttrTypeStandard:NickName</string>
+ <string>dsAttrTypeStandard:Note</string>
+ <string>dsAttrTypeStandard:OrganizationInfo</string>
+ <string>dsAttrTypeStandard:OrganizationName</string>
+ <string>dsAttrTypeStandard:PGPPublicKey</string>
+ <string>dsAttrTypeStandard:PagerNumber</string>
+ <string>dsAttrTypeStandard:PhoneContacts</string>
+ <string>dsAttrTypeStandard:PhoneNumber</string>
+ <string>dsAttrTypeStandard:PostalAddress</string>
+ <string>dsAttrTypeStandard:PostalAddressContacts</string>
+ <string>dsAttrTypeStandard:PostalCode</string>
+ <string>dsAttrTypeStandard:Relationships</string>
+ <string>dsAttrTypeStandard:State</string>
+ <string>dsAttrTypeStandard:Street</string>
+ <string>dsAttrTypeStandard:URL</string>
+ <string>dsAttrTypeStandard:UserCertificate</string>
+ <string>dsAttrTypeStandard:UserPKCS12Data</string>
+ <string>dsAttrTypeStandard:UserSMIMECertificate</string>
+ <string>dsAttrTypeStandard:WeblogURI</string>
+ </array>
+ ->
+ </dict>
+ -->
+ <!-- twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService -->
+ <key>type</key>
+ <string>twistedcaldav.directory.ldapdirectorybacker.LdapDirectoryBackingService</string>
+ <key>params</key>
+ <dict>
+ <key>warningThresholdSeconds</key>
+ <integer>1</integer>
+ <key>appleInternalServer</key>
+ <true/>
+ <!-- fake uri, fill in. -->
+ <key>uri</key>
+ <string>ldap://example.com/</string>
+ <!-- fill in auth info, if needed. -->
+ <key>tls</key>
+ <false/>
+ <key>tlsCACertFile</key>
+ <string></string>
+ <key>tlsCACertDir</key>
+ <string></string>
+ <key>tlsRequireCert</key>
+ <string>never</string>
+ <key>credentials</key>
+ <dict/>
+ <key>authMethod</key>
+ <string>LDAP</string>
+ <key>rdnSchema</key>
+ <dict>
+ <key>base</key>
+ <string>o=apple.com,o=email</string>
+ <key>queries</key>
+ <array>
+ <!-- people vCards for another server. -->
+ <dict>
+ <key>rdn</key>
+ <string>ou=People</string>
+ <key>filter</key>
+ <string></string>
+ <!-- map from ab query to indexed ldap attribute. If unindexed, too slow. -->
+ <key>ldapAttrToDSAttrMap</key>
+ <dict>
+ <key>givenName</key>
+ <string>FirstName</string>
+ <key>sn</key>
+ <string>LastName</string>
+ <key>cn</key>
+ <array>
+ <string>RealName</string>
+ <string>RecordName</string>
+ </array>
+ <key>mail</key>
+ <string>EMailAddress</string>
+ <key>uid</key>
+ <string>GeneratedUID</string>
+ </dict>
+ <key>vcardPropToLdapAttrMap</key>
+ <dict>
+ <key>FN</key>
+ <string>cn</string>
+ <key>EMAIL</key>
+ <string>mail</string>
+ <key>UID</key>
+ <string>uid</string>
+ </dict>
+ </dict>
+ <!-- group vCards for another server.
+ <dict>
+ <key>rdn</key>
+ <string>ou=Groups</string>
+ <key>filter</key>
+ <string></string>
+ <key>additionalVCardProps</key>
+ <dict>
+ <key>X-ADDRESSBOOKSERVER-KIND</key>
+ <string>group</string>
+ </dict>
+ <key>ldapAttrTransforms</key>
+ <dict>
+ <key>uniqueMember</key>
+ <array>
+ <string>uid</string>
+ <string>cn</string>
+ </array>
+ </dict>
+ <key>ldapAttrToDSAttrMap</key>
+ <dict>
+ <key>givenName</key>
+ <string>FirstName</string>
+ <key>sn</key>
+ <string>LastName</string>
+ <key>description</key>
+ <array>
+ <string>RealName</string>
+ </array>
+ <key>cn</key>
+ <array>
+ <string>GeneratedUID</string>
+ </array>
+ <key>mail</key>
+ <string>EMailAddress</string>
+ <key>uniqueMember</key>
+ <string>GroupMembers</string>
+ </dict>
+ <key>vcardPropToLdapAttrMap</key>
+ <dict>
+ <key>FN</key>
+ <string>cn</string>
+ <key>EMAIL</key>
+ <string>mail</string>
+ <key>UID</key>
+ <string>cn</string>
+ </dict>
+ </dict>
+ -->
+ <!-- distribution list vCards for another server. Cannot use with groups because UID/href is not unique -->
+ <dict>
+ <key>rdn</key>
+ <string>ou=Groups</string>
+ <key>filter</key>
+ <string></string>
+ <key>additionalVCardProps</key>
+ <dict>
+ <key>X-ABShowAs</key>
+ <string>COMPANY</string>
+ </dict>
+ <key>ldapAttrToDSAttrMap</key>
+ <dict>
+ <key>givenName</key>
+ <string>FirstName</string>
+ <key>sn</key>
+ <string>LastName</string>
+ <key>description</key>
+ <array>
+ <string>RealName</string>
+ </array>
+ <key>cn</key>
+ <array>
+ <string>GeneratedUID</string>
+ </array>
+ <key>mail</key>
+ <string>EMailAddress</string>
+ <key>uniqueMember</key>
+ <string>Comment</string>
+ </dict>
+ <key>vcardPropToLdapAttrMap</key>
+ <dict>
+ <key>FN</key>
+ <array>
+ <string>cn</string>
+ </array>
+ <key>EMAIL</key>
+ <string>mail</string>
+ <key>UID</key>
+ <string>cn</string>
+ </dict>
+ </dict>
+ </array>
+ </dict>
+ </dict>
+ </dict>
+ </dict>
+</plist>
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectorybacker.py 2012-04-16 22:38:03 UTC (rev 9132)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectorybacker.py 2012-04-16 23:10:10 UTC (rev 9133)
@@ -57,6 +57,7 @@
"ldapAttrToDSAttrMap" : { # maps ldap attributes to ds attribute types
"cn" : "dsAttrTypeStandard:RealName",
},
+ "additionalVCardProps":None,
},
),
@@ -114,7 +115,7 @@
assert directoryBackedAddressBook is not None
self.directoryBackedAddressBook = directoryBackedAddressBook
-
+
self.maxQueryResults = maxQueryResults
### params for ABDirectoryQueryResult()
@@ -159,7 +160,7 @@
@inlineCallbacks
- def _getLdapQueryResults(self, base, queryStr, attributes=None, maxResults=0, ldapAttrToDSAttrMap={} ):
+ def _getLdapQueryResults(self, base, queryStr, attributes=None, maxResults=0, ldapAttrToDSAttrMap=None, ldapAttrTransforms=None, additionalVCardProps=None ):
"""
Get a list of ABDirectoryQueryResult for the given query with the given attributes.
query == None gets all records. attribute == None gets ABDirectoryQueryResult.allDSQueryAttributes
@@ -193,9 +194,41 @@
ldapAttributeValues = [attr for attr in ldapAttributeValues if len(attr)]
if len(ldapAttributeValues):
+
+
dsAttributeNames = ldapAttrToDSAttrMap.get(ldapAttributeName)
if dsAttributeNames:
+ if ldapAttrTransforms:
+
+ # do value transforms
+ # need to expand this to cover all cases
+ # All this does now is to pull part of an ldap string out
+ # e.g: uid=renuka,ou=People,o=apple.com,o=email -> renuka
+ transforms = ldapAttrTransforms.get(ldapAttributeName)
+ if transforms:
+ if not isinstance(transforms, list):
+ transforms = [transforms,]
+
+ transformedValues = []
+ for ldapAttributeValue in ldapAttributeValues:
+ transformedValue = ldapAttributeValue
+ for valuePart in ldapAttributeValue.lower().split(","):
+ kvPair = valuePart.split("=")
+ if len(kvPair) == 2:
+ for transform in transforms:
+ if transform.lower() == kvPair[0]:
+ transformedValue = kvPair[1]
+ break
+
+ transformedValues += [transformedValue,]
+
+ if (ldapAttributeValues != transformedValues):
+ self.log_debug("_getLdapQueryResults: %s %s transformed to %s" % (ldapAttributeName, ldapAttributeValues, transformedValues))
+ ldapAttributeValues = transformedValues
+
+
+
if not isinstance(dsAttributeNames, list):
dsAttributeNames = [dsAttributeNames,]
@@ -213,7 +246,7 @@
self.log_debug("doAddressBookQuery: dsRecordAttributes[%s] = %s" % (dsAttributeName, dsRecordAttributes[dsAttributeName],))
# get a record for dsRecordAttributes
- result = ABDirectoryQueryResult(self.directoryBackedAddressBook, dsRecordAttributes, appleInternalServer=self.appleInternalServer)
+ result = ABDirectoryQueryResult(self.directoryBackedAddressBook, dsRecordAttributes, additionalVCardProps=additionalVCardProps, appleInternalServer=self.appleInternalServer)
except:
traceback.print_exc()
self.log_info("Could not get vcard for %s" % (dn,))
@@ -245,6 +278,8 @@
rdn = queryMap["rdn"]
vcardPropToLdapAttrMap = queryMap["vcardPropToLdapAttrMap"]
ldapAttrToDSAttrMap = queryMap["ldapAttrToDSAttrMap"]
+ additionalVCardProps = queryMap.get("additionalVCardProps")
+ ldapAttrTransforms = queryMap.get("ldapAttrTransforms")
allRecords, filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToLdapAttrMap );
self.log_debug("doAddressBookQuery: rdn=%s LDAP allRecords=%s, filterAttributes=%s, query=%s" % (rdn, allRecords, filterAttributes, "None" if dsFilter is None else dsFilter.generate(),))
@@ -283,7 +318,13 @@
maxLdapResults = int(remainingMaxResults * 1.2)
while True:
- ldapQueryResultsDictionary, ldapQueryLimited = (yield self._getLdapQueryResults(base=base, queryStr=queryStr, attributes=attributes, maxResults=maxLdapResults, ldapAttrToDSAttrMap=ldapAttrToDSAttrMap))
+ ldapQueryResultsDictionary, ldapQueryLimited = (yield self._getLdapQueryResults(base=base,
+ queryStr=queryStr,
+ attributes=attributes,
+ maxResults=maxLdapResults,
+ ldapAttrToDSAttrMap=ldapAttrToDSAttrMap,
+ ldapAttrTransforms=ldapAttrTransforms,
+ additionalVCardProps=additionalVCardProps))
for uid, ldapQueryResult in ldapQueryResultsDictionary.iteritems():
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py 2012-04-16 22:38:03 UTC (rev 9132)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py 2012-04-16 23:10:10 UTC (rev 9133)
@@ -1044,9 +1044,17 @@
}
- def __init__(self, directoryBackedAddressBook, recordAttributes, addDSAttrXProperties=False, appleInternalServer=False, ):
+ def __init__(self, directoryBackedAddressBook, recordAttributes, additionalVCardProps=None, addDSAttrXProperties=False, appleInternalServer=False, ):
- self.log_debug("directoryBackedAddressBook=%s, attributes=%s" % (directoryBackedAddressBook, recordAttributes))
+ self.log_debug("directoryBackedAddressBook=%s, attributes=%s, additionalVCardProps=%s" % (directoryBackedAddressBook, recordAttributes, additionalVCardProps,))
+
+ constantProperties = ABDirectoryQueryResult.constantProperties.copy()
+ if additionalVCardProps:
+ for key, value in additionalVCardProps.iteritems():
+ if key not in constantProperties:
+ constantProperties[key] = value
+ self.constantProperties = constantProperties
+ self.log_debug("directoryBackedAddressBook=%s, attributes=%s, self.constantProperties=%s" % (directoryBackedAddressBook, recordAttributes, self.constantProperties,))
#save off for debugging
self.addDSAttrXProperties = addDSAttrXProperties;
@@ -1232,7 +1240,7 @@
groupCount = [0]
# add constant properties - properties that are the same regardless of the record attributes
- for key, value in ABDirectoryQueryResult.constantProperties.items():
+ for key, value in self.constantProperties.items():
vcard.addProperty(Property(key, value))
# 3.1 IDENTIFICATION TYPES http://tools.ietf.org/html/rfc2426#section-3.1
@@ -1480,12 +1488,10 @@
# 3.6.2 NOTE Type Definition
# dsattributes.kDS1AttrComment, # Attribute used for unformatted comment.
# dsattributes.kDS1AttrNote, # Note attribute. Commonly used in printer records.
- for comment in self.valuesForAttribute(dsattributes.kDS1AttrComment):
- addUniqueProperty(vcard, Property("NOTE", comment), None, dsattributes.kDS1AttrComment, comment)
+ notes = self.valuesForAttribute(dsattributes.kDS1AttrComment, []) + self.valuesForAttribute(dsattributes.kDS1AttrNote, []);
+ if len(notes):
+ vcard.addProperty(Property("NOTE", "\n".join(notes),))
- for note in self.valuesForAttribute(dsattributes.kDS1AttrNote):
- addUniqueProperty(vcard, Property("NOTE", note), None, dsattributes.kDS1AttrNote, note)
-
# 3.6.3 PRODID Type Definition
#vcard.addProperty(Property("PRODID", vCardProductID + "//BUILD %s" % twistedcaldav.__version__))
#vcard.addProperty(Property("PRODID", vCardProductID))
@@ -1615,9 +1621,10 @@
# add apple-defined group vcard properties if record type is group
if self.firstValueForAttribute(dsattributes.kDSNAttrRecordType) == dsattributes.kDSStdRecordTypeGroups:
vcard.addProperty(Property("X-ADDRESSBOOKSERVER-KIND", "group"))
-
- for memberguid in self.valuesForAttribute(dsattributes.kDSNAttrGroupMembers):
- vcard.addProperty(Property("X-ADDRESSBOOKSERVER-MEMBER", "urn:uuid:" + memberguid))
+
+ # add members
+ for memberguid in self.valuesForAttribute(dsattributes.kDSNAttrGroupMembers):
+ vcard.addProperty(Property("X-ADDRESSBOOKSERVER-MEMBER", "urn:uuid:" + memberguid))
"""
# UNIMPLEMENTED: X- attributes
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120416/7886c70f/attachment-0001.html>
More information about the calendarserver-changes
mailing list