diff --git a/src/java/davmail/exchange/ExchangeSession.java b/src/java/davmail/exchange/ExchangeSession.java index 88dae8ac..82708748 100644 --- a/src/java/davmail/exchange/ExchangeSession.java +++ b/src/java/davmail/exchange/ExchangeSession.java @@ -652,7 +652,7 @@ public abstract class ExchangeSession { /** * Test if the contact matches current condition. - * + * * @param contact Exchange Contact * @return true if contact matches condition */ @@ -676,6 +676,15 @@ public abstract class ExchangeSession { public boolean isEmpty() { return false; } + + public String getAttributeName() { + return attributeName; + } + + public String getValue() { + return value; + } + } /** @@ -736,7 +745,7 @@ public abstract class ExchangeSession { return false; } } - + } /** @@ -776,15 +785,9 @@ public abstract class ExchangeSession { public boolean isMatch(ExchangeSession.Contact contact) { String actualValue = contact.get(attributeName); - if (operator == Operator.IsNull) { - return actualValue == null; - } else if (operator == Operator.IsFalse) { - return "false".equals(actualValue); - } else if (operator == Operator.IsTrue) { - return "true".equals(actualValue); - } else { - return false; - } + return (operator == Operator.IsNull && actualValue == null) || + (operator == Operator.IsFalse && "false".equals(actualValue)) || + (operator == Operator.IsTrue && "true".equals(actualValue)); } } @@ -1004,7 +1007,7 @@ public abstract class ExchangeSession { Set visibleRecipients = new HashSet(); Address[] recipients = mimeMessage.getAllRecipients(); for (Address address : recipients) { - visibleRecipients.add(((InternetAddress)address).getAddress().toLowerCase()); + visibleRecipients.add(((InternetAddress) address).getAddress().toLowerCase()); } for (String recipient : rcptToRecipients) { if (!visibleRecipients.contains(recipient.toLowerCase())) { @@ -1732,6 +1735,10 @@ public abstract class ExchangeSession { return name; } + public void setName(String name) { + this.itemName = name; + } + /** * Compute vcard uid from name. * @@ -2003,7 +2010,7 @@ public abstract class ExchangeSession { // TODO: get current user attendee status, i18n String subject = vCalendar.getFirstVeventPropertyValue("SUMMARY"); if (subject == null) { - subject = BundleMessage.format("MEETING_REQUEST"); + subject = BundleMessage.format("MEETING_REQUEST"); } writer.writeHeader("Subject", subject); @@ -2809,6 +2816,8 @@ public abstract class ExchangeSession { return results; } + public abstract Map galFind(Condition condition) throws IOException; + /** * Full Contact attribute list */ diff --git a/src/java/davmail/exchange/dav/DavExchangeSession.java b/src/java/davmail/exchange/dav/DavExchangeSession.java index 298e9dfa..cd0806b5 100644 --- a/src/java/davmail/exchange/dav/DavExchangeSession.java +++ b/src/java/davmail/exchange/dav/DavExchangeSession.java @@ -25,6 +25,7 @@ import davmail.exception.DavMailException; import davmail.exception.HttpNotFoundException; import davmail.exchange.ExchangeSession; import davmail.exchange.VObject; +import davmail.exchange.XMLStreamUtil; import davmail.http.DavGatewayHttpClientFacade; import davmail.ui.tray.DavGatewayTray; import davmail.util.IOUtil; @@ -176,6 +177,96 @@ public class DavExchangeSession extends ExchangeSession { return !getFolderPath(folderPath).toLowerCase().startsWith(mailPath.toLowerCase()); } + /** + * LDAP to Exchange Criteria Map + */ + static final HashMap GALFIND_CRITERIA_MAP = new HashMap(); + + static { + GALFIND_CRITERIA_MAP.put("uid", "AN"); + // assume mail starts with firstname + GALFIND_CRITERIA_MAP.put("smtpemail1", "FN"); + GALFIND_CRITERIA_MAP.put("displayname", "DN"); + GALFIND_CRITERIA_MAP.put("cn", "DN"); + GALFIND_CRITERIA_MAP.put("givenname", "FN"); + GALFIND_CRITERIA_MAP.put("sn", "LN"); + GALFIND_CRITERIA_MAP.put("title", "TL"); + GALFIND_CRITERIA_MAP.put("company", "CP"); + GALFIND_CRITERIA_MAP.put("o", "CP"); + GALFIND_CRITERIA_MAP.put("l", "OF"); + GALFIND_CRITERIA_MAP.put("department", "DP"); + GALFIND_CRITERIA_MAP.put("apple-group-realname", "DP"); + } + + /** + * Exchange to LDAP attribute map + */ + static final HashMap GALFIND_ATTRIBUTE_MAP = new HashMap(); + + static { + GALFIND_ATTRIBUTE_MAP.put("uid", "AN"); + GALFIND_ATTRIBUTE_MAP.put("smtpemail1", "EM"); + GALFIND_ATTRIBUTE_MAP.put("cn", "DN"); + GALFIND_ATTRIBUTE_MAP.put("displayName", "DN"); + GALFIND_ATTRIBUTE_MAP.put("telephoneNumber", "PH"); + GALFIND_ATTRIBUTE_MAP.put("l", "OFFICE"); + GALFIND_ATTRIBUTE_MAP.put("company", "CP"); + GALFIND_ATTRIBUTE_MAP.put("title", "TL"); + + GALFIND_ATTRIBUTE_MAP.put("givenName", "first"); + GALFIND_ATTRIBUTE_MAP.put("initials", "initials"); + GALFIND_ATTRIBUTE_MAP.put("sn", "last"); + GALFIND_ATTRIBUTE_MAP.put("street", "street"); + GALFIND_ATTRIBUTE_MAP.put("st", "state"); + GALFIND_ATTRIBUTE_MAP.put("postalCode", "zip"); + GALFIND_ATTRIBUTE_MAP.put("c", "country"); + GALFIND_ATTRIBUTE_MAP.put("departement", "department"); + GALFIND_ATTRIBUTE_MAP.put("mobile", "mobile"); + } + + @Override + public Map galFind(Condition condition) throws IOException { + Map contacts = new HashMap(); + if (condition instanceof MultiCondition) { + // TODO + } else if (condition instanceof AttributeCondition) { + String searchAttribute = GALFIND_CRITERIA_MAP.get(((ExchangeSession.AttributeCondition) condition).getAttributeName()); + if (searchAttribute != null) { + String searchValue = ((ExchangeSession.AttributeCondition) condition).getValue(); + Map> results; + GetMethod getMethod = new GetMethod(URIUtil.encodePathQuery(getCmdBasePath() + "?Cmd=galfind&" + searchAttribute + '=' + searchValue)); + try { + DavGatewayHttpClientFacade.executeGetMethod(httpClient, getMethod, true); + results = XMLStreamUtil.getElementContentsAsMap(getMethod.getResponseBodyAsStream(), "item", "AN"); + } finally { + getMethod.releaseConnection(); + } + LOGGER.debug("galfind " + searchAttribute + '=' + searchValue + ": " + results.size() + " result(s)"); + for (Map result:results.values()) { + Contact contact = buildGalfindContact(result); + if (condition.isMatch(contact)) { + contacts.put(contact.getName().toLowerCase(), contact); + } + } + } + + } + return contacts; + } + + protected Contact buildGalfindContact(Map response) { + Contact contact = new Contact(); + contact.setName(response.get("AN")); + contact.put("uid", response.get("AN")); + for (Map.Entry entry : GALFIND_ATTRIBUTE_MAP.entrySet()) { + String attributeValue = response.get(entry.getValue()); + if (attributeValue != null) { + contact.put(entry.getKey(), attributeValue); + } + } + return contact; + } + @Override protected String getFreeBusyData(String attendee, String start, String end, int interval) throws IOException { String freebusyUrl = publicFolderUrl + "/?cmd=freebusy" + @@ -460,7 +551,7 @@ public class DavExchangeSession extends ExchangeSession { if (operator == Operator.IsEqualTo) { return actualValue.equals(lowerCaseValue); } else if (operator == Operator.Like) { - return actualValue.contains(lowerCaseValue); + return actualValue.contains(lowerCaseValue); } else if (operator == Operator.StartsWith) { return actualValue.startsWith(lowerCaseValue); } else { @@ -619,6 +710,9 @@ public class DavExchangeSession extends ExchangeSession { super(folderPath, itemName, properties, etag, noneMatch); } + public Contact() { + } + protected Set buildProperties() { Set propertyValues = new HashSet(); for (Map.Entry entry : entrySet()) { diff --git a/src/java/davmail/exchange/ews/EWSMethod.java b/src/java/davmail/exchange/ews/EWSMethod.java index 032795a3..d6ce8603 100644 --- a/src/java/davmail/exchange/ews/EWSMethod.java +++ b/src/java/davmail/exchange/ews/EWSMethod.java @@ -553,8 +553,6 @@ public abstract class EWSMethod extends PostMethod { public void checkSuccess() throws EWSException { if (errorDetail != null) { if (!"ErrorAccessDenied".equals(errorDetail) - && !"ErrorNameResolutionMultipleResults".equals(errorDetail) - && !"ErrorNameResolutionNoResults".equals(errorDetail) && !"ErrorMailRecipientNotFound".equals(errorDetail)) { try { throw new EWSException(errorDetail + "\n request: " + new String(generateSoapEnvelope(), "UTF-8")); @@ -633,7 +631,11 @@ public abstract class EWSMethod extends PostMethod { protected void handleErrors(XMLStreamReader reader) throws XMLStreamException { String result = handleTag(reader, "ResponseCode"); - if (errorDetail == null && result != null && !"NoError".equals(result)) { + if (errorDetail == null && result != null + && !"NoError".equals(result) + && !"ErrorNameResolutionMultipleResults".equals(result) + && !"ErrorNameResolutionNoResults".equals(result) + ) { errorDetail = result; } if (isStartTag(reader, "faultstring")) { diff --git a/src/java/davmail/exchange/ews/EwsExchangeSession.java b/src/java/davmail/exchange/ews/EwsExchangeSession.java index 26c86e6a..41c4c2d8 100644 --- a/src/java/davmail/exchange/ews/EwsExchangeSession.java +++ b/src/java/davmail/exchange/ews/EwsExchangeSession.java @@ -361,10 +361,6 @@ public class EwsExchangeSession extends ExchangeSession { return fieldURI; } - protected String getValue() { - return value; - } - protected Operator getOperator() { return operator; } @@ -381,22 +377,24 @@ public class EwsExchangeSession extends ExchangeSession { FieldURI fieldURI = getFieldURI(); fieldURI.appendTo(buffer); - buffer.append(""); + } + buffer.append(""); + buffer.append("\"/>"); + if (operator == Operator.IsEqualTo) { + buffer.append(""); + } buffer.append("'); } - public String getAttributeName() { - return attributeName; - } - public boolean isMatch(ExchangeSession.Contact contact) { String lowerCaseValue = value.toLowerCase(); @@ -406,7 +404,7 @@ public class EwsExchangeSession extends ExchangeSession { } actualValue = actualValue.toLowerCase(); if (operator == Operator.IsEqualTo) { - return value.equals(actualValue); + return lowerCaseValue.equals(actualValue); } else { return operator == Operator.Contains && ((containmentMode.equals(ContainmentMode.Substring) && actualValue.contains(lowerCaseValue)) || (containmentMode.equals(ContainmentMode.Prefixed) && actualValue.startsWith(lowerCaseValue))); @@ -711,7 +709,7 @@ public class EwsExchangeSession extends ExchangeSession { } for (String attributeName : CONTACT_ATTRIBUTES) { String value = response.get(Field.get(attributeName).getResponseName()); - if (value != null) { + if (value != null && value.length() > 0) { if ("bday".equals(attributeName) || "anniversary".equals(attributeName) || "lastmodified".equals(attributeName) || "datereceived".equals(attributeName)) { value = convertDateFromExchange(value); } @@ -852,10 +850,6 @@ public class EwsExchangeSession extends ExchangeSession { return itemResult; } - - public void setName(String name) { - this.itemName = name; - } } protected class Event extends ExchangeSession.Event { @@ -1264,17 +1258,19 @@ public class EwsExchangeSession extends ExchangeSession { protected static final HashMap GALFIND_ATTRIBUTE_MAP = new HashMap(); static { + GALFIND_ATTRIBUTE_MAP.put("uid", "Name"); GALFIND_ATTRIBUTE_MAP.put("cn", "DisplayName"); GALFIND_ATTRIBUTE_MAP.put("givenName", "GivenName"); GALFIND_ATTRIBUTE_MAP.put("sn", "Surname"); GALFIND_ATTRIBUTE_MAP.put("email1", "EmailAddress1"); - GALFIND_ATTRIBUTE_MAP.put("email2", "EmailAddress1"); - GALFIND_ATTRIBUTE_MAP.put("email3", "EmailAddress1"); + GALFIND_ATTRIBUTE_MAP.put("email2", "EmailAddress2"); + GALFIND_ATTRIBUTE_MAP.put("email3", "EmailAddress3"); } protected Contact buildGalfindContact(EWSMethod.Item response) { Contact contact = new Contact(); - contact.setName(response.get("DisplayName")); + contact.setName(response.get("Name")); + contact.put("uid", response.get("Name")); for (Map.Entry entry : GALFIND_ATTRIBUTE_MAP.entrySet()) { String attributeValue = response.get(entry.getValue()); if (attributeValue != null) { @@ -1284,7 +1280,7 @@ public class EwsExchangeSession extends ExchangeSession { return contact; } - protected Map galFind(Condition condition) throws IOException { + public Map galFind(Condition condition) throws IOException { Map contacts = new HashMap(); if (condition instanceof MultiCondition) { List conditions = ((MultiCondition) condition).getConditions(); @@ -1297,7 +1293,7 @@ public class EwsExchangeSession extends ExchangeSession { Map innerContacts = galFind(conditions.get(0)); for (ExchangeSession.Contact contact : innerContacts.values()) { if (condition.isMatch(contact)) { - contacts.put(contact.getName(), contact); + contacts.put(contact.getName().toLowerCase(), contact); } } } @@ -1313,13 +1309,16 @@ public class EwsExchangeSession extends ExchangeSession { if (operator == Operator.IsEqualTo) { searchValue = '=' + searchValue; } + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("ResolveNames(" + searchValue + ')'); + } ResolveNamesMethod resolveNamesMethod = new ResolveNamesMethod(searchValue); executeMethod(resolveNamesMethod); List responses = resolveNamesMethod.getResponseItems(); for (EWSMethod.Item response : responses) { Contact contact = buildGalfindContact(response); if (condition.isMatch(contact)) { - contacts.put(contact.getName(), contact); + contacts.put(contact.getName().toLowerCase(), contact); } } } diff --git a/src/java/davmail/exchange/ews/ResolveNamesMethod.java b/src/java/davmail/exchange/ews/ResolveNamesMethod.java index db0c2f55..95b07834 100644 --- a/src/java/davmail/exchange/ews/ResolveNamesMethod.java +++ b/src/java/davmail/exchange/ews/ResolveNamesMethod.java @@ -45,24 +45,74 @@ public class ResolveNamesMethod extends EWSMethod { Item responseItem = new Item(); responseItem.type = "Contact"; // skip to Contact - while (reader.hasNext() && !isStartTag(reader, "Contact")) { + while (reader.hasNext() && !isStartTag(reader, "Resolution")) { reader.next(); } - while (reader.hasNext() && !isEndTag(reader, "Contact")) { + while (reader.hasNext() && !isEndTag(reader, "Resolution")) { int event = reader.next(); if (event == XMLStreamConstants.START_ELEMENT) { String tagLocalName = reader.getLocalName(); - if ("EmailAddresses".equals(tagLocalName)) { - handleAddresses(reader, responseItem); - } else { - responseItem.put(tagLocalName, reader.getElementText()); + if ("Mailbox".equals(tagLocalName)) { + handleMailbox(reader, responseItem); + } else if ("Contact".equals(tagLocalName)) { + handleContact(reader, responseItem); } } } return responseItem; } - protected void handleAddresses(XMLStreamReader reader, Item responseItem) throws XMLStreamException { + protected void handleMailbox(XMLStreamReader reader, Item responseItem) throws XMLStreamException { + while (reader.hasNext() && !isEndTag(reader, "Mailbox")) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + String tagLocalName = reader.getLocalName(); + if ("Name".equals(tagLocalName)) { + responseItem.put(tagLocalName, reader.getElementText()); + } + } + } + } + + protected void handleContact(XMLStreamReader reader, Item responseItem) throws XMLStreamException { + while (reader.hasNext() && !isEndTag(reader, "Contact")) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + String tagLocalName = reader.getLocalName(); + if ("EmailAddresses".equals(tagLocalName)) { + handleEmailAddresses(reader, responseItem); + } else if ("PhysicalAddresses".equals(tagLocalName)) { + handlePhysicalAddresses(reader, responseItem); + } else if ("PhoneNumbers".equals(tagLocalName)) { + handlePhoneNumbers(reader, responseItem); + } else { + responseItem.put(tagLocalName, reader.getElementText()); + } + } + } + } + + protected void handlePhysicalAddresses(XMLStreamReader reader, Item responseItem) throws XMLStreamException { + while (reader.hasNext() && !isEndTag(reader, "PhysicalAddresses")) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + String tagLocalName = reader.getLocalName(); + // TODO + } + } + } + + protected void handlePhoneNumbers(XMLStreamReader reader, Item responseItem) throws XMLStreamException { + while (reader.hasNext() && !isEndTag(reader, "PhoneNumbers")) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + String tagLocalName = reader.getLocalName(); + // TODO + } + } + } + + protected void handleEmailAddresses(XMLStreamReader reader, Item responseItem) throws XMLStreamException { while (reader.hasNext() && !isEndTag(reader, "EmailAddresses")) { int event = reader.next(); if (event == XMLStreamConstants.START_ELEMENT) { diff --git a/src/java/davmail/ldap/LdapConnection.java b/src/java/davmail/ldap/LdapConnection.java index 596528c1..01d69492 100644 --- a/src/java/davmail/ldap/LdapConnection.java +++ b/src/java/davmail/ldap/LdapConnection.java @@ -105,8 +105,8 @@ public class LdapConnection extends AbstractConnection { CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("extensionattribute2", "custom2"); CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("extensionattribute3", "custom3"); CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("extensionattribute4", "custom4"); - CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("email1", "mail"); - CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("email2", "xmozillasecondemail"); + CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("smtpemail1", "mail"); + CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("smtpemail2", "xmozillasecondemail"); CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("homeCountry", "mozillahomecountryname"); CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("homeCity", "mozillahomelocalityname"); CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("homePostalCode", "mozillahomepostalcode"); @@ -225,7 +225,7 @@ public class LdapConnection extends AbstractConnection { static { LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("uid", "imapUid"); - LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("mail", "email1"); + LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("mail", "smtpemail1"); LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("displayname", "cn"); LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("commonname", "cn"); @@ -846,7 +846,7 @@ public class LdapConnection extends AbstractConnection { static interface LdapFilter { ExchangeSession.Condition getContactSearchFilter(); - Map> findInGAL(ExchangeSession session) throws IOException; + Map findInGAL(ExchangeSession session) throws IOException; void add(LdapFilter filter); @@ -973,11 +973,11 @@ public class LdapConnection extends AbstractConnection { * @return persons map * @throws IOException on error */ - public Map> findInGAL(ExchangeSession session) throws IOException { - Map> persons = null; + public Map findInGAL(ExchangeSession session) throws IOException { + Map persons = null; for (LdapFilter child : criteria) { - Map> childFind = child.findInGAL(session); + Map childFind = child.findInGAL(session); if (childFind != null) { if (persons == null) { @@ -992,10 +992,10 @@ public class LdapConnection extends AbstractConnection { // Thus, instead of building the intersection, we check each result against // all filters. - for (Map result : childFind.values()) { + for (ExchangeSession.Contact result : childFind.values()) { if (isMatch(result)) { // This item from the child result set matches all sub-criteria, add it - persons.put(result.get("AN"), result); + persons.put(result.get("uid"), result); } } } @@ -1004,7 +1004,7 @@ public class LdapConnection extends AbstractConnection { if ((persons == null) && !isFullSearch()) { // return an empty map (indicating no results were found) - return new HashMap>(); + return new HashMap(); } return persons; @@ -1139,7 +1139,7 @@ public class LdapConnection extends AbstractConnection { return false; } - public Map> findInGAL(ExchangeSession session) throws IOException { + public Map findInGAL(ExchangeSession session) throws IOException { if (canIgnore) { return null; } @@ -1148,17 +1148,17 @@ public class LdapConnection extends AbstractConnection { if (galFindAttributeName != null) { // quick fix for cn=* filter - Map> galPersons = session.galFind(galFindAttributeName, "*".equals(value) ? "A" : value); + Map galPersons = session.galFind(session.startsWith(attributeName, "*".equals(value) ? "A" : value)); if (operator == LDAP_FILTER_EQUALITY) { // Make sure only exact matches are returned - Map> results = new HashMap>(); + Map results = new HashMap(); - for (Map person : galPersons.values()) { + for (ExchangeSession.Contact person : galPersons.values()) { if (isMatch(person)) { // Found an exact match - results.put(person.get("AN"), person); + results.put(person.get("uid"), person); } } @@ -1213,9 +1213,9 @@ public class LdapConnection extends AbstractConnection { protected static String getLdapAttributeName(String contactAttributeName) { String mappedAttributeName = CONTACT_TO_LDAP_ATTRIBUTE_MAP.get(contactAttributeName); if (mappedAttributeName != null) { - return contactAttributeName; - } else { return mappedAttributeName; + } else { + return contactAttributeName; } } @@ -1265,7 +1265,7 @@ public class LdapConnection extends AbstractConnection { if (session != null) { // single user request String uid = dn.substring("uid=".length(), dn.indexOf(',')); - Map> persons = null; + Map persons = null; // first search in contact try { @@ -1278,12 +1278,12 @@ public class LdapConnection extends AbstractConnection { // then in GAL if (persons == null || persons.isEmpty()) { - persons = session.galFind("AN", uid); + persons = session.galFind(session.isEqualTo("uid", uid)); - Map person = persons.get(uid.toLowerCase()); + ExchangeSession.Contact person = persons.get(uid.toLowerCase()); // filter out non exact results if (persons.size() > 1 || person == null) { - persons = new HashMap>(); + persons = new HashMap(); if (person != null) { persons.put(uid.toLowerCase(), person); } @@ -1303,10 +1303,10 @@ public class LdapConnection extends AbstractConnection { sendComputerContext(currentMessageId, returningAttributes); } else if ((BASE_CONTEXT.equalsIgnoreCase(dn) || OD_USER_CONTEXT.equalsIgnoreCase(dn))) { if (session != null) { - Map> persons = new HashMap>(); + Map persons = new HashMap(); if (ldapFilter.isFullSearch()) { // append personal contacts first - for (Map person : contactFind(null, returningAttributes, sizeLimit).values()) { + for (ExchangeSession.Contact person : contactFind(null, returningAttributes, sizeLimit).values()) { persons.put(person.get("imapUid"), person); if (persons.size() == sizeLimit) { break; @@ -1315,8 +1315,8 @@ public class LdapConnection extends AbstractConnection { // full search for (char c = 'A'; c < 'Z'; c++) { if (!abandon && persons.size() < sizeLimit) { - for (Map person : session.galFind("AN", String.valueOf(c)).values()) { - persons.put(person.get("AN"), person); + for (ExchangeSession.Contact person : session.galFind(session.startsWith("uid", String.valueOf(c))).values()) { + persons.put(person.get("uid"), person); if (persons.size() == sizeLimit) { break; } @@ -1333,7 +1333,7 @@ public class LdapConnection extends AbstractConnection { // if ldapfilter is not a full search and filter is null, // ignored all attribute filters => return empty results if (ldapFilter.isFullSearch() || filter != null) { - for (Map person : contactFind(filter, returningAttributes, sizeLimit).values()) { + for (ExchangeSession.Contact person : contactFind(filter, returningAttributes, sizeLimit).values()) { persons.put(person.get("imapUid"), person); if (persons.size() == sizeLimit) { @@ -1341,12 +1341,12 @@ public class LdapConnection extends AbstractConnection { } } if (!abandon && persons.size() < sizeLimit) { - for (Map person : ldapFilter.findInGAL(session).values()) { + for (ExchangeSession.Contact person : ldapFilter.findInGAL(session).values()) { if (persons.size() == sizeLimit) { break; } - persons.put(person.get("AN"), person); + persons.put(person.get("uid"), person); } } } @@ -1399,7 +1399,7 @@ public class LdapConnection extends AbstractConnection { * @return List of users * @throws IOException on error */ - public Map> contactFind(ExchangeSession.Condition condition, Set returningAttributes, int maxCount) throws IOException { + public Map contactFind(ExchangeSession.Condition condition, Set returningAttributes, int maxCount) throws IOException { Set contactReturningAttributes; if (returningAttributes != null && !returningAttributes.isEmpty()) { contactReturningAttributes = new HashSet(); @@ -1415,13 +1415,17 @@ public class LdapConnection extends AbstractConnection { contactReturningAttributes = ExchangeSession.CONTACT_ATTRIBUTES; } - Map> results = new HashMap>(); + Map results = new HashMap(); List contacts = session.searchContacts(ExchangeSession.CONTACTS, contactReturningAttributes, condition, maxCount); for (ExchangeSession.Contact contact : contacts) { - if (contact.get("imapUid") != null) { - results.put(contact.get("imapUid"), contact); + // use imapUid as uid + String imapUid = contact.get("imapUid"); + if (imapUid != null) { + contact.put("uid", imapUid); + contact.remove("imapUid"); + results.put(imapUid, contact); } } @@ -1438,7 +1442,7 @@ public class LdapConnection extends AbstractConnection { * @param returningAttributes returning attributes * @throws IOException on error */ - protected void sendPersons(int currentMessageId, String baseContext, Map> persons, Set returningAttributes) throws IOException { + protected void sendPersons(int currentMessageId, String baseContext, Map persons, Set returningAttributes) throws IOException { boolean needObjectClasses = returningAttributes.contains("objectclass") || returningAttributes.isEmpty(); boolean iCalSearch = returningAttributes.contains("apple-serviceslocator"); boolean returnAllAttributes = returningAttributes.isEmpty(); @@ -1456,16 +1460,16 @@ public class LdapConnection extends AbstractConnection { needDetails = false; } - for (Map person : persons.values()) { + for (ExchangeSession.Contact person : persons.values()) { if (abandon) { break; } - returningAttributes.add("uid"); Map ldapPerson = new HashMap(); // convert GAL entries - if (person.get("AN") != null) { + /*if (person.get("uid") != null) { + // TODO: move to galFind // add detailed information, only for GAL entries if (needDetails) { session.galLookup(person); @@ -1484,13 +1488,14 @@ public class LdapConnection extends AbstractConnection { ldapPerson.put(ldapAttribute, value); } } + // TODO // iCal fix to suit both iCal 3 and 4: move cn to sn, remove cn if (iCalSearch && ldapPerson.get("cn") != null && returningAttributes.contains("sn")) { ldapPerson.put("sn", ldapPerson.get("cn")); ldapPerson.remove("cn"); } - } else { + } else {*/ // convert Contact entries if (returnAllAttributes) { // just convert contact attributes to default ldap names @@ -1502,6 +1507,8 @@ public class LdapConnection extends AbstractConnection { } } } else { + // always map uid + ldapPerson.put("uid", person.get("uid")); // iterate over requested attributes for (String ldapAttribute : returningAttributes) { String contactAttribute = getContactAttributeName(ldapAttribute); @@ -1528,7 +1535,7 @@ public class LdapConnection extends AbstractConnection { } } - } + //} // Process all attributes which have static mappings for (Map.Entry entry : STATIC_ATTRIBUTE_MAP.entrySet()) {