[CalendarServer-changes] [9153] CalendarServer/branches/users/gaya/ldapdirectorybacker
source_changes at macosforge.org
source_changes at macosforge.org
Thu Apr 19 13:20:48 PDT 2012
Revision: 9153
http://trac.macosforge.org/projects/calendarserver/changeset/9153
Author: gaya at apple.com
Date: 2012-04-19 13:20:48 -0700 (Thu, 19 Apr 2012)
Log Message:
-----------
support ab queries on KIND
Modified Paths:
--------------
CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest.plist
CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest2.plist
CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-odtest.plist
CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectorybacker.py
CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/xmldirectorybacker.py
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest.plist
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest.plist 2012-04-19 17:41:39 UTC (rev 9152)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest.plist 2012-04-19 20:20:48 UTC (rev 9153)
@@ -1018,102 +1018,6 @@
<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>
@@ -1154,12 +1058,9 @@
<!-- map from ab query to indexed ldap attribute. If unindexed, too slow. -->
<key>vcardPropToLdapAttrMap</key>
<dict>
- <key>FN</key>
- <string>cn</string>
- <key>EMAIL</key>
- <string>mail</string>
- <key>TEL</key>
- <string>telephoneNumber</string>
+ <key>FN</key> <string>cn</string>
+ <key>EMAIL</key> <string>mail</string>
+ <key>TEL</key> <string>telephoneNumber</string>
<key>ADR</key>
<array>
<string>buildingName</string>
@@ -1168,105 +1069,69 @@
<string>l</string>
<string>st</string>
</array>
- <key>ORG</key>
- <string>ou</string>
- <key>UID</key>
- <string>appleDSID</string>
+ <key>ORG</key> <string>ou</string>
+ <key>UID</key> <string>appleDSID</string>
</dict>
<!-- map ldap attributes to ds attribute types. -->
<key>ldapAttrToDSAttrMap</key>
<dict>
- <key>givenName</key>
- <string>FirstName</string>
- <key>sn</key>
- <string>LastName</string>
- <key>cn</key>
- <string>RealName</string>
+ <key>givenName</key> <string>FirstName</string>
+ <key>sn</key> <string>LastName</string>
+ <key>cn</key> <string>RealName</string>
<!-- PHOTO -->
- <key>applePhotoPreferred-jpeg</key>
- <string>JPEGPhoto</string>
+ <key>applePhotoPreferred-jpeg</key> <string>JPEGPhoto</string>
<!-- ADR -->
- <key>buildingName</key>
- <string>Building</string>
- <key>destinationIndicator</key>
- <string>Building</string>
- <key>street</key>
- <string>Street</string>
- <key>l</key>
- <string>City</string>
- <key>st</key>
- <string>State</string>
- <key>postalCode</key>
- <string>PostalCode</string>
- <key>co</key>
- <string>Country</string>
+ <key>buildingName</key> <string>Building</string>
+ <key>destinationIndicator</key> <string>Building</string>
+ <key>street</key> <string>Street</string>
+ <key>l</key> <string>City</string>
+ <key>st</key> <string>State</string>
+ <key>postalCode</key> <string>PostalCode</string>
+ <key>co</key> <string>Country</string>
<!-- TEL -->
- <key>telephoneNumber</key>
- <string>PhoneNumber</string>
- <key>appleSecondaryPhone</key>
- <string>PhoneNumber</string>
- <key>facsimileTelephoneNumber</key>
- <string>FaxNumber</string>
- <key>pager</key>
- <string>PagerNumber</string>
- <key>mobile</key>
- <string>MobileNumber</string>
+ <key>telephoneNumber</key> <string>PhoneNumber</string>
+ <key>appleSecondaryPhone</key> <string>PhoneNumber</string>
+ <key>facsimileTelephoneNumber</key> <string>FaxNumber</string>
+ <key>pager</key> <string>PagerNumber</string>
+ <key>mobile</key> <string>MobileNumber</string>
<!-- EMAIL -->
- <key>mail</key>
- <string>EMailAddress</string>
- <key>applePreferredEmail</key>
- <string>EMailAddress</string>
- <key>appleNotificationEmail</key>
- <string>EMailAddress</string>
+ <key>mail</key> <string>EMailAddress</string>
+ <key>applePreferredEmail</key> <string>EMailAddress</string>
+ <key>appleNotificationEmail</key> <string>EMailAddress</string>
<!-- UID -->
- <key>appleDSID</key>
- <string>GeneratedUID</string>
+ <key>appleDSID</key> <string>GeneratedUID</string>
<!-- ORG -->
- <key>o</key>
- <string>OrganizationName</string>
- <key>ou</key>
- <string>Department</string>
+ <key>o</key> <string>OrganizationName</string>
+ <key>ou</key> <string>Department</string>
<!-- IMPP -->
- <key>appleAIMPreferred</key>
- <string>IMHandle</string>
- <key>appleAIMOfficial</key>
- <string>IMHandle</string>
- <key>appleManager</key>
- <string>dsAttrTypeNative:appleManager</string>
+ <key>appleAIMPreferred</key> <string>IMHandle</string>
+ <key>appleAIMOfficial</key> <string>IMHandle</string>
+ <key>appleManager</key> <string>dsAttrTypeNative:appleManager</string>
</dict>
</dict>
<!-- mailing list vCards. Should mark as company-->
<dict>
- <key>rdn</key>
- <string>ou=groups</string>
- <key>filter</key>
- <string>(objectClass=appleGroup)</string>
- <key>getAllAttributes</key>
- <false/>
+ <key>rdn</key> <string>ou=groups</string>
+ <key>kind</key> <string>org</string>
+ <key>filter</key> <string>(objectClass=appleGroup)</string>
+ <key>getAllAttributes</key> <false/>
<key>vcardPropToLdapAttrMap</key>
<dict>
- <key>EMAIL</key>
- <string>appleGroupEmail</string>
- <key>FN</key>
- <string>description</string>
- <key>UID</key>
- <string>appleDSID</string>
+ <key>EMAIL</key> <string>appleGroupEmail</string>
+ <key>FN</key> <string>description</string>
+ <key>UID</key> <string>appleDSID</string>
</dict>
<key>ldapAttrToDSAttrMap</key>
<dict>
- <key>cn</key>
- <string>RecordName</string>
+ <key>cn</key> <string>RecordName</string>
<key>description</key>
<array>
<string>RealName</string>
<string>OrganizationName</string>
</array>
- <key>appleDSID</key>
- <string>GeneratedUID</string>
- <key>appleGroupContact</key>
- <string>dsAttrTypeNative:appleManager</string>
- <key>appleGroupEmail</key>
- <string>EMailAddress</string>
+ <key>appleDSID</key> <string>GeneratedUID</string>
+ <key>appleGroupContact</key> <string>dsAttrTypeNative:appleManager</string>
+ <key>appleGroupEmail</key> <string>EMailAddress</string>
</dict>
</dict>
</array>
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest2.plist
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest2.plist 2012-04-19 17:41:39 UTC (rev 9152)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-ldaptest2.plist 2012-04-19 20:20:48 UTC (rev 9153)
@@ -1050,13 +1050,13 @@
<array>
<!-- people vCards -->
<dict>
- <key>rdn</key> <string>ou=People</string>
+ <key>rdn</key> <string>ou=People</string>
+ <key>kind</key> <string>individual</string>
<key>filter</key> <string></string>
<!-- map from ab query to indexed ldap attribute. If unindexed, too slow. -->
<key>additionalVCardProps</key>
<dict>
- <key>KIND</key> <string>individual</string>
- <key>NOTE</key> <string>individual</string>
+ <key>NOTE</key> <string>KIND: individual</string>
</dict>
<key>ldapAttrToDSAttrMap</key>
<dict>
@@ -1073,14 +1073,11 @@
<key>UID</key> <string>uid</string>
</dict>
</dict>
- <!-- distribution list (group) vCards shown by 10.6-7 clients as persons. Members are in NOTE. Does not hide groups below because UID different -->
+ <!-- distribution list (group) vCards shown by 10.6-7 clients as a company. Does not hide groups below because UIDs are different -->
<dict>
<key>rdn</key> <string>ou=Groups</string>
+ <key>kind</key> <string>org</string>
<key>filter</key> <string>(|(mail=*)(uniqueMember=*))</string> <!-- add a filter to skip uninteresting groups -->
- <key>additionalVCardProps</key>
- <dict>
- <key>KIND</key> <string>group</string>
- </dict>
<key>ldapAttrToDSAttrMap</key>
<dict>
<key>givenName</key> <string>FirstName</string>
@@ -1088,7 +1085,7 @@
<key>description</key> <string>RealName</string>
<key>cn</key> <string>RecordName</string>
<key>mail</key> <string>EMailAddress</string>
- <key>uniqueMember</key> <string>Comment</string>
+ <key>uniqueMember</key> <string>Comment</string> <!-- debug only -->
</dict>
<key>vcardPropToLdapAttrMap</key>
<dict>
@@ -1100,12 +1097,8 @@
<!-- group vCards NOT shown 10.6-7 clients. Hopefully, future client will show these. Client can expand members with exact query on group member UID -->
<dict>
<key>rdn</key> <string>ou=Groups</string>
+ <key>kind</key> <string>group</string>
<key>filter</key> <string>(|(mail=*)(uniqueMember=*))</string> <!-- add a filter to skip uninteresting groups -->
- <key>additionalVCardProps</key>
- <dict>
- <key>X-ADDRESSBOOKSERVER-KIND</key> <string>group</string>
- <key>KIND</key> <string>group</string>
- </dict>
<key>ldapAttrTransforms</key>
<dict>
<key>uniqueMember</key>
@@ -1133,12 +1126,12 @@
<!-- group vCards shown by 10.6-7 clients as persons. Future client should show as location. Need to add Map URL or GEO -->
<dict>
<key>rdn</key> <string>ou=places</string>
+ <key>kind</key> <string>location</string>
<key>filter</key> <string>(objectClass=apple-resource)</string>
<!-- map from ab query to indexed ldap attribute. If unindexed, too slow. -->
<key>additionalVCardProps</key>
<dict>
- <key>KIND</key> <string>location</string>
- <key>NOTE</key> <string>location</string>
+ <key>NOTE</key> <string>KIND:location</string>
</dict>
<key>ldapAttrToDSAttrMap</key>
<dict>
@@ -1156,11 +1149,11 @@
<!-- calendarresource vCards shown by 10.6-7 clients as persons. Just for testing only, at this point in time -->
<dict>
<key>rdn</key> <string>ou=resources</string>
+ <key>kind</key> <string>calendarresource</string>
<key>filter</key> <string>(objectClass=apple-resource)</string>
<key>additionalVCardProps</key>
<dict>
- <key>KIND</key> <string>calendarresource</string>
- <key>NOTE</key> <string>location</string>
+ <key>NOTE</key> <string>KIND: calendarresource</string>
</dict>
<key>ldapAttrToDSAttrMap</key>
<dict>
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-odtest.plist
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-odtest.plist 2012-04-19 17:41:39 UTC (rev 9152)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-odtest.plist 2012-04-19 20:20:48 UTC (rev 9153)
@@ -1139,188 +1139,6 @@
</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</string>
- <key>queryTypes</key>
- <array>
- <string>people</string>
- <string>distribution list</string>
- </array>
- <!- user vCards ->
- <key>people</key>
- <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>vcardPropToLdapAttrMap</key>
- <dict>
- <key>FN</key>
- <string>cn</string>
- <key>EMAIL</key>
- <string>mail</string>
- <key>TEL</key>
- <string>telephoneNumber</string>
- <key>UID</key>
- <string>appleDSID</string>
- </dict>
- <!- map ldap attributes to ds attribute types. ->
- <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>applePhotoPreferred-jpeg</key>
- <string>JPEGPhoto</string>
- <key>buildingName</key>
- <string>Building</string>
- <key>destinationIndicator</key>
- <string>Building</string>
- <key>street</key>
- <string>Street</string>
- <key>l</key>
- <string>City</string>
- <key>st</key>
- <string>State</string>
- <key>postalCode</key>
- <string>PostalCode</string>
- <key>co</key>
- <string>Country</string>
- <key>telephoneNumber</key>
- <string>PhoneNumber</string>
- <key>appleSecondaryPhone</key>
- <string>PhoneNumber</string>
- <key>facsimileTelephoneNumber</key>
- <string>FaxNumber</string>
- <key>pager</key>
- <string>PagerNumber</string>
- <key>mobile</key>
- <string>MobileNumber</string>
- <key>mail</key>
- <string>EMailAddress</string>
- <key>applePreferredEmail</key>
- <string>EMailAddress</string>
- <key>appleNotificationEmail</key>
- <string>EMailAddress</string>
- <key>appleDSID</key>
- <string>GeneratedUID</string>
- <key>o</key>
- <string>OrganizationName</string>
- <key>ou</key>
- <string>Department</string>
- <key>appleAIMPreferred</key>
- <string>IMHandle</string>
- <key>appleAIMOfficial</key>
- <string>IMHandle</string>
- <key>appleManager</key>
- <string>dsAttrTypeNative:appleManager</string>
- </dict>
- </dict>
- <!- mailing list vCards. Should mark as "company" or use vCard 4.0 types ->
- <key>distribution list</key>
- <dict>
- <key>rdn</key>
- <string>ou=groups</string>
- <key>filter</key>
- <string>(objectClass=appleGroup)</string>
- <key>getAllAttributes</key>
- <false/>
- <key>vcardPropToLdapAttrMap</key>
- <dict>
- <key>EMAIL</key>
- <string>appleGroupEmail</string>
- <key>FN</key>
- <string>description</string>
- <key>UID</key>
- <string>appleDSID</string>
- </dict>
- <key>ldapAttrToDSAttrMap</key>
- <dict>
- <key>cn</key>
- <string>RecordName</string>
- <key>description</key>
- <array>
- <string>RealName</string>
- <string>OrganizationName</string>
- </array>
- <key>appleDSID</key>
- <string>GeneratedUID</string>
- <key>appleGroupContact</key>
- <string>dsAttrTypeNative:appleManager</string>
- <key>appleGroupEmail</key>
- <string>EMailAddress</string>
- </dict>
- </dict>
- <!- people vCards for another server. Unused
- <key>people - 2</key>
- <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>
- </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-19 17:41:39 UTC (rev 9152)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectorybacker.py 2012-04-19 20:20:48 UTC (rev 9153)
@@ -164,7 +164,7 @@
@inlineCallbacks
- def _getLdapQueryResults(self, base, queryStr, attributes=None, maxResults=0, ldapAttrToDSAttrMap=None, ldapAttrTransforms=None, additionalVCardProps=None ):
+ def _getLdapQueryResults(self, base, queryStr, attributes=None, maxResults=0, ldapAttrToDSAttrMap=None, ldapAttrTransforms=None, additionalVCardProps=None, kind=None ):
"""
Get a list of ABDirectoryQueryResult for the given query with the given attributes.
query == None gets all records. attribute == None gets ABDirectoryQueryResult.allDSQueryAttributes
@@ -253,7 +253,7 @@
self.log_debug("doAddressBookQuery: dsRecordAttributes[%s] = %s" % (dsAttributeName, dsRecordAttributes[dsAttributeName],))
# get a record for dsRecordAttributes
- result = ABDirectoryQueryResult(self.directoryBackedAddressBook, dsRecordAttributes, additionalVCardProps=additionalVCardProps, appleInternalServer=self.appleInternalServer)
+ result = ABDirectoryQueryResult(self.directoryBackedAddressBook, dsRecordAttributes, kind=kind, additionalVCardProps=additionalVCardProps, appleInternalServer=self.appleInternalServer)
except:
traceback.print_exc()
self.log_info("Could not get vcard for %s" % (dn,))
@@ -287,8 +287,18 @@
ldapAttrToDSAttrMap = queryMap["ldapAttrToDSAttrMap"]
additionalVCardProps = queryMap.get("additionalVCardProps")
ldapAttrTransforms = queryMap.get("ldapAttrTransforms")
+ kind = queryMap.get("kind", "individual")
+
+ # add constants and KIND
+ constantProperties = ABDirectoryQueryResult.constantProperties.copy()
+ if additionalVCardProps:
+ for key, value in additionalVCardProps.iteritems():
+ if key not in constantProperties:
+ constantProperties[key] = value
+ constantProperties["KIND"] = kind
+
- allRecords, filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToLdapAttrMap );
+ allRecords, filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToLdapAttrMap, constantProperties=constantProperties );
self.log_debug("doAddressBookQuery: rdn=%s LDAP allRecords=%s, filterAttributes=%s, query=%s" % (rdn, allRecords, filterAttributes, "None" if dsFilter is None else dsFilter.generate(),))
@@ -329,6 +339,7 @@
queryStr=queryStr,
attributes=attributes,
maxResults=maxLdapResults,
+ kind=kind,
ldapAttrToDSAttrMap=ldapAttrToDSAttrMap,
ldapAttrTransforms=ldapAttrTransforms,
additionalVCardProps=additionalVCardProps))
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py 2012-04-19 17:41:39 UTC (rev 9152)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py 2012-04-19 20:20:48 UTC (rev 9153)
@@ -184,14 +184,24 @@
self.log_debug("self.searchAttributes=%s" % (searchAttributes, ))
# calculate search map
- vCardPropToSearchableDSAttrMap = {}
+ vcardPropToSearchableDSAttrMap = {}
for prop, dsAttributeList in ABDirectoryQueryResult.vcardPropToDSAttrMap.iteritems():
dsIndexedAttributeList = [attr for attr in dsAttributeList if attr in searchAttributes]
if len(dsIndexedAttributeList):
- vCardPropToSearchableDSAttrMap[prop] = dsIndexedAttributeList
+ vcardPropToSearchableDSAttrMap[prop] = dsIndexedAttributeList
- self.vCardPropToSearchableDSAttrMap = vCardPropToSearchableDSAttrMap
- self.log_debug("self.vCardPropToSearchableDSAttrMap=%s" % (self.vCardPropToSearchableDSAttrMap, ))
+ self.vcardPropToSearchableDSAttrMap = vcardPropToSearchableDSAttrMap
+ self.log_debug("self.vcardPropToSearchableDSAttrMap=%s" % (self.vcardPropToSearchableDSAttrMap, ))
+
+ # calculate unsearch map - a map of the binary attributes.
+ vCardPropToUnsearchableDSAttrMap = {}
+ for prop, dsAttributeList in ABDirectoryQueryResult.vcardPropToDSAttrMap.iteritems():
+ for attr in dsAttributeList:
+ if isinstance(attr, tuple):
+ vCardPropToUnsearchableDSAttrMap[prop] = dsAttributeList
+
+ self.vCardPropToUnsearchableDSAttrMap = vCardPropToUnsearchableDSAttrMap
+ self.log_debug("self.vCardPropToUnsearchableDSAttrMap=%s" % (self.vCardPropToUnsearchableDSAttrMap, ))
#get attributes required for needed for valid vCard
@@ -479,7 +489,7 @@
else:
queryAttributes = self.requiredAttributes
for prop in propertyNames:
- attributes = self.vCardPropToSearchableDSAttrMap.get(prop)
+ attributes = self.vcardPropToSearchableDSAttrMap.get(prop)
if attributes:
queryAttributes += attributes
@@ -493,7 +503,8 @@
Get vCards for a given addressBookFilter and addressBookQuery
"""
- allRecords, filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToDSAttrMap=self.vCardPropToSearchableDSAttrMap );
+ allRecords, filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, self.vcardPropToSearchableDSAttrMap,
+ constantProperties=ABDirectoryQueryResult.constantProperties );
self.log_debug("allRecords = %s, query = %s" % (allRecords, "None" if dsFilter is None else dsFilter.generate(),))
# testing:
@@ -595,13 +606,18 @@
return (etagRequested, propertyNames if len(propertyNames) else None)
-def dsFilterFromAddressBookFilter(addressBookFilter, vcardPropToDSAttrMap):
+def dsFilterFromAddressBookFilter(addressBookFilter, vcardPropToSearchableAttrMap, vcardPropToUnsearchableAttrMap={}, constantProperties={}):
"""
Convert the supplied addressbook-query into a ds expression tree.
@param filter: the L{Filter} for the addressbook-query to convert.
- @return: (needsAllRecords, espressionAttributes, expression) tuple
+ @return: (needsAllRecords, expressionAttributes, expression) tuple
"""
+ #TODO: 1. get rid of needsAllRecords: instead should be: expression==None means list all results, expression==False means no results
+ # 2. expressionAttributes returned is incorrect in many cases for "return (xxx, [], [])" below
+ # 3. vcardPropToUnsearchableAttrMap is unused by callers. In the past, vcardPropToUnsearchableAttrMap was that part of vCardProp map
+ # containing binary attributes.
+ #
def propFilterListQuery(filterAllOf, propFilters):
def propFilterExpression(filterAllOf, propFilter):
@@ -610,16 +626,15 @@
Create an expression for a single prop-filter element.
@param propFilter: the L{PropertyFilter} element.
- @return: (needsAllRecords, espressionAttributes, expressions) tuple
+ @return: (needsAllRecords, expressionAttributes, expressions) tuple
"""
- def definedExpression( defined, allOf, filterName, constant, queryAttributes, allAttrStrings):
+ def definedExpression( defined, allOf, filterName, constant, queryAttributes, allAttrNames):
if constant or filterName in ("N" , "FN", "UID", "SOURCE",):
return (defined, [], []) # all records have this property so no records do not have it
else:
- matchList = list(set([dsquery.match(attrName, "", dsattributes.eDSStartsWith) for attrName in allAttrStrings]))
+ matchList = [dsquery.match(attrName, "", dsattributes.eDSStartsWith) for attrName in allAttrNames]
if defined:
- # TODO: Investigate what happens when andOrExpresion() does not return an expression
return andOrExpression(allOf, queryAttributes, matchList)
else:
if len(matchList) > 1:
@@ -627,7 +642,7 @@
else:
expr = matchList[0]
return (False, queryAttributes, [dsquery.expression( dsquery.expression.NOT, expr),])
- #end isNotDefinedExpression()
+ #end definedExpression()
def andOrExpression(propFilterAllOf, queryAttributes, matchList):
@@ -739,10 +754,10 @@
matchStrings = getMatchStrings(propFilter, textMatchElement.text)
- if not len(matchStrings) or binaryAttrNames:
+ if not len(matchStrings) or unsearchableAttributes:
# no searching text in binary ds attributes, so change to defined/not defined case
if textMatchElement.negate:
- return definedExpression(False, propFilterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrStrings)
+ return definedExpression(False, propFilterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrNames)
# else fall through to attribute exists case below
else:
@@ -769,8 +784,7 @@
)
# use match_type where possible depending on property/attribute mapping
- # Note that case sensitive negate will not work
- # Should return all records in that case
+ # FIXME: case-sensitive negate will not work. This should return all all records in that case
matchType = dsattributes.eDSContains
if propFilter.filter_name in ("NICKNAME" , "TITLE" , "NOTE" , "UID", "URL", "N", "ADR", "ORG", "REV", "LABEL", ):
if textMatchElement.match_type == "equals":
@@ -782,7 +796,7 @@
matchList = []
for matchString in matchStrings:
- matchList += [dsquery.match(attrName, matchString, matchType) for attrName in stringAttrNames]
+ matchList += [dsquery.match(attrName, matchString, matchType) for attrName in searchableAttributes]
matchList = list(set(matchList))
@@ -796,31 +810,37 @@
return andOrExpression(propFilterAllOf, queryAttributes, matchList)
# attribute exists search
- return definedExpression(True, propFilterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrStrings)
+ return definedExpression(True, propFilterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrNames)
#end textMatchElementExpression()
- # get attribute strings
- queryAttributes = vcardPropToDSAttrMap.get(propFilter.filter_name, [])
- if isinstance(queryAttributes, str):
- queryAttributes = [queryAttributes,]
+ # queryAttributes are attributes used by this query needed for building vCard and correct post-filtering
+ searchableAttributes = vcardPropToSearchableAttrMap.get(propFilter.filter_name, [])
+ if isinstance(searchableAttributes, str):
+ searchableAttributes = [searchableAttributes,]
+
+ unsearchableAttributes = vcardPropToUnsearchableAttrMap.get(propFilter.filter_name, [])
+ if isinstance(unsearchableAttributes, str):
+ unsearchableAttributes = [unsearchableAttributes,]
- binaryAttrNames = []
- stringAttrNames = []
- for attr in queryAttributes:
- if isinstance(attr, tuple):
- binaryAttrNames.append(attr[0])
+ #log.debug("searchableAttributes=%s" % (searchableAttributes,))
+ #log.debug("unsearchableAttributes=%s" % (unsearchableAttributes,))
+ queryAttributes = list(searchableAttributes) + list(unsearchableAttributes)
+ if not queryAttributes:
+ # not allAttrNames means propFilter.filter_name is not mapped
+ # return None to try to match all items if this is the only property filter
+ return (None, [], [])
+
+ allAttrNames = []
+ for attrName in queryAttributes:
+ if isinstance(attrName, tuple):
+ allAttrNames.append(attrName[0])
else:
- stringAttrNames.append(attr)
- allAttrStrings = stringAttrNames + binaryAttrNames
- if not allAttrStrings:
- # not AllAttrStrings means propFilter.filter_name is not mapped
- # return None to try to match all items if this is the only property filter
- return (None, [], [])
+ allAttrNames.append(attrName)
- constant = ABDirectoryQueryResult.constantProperties.get(propFilter.filter_name)
+ constant = constantProperties.get(propFilter.filter_name)
if propFilter.qualifier and isinstance(propFilter.qualifier, addressbookqueryfilter.IsNotDefined):
- return definedExpression(False, filterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrStrings)
+ return definedExpression(False, filterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrNames)
paramFilterElements = [paramFilterElement for paramFilterElement in propFilter.filters if isinstance(paramFilterElement, addressbookqueryfilter.ParameterFilter)]
textMatchElements = [textMatchElement for textMatchElement in propFilter.filters if isinstance(textMatchElement, addressbookqueryfilter.TextMatch)]
@@ -835,7 +855,7 @@
if len(paramFilterElements) > 0:
if supportedParamter(propFilter.filter_name, paramFilterElements, propFilterAllOf ):
if len(textMatchElements) == 0:
- return definedExpression(True, filterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrStrings)
+ return definedExpression(True, filterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrNames)
else:
if propFilterAllOf:
return (False, [], [])
@@ -869,7 +889,7 @@
@param filterAllOf: the C{True} if parent filter test is "allof"
@param propFilters: the C{list} of L{ComponentFilter} elements.
- @return: (needsAllRecords, espressionAttributes, expression) tuple
+ @return: (needsAllRecords, expressionAttributes, expression) tuple
"""
needsAllRecords = None
attributes = []
@@ -1050,7 +1070,12 @@
}
- def __init__(self, directoryBackedAddressBook, recordAttributes, additionalVCardProps=None, addDSAttrXProperties=False, appleInternalServer=False, ):
+ def __init__(self, directoryBackedAddressBook, recordAttributes,
+ kind=None,
+ additionalVCardProps=None,
+ addDSAttrXProperties=False,
+ appleInternalServer=False,
+ ):
self.log_debug("directoryBackedAddressBook=%s, attributes=%s, additionalVCardProps=%s" % (directoryBackedAddressBook, recordAttributes, additionalVCardProps,))
@@ -1090,7 +1115,20 @@
self.attributes[dsattributes.kDS1AttrGeneratedUID] = guid
- #generate a vCard here. May throw an exception
+ if not kind:
+ dsRecordTypeToKindMap = {
+ #dsattributes.kDSStdRecordTypePeople:"individual",
+ #dsattributes.kDSStdRecordTypeUsers:"individual",
+ dsattributes.kDSStdRecordTypeGroups:"group",
+ dsattributes.kDSStdRecordTypeLocations:"location",
+ dsattributes.kDSStdRecordTypeResources:"device",
+ }
+ recordType = self.firstValueForAttribute(dsattributes.kDSNAttrRecordType)
+ kind = dsRecordTypeToKindMap.get(recordType, "individual")
+ self.kind = kind.lower()
+
+
+ #generate a vCard here. May throw an exception
self.vCard()
@@ -1625,7 +1663,7 @@
# add apple-defined group vcard properties if record type is group
- if self.firstValueForAttribute(dsattributes.kDSNAttrRecordType) == dsattributes.kDSStdRecordTypeGroups:
+ if self.kind == "group":
vcard.addProperty(Property("X-ADDRESSBOOKSERVER-KIND", "group"))
# add members
@@ -1653,9 +1691,12 @@
"""
- # 2.1.4 SOURCE Type
+ # 2.1.4 SOURCE Type http://tools.ietf.org/html/rfc2426#section-2.1.4
# If the SOURCE type is present, then its value provides information
# how to find the source for the vCard.
+
+ # add the source, so that if the SOURCE is copied out and preserved, the client can refresh information
+ # However, client should really do a ab-query report matching UID on /directory/ not a multiget.
uri = joinURL(self._directoryBackedAddressBook.uri, vcard.propertyValue("UID") + ".vcf")
# seems like this should be in some standard place.
@@ -1671,7 +1712,19 @@
source = "http://%s:%s%s" % (config.ServerHostName, config.HTTPPort, uri)
vcard.addProperty(Property("SOURCE", source))
- # debug, create x attributes for all ds attributes
+ # in 4.0 spec:
+ # 6.1.4. KIND http://tools.ietf.org/html/rfc6350#section-6.1.4
+ #
+ # see also: http://www.iana.org/assignments/vcard-elements/vcard-elements.xml
+ #
+ vcard.addProperty(Property("KIND", self.kind))
+
+ # one more X- related to kind
+ if self.kind == "org":
+ vcard.addProperty(Property("X-ABShowAs", "COMPANY"))
+
+
+ # debug, create X-attributes for all ds attributes
if self.addDSAttrXProperties:
for attribute in self.originalAttributes:
for value in self.valuesForAttribute(attribute):
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/xmldirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/xmldirectorybacker.py 2012-04-19 17:41:39 UTC (rev 9152)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/xmldirectorybacker.py 2012-04-19 20:20:48 UTC (rev 9153)
@@ -130,8 +130,16 @@
queryMap = self.rdnSchema[queryType]
vcardPropToDirRecordAttrMap = queryMap["vcardPropToDirRecordAttrMap"]
dirRecordAttrToDSAttrMap = queryMap["dirRecordAttrToDSAttrMap"]
+
+ kind = {self.recordType_groups:"group",
+ self.recordType_locations:"location",
+ self.recordType_resources:"calendarresource",
+ }.get(queryType, "individual")
+
+ constantProperties = ABDirectoryQueryResult.constantProperties.copy()
+ constantProperties["KIND"] = kind
- allRecords, filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToDirRecordAttrMap );
+ allRecords, filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToDirRecordAttrMap, constantProperties=constantProperties );
self.log_debug("doAddressBookQuery: queryType=\"%s\" LDAP allRecords=%s, filterAttributes=%s, query=%s" % (queryType, allRecords, filterAttributes, "None" if dsFilter is None else dsFilter.generate(),))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120419/57479c22/attachment-0001.html>
More information about the calendarserver-changes
mailing list