mirror of
https://github.com/moparisthebest/davmail
synced 2024-12-13 19:22:22 -05:00
Handle returning attributes : return only requested attributes
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@214 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
d66bd4b38c
commit
937dadb988
@ -19,6 +19,8 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a caldav connection.
|
* Handle a caldav connection.
|
||||||
@ -28,6 +30,14 @@ public class LdapConnection extends AbstractConnection {
|
|||||||
* Davmail base context
|
* Davmail base context
|
||||||
*/
|
*/
|
||||||
static final String BASE_CONTEXT = "ou=people";
|
static final String BASE_CONTEXT = "ou=people";
|
||||||
|
|
||||||
|
static final List<String> PERSON_OBJECT_CLASSES = new ArrayList<String>();
|
||||||
|
static {
|
||||||
|
PERSON_OBJECT_CLASSES.add("top");
|
||||||
|
PERSON_OBJECT_CLASSES.add("person");
|
||||||
|
PERSON_OBJECT_CLASSES.add("organizationalPerson");
|
||||||
|
PERSON_OBJECT_CLASSES.add("inetOrgPerson");
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Exchange to LDAP attribute map
|
* Exchange to LDAP attribute map
|
||||||
*/
|
*/
|
||||||
@ -35,13 +45,13 @@ public class LdapConnection extends AbstractConnection {
|
|||||||
static {
|
static {
|
||||||
ATTRIBUTE_MAP.put("uid", "AN");
|
ATTRIBUTE_MAP.put("uid", "AN");
|
||||||
ATTRIBUTE_MAP.put("mail", "EM");
|
ATTRIBUTE_MAP.put("mail", "EM");
|
||||||
|
ATTRIBUTE_MAP.put("cn", "DN");
|
||||||
ATTRIBUTE_MAP.put("displayName", "DN");
|
ATTRIBUTE_MAP.put("displayName", "DN");
|
||||||
ATTRIBUTE_MAP.put("telephoneNumber", "PH");
|
ATTRIBUTE_MAP.put("telephoneNumber", "PH");
|
||||||
ATTRIBUTE_MAP.put("l", "OFFICE");
|
ATTRIBUTE_MAP.put("l", "OFFICE");
|
||||||
ATTRIBUTE_MAP.put("company", "CP");
|
ATTRIBUTE_MAP.put("company", "CP");
|
||||||
ATTRIBUTE_MAP.put("title", "TL");
|
ATTRIBUTE_MAP.put("title", "TL");
|
||||||
|
|
||||||
ATTRIBUTE_MAP.put("cn", "DN");
|
|
||||||
ATTRIBUTE_MAP.put("givenName", "first");
|
ATTRIBUTE_MAP.put("givenName", "first");
|
||||||
ATTRIBUTE_MAP.put("initials", "initials");
|
ATTRIBUTE_MAP.put("initials", "initials");
|
||||||
ATTRIBUTE_MAP.put("sn", "last");
|
ATTRIBUTE_MAP.put("sn", "last");
|
||||||
@ -53,6 +63,19 @@ public class LdapConnection extends AbstractConnection {
|
|||||||
ATTRIBUTE_MAP.put("mobile", "mobile");
|
ATTRIBUTE_MAP.put("mobile", "mobile");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final HashSet<String> EXTENDED_ATTRIBUTES = new HashSet<String>();
|
||||||
|
static {
|
||||||
|
EXTENDED_ATTRIBUTES.add("givenname");
|
||||||
|
EXTENDED_ATTRIBUTES.add("initials");
|
||||||
|
EXTENDED_ATTRIBUTES.add("sn");
|
||||||
|
EXTENDED_ATTRIBUTES.add("street");
|
||||||
|
EXTENDED_ATTRIBUTES.add("st");
|
||||||
|
EXTENDED_ATTRIBUTES.add("postalcode");
|
||||||
|
EXTENDED_ATTRIBUTES.add("c");
|
||||||
|
EXTENDED_ATTRIBUTES.add("departement");
|
||||||
|
EXTENDED_ATTRIBUTES.add("mobile");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LDAP to Exchange Criteria Map
|
* LDAP to Exchange Criteria Map
|
||||||
*/
|
*/
|
||||||
@ -153,17 +176,11 @@ public class LdapConnection extends AbstractConnection {
|
|||||||
int bytesleft; // Number of bytes that need to read for completing resp
|
int bytesleft; // Number of bytes that need to read for completing resp
|
||||||
int br; // Temp; number of bytes read from stream
|
int br; // Temp; number of bytes read from stream
|
||||||
int offset; // Offset of where to store bytes in inbuf
|
int offset; // Offset of where to store bytes in inbuf
|
||||||
int seqlen; // Length of ASN sequence
|
|
||||||
int seqlenlen; // Number of sequence length bytes
|
|
||||||
boolean eos; // End of stream
|
boolean eos; // End of stream
|
||||||
BerDecoder reqBer; // Decoder for ASN.1 BER data from inbuf
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
seqlen = 0;
|
|
||||||
seqlenlen = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// check that it is the beginning of a sequence
|
// check that it is the beginning of a sequence
|
||||||
bytesread = is.read(inbuf, offset, 1);
|
bytesread = is.read(inbuf, offset, 1);
|
||||||
@ -178,13 +195,13 @@ public class LdapConnection extends AbstractConnection {
|
|||||||
bytesread = is.read(inbuf, offset, 1);
|
bytesread = is.read(inbuf, offset, 1);
|
||||||
if (bytesread < 0)
|
if (bytesread < 0)
|
||||||
break; // EOF
|
break; // EOF
|
||||||
seqlen = inbuf[offset++];
|
int seqlen = inbuf[offset++]; // Length of ASN sequence
|
||||||
|
|
||||||
// if high bit is on, length is encoded in the
|
// if high bit is on, length is encoded in the
|
||||||
// subsequent length bytes and the number of length bytes
|
// subsequent length bytes and the number of length bytes
|
||||||
// is equal to & 0x80 (i.e. length byte with high bit off).
|
// is equal to & 0x80 (i.e. length byte with high bit off).
|
||||||
if ((seqlen & 0x80) == 0x80) {
|
if ((seqlen & 0x80) == 0x80) {
|
||||||
seqlenlen = seqlen & 0x7f; // number of length bytes
|
int seqlenlen = seqlen & 0x7f; // number of length bytes
|
||||||
|
|
||||||
bytesread = 0;
|
bytesread = 0;
|
||||||
eos = false;
|
eos = false;
|
||||||
@ -279,15 +296,19 @@ public class LdapConnection extends AbstractConnection {
|
|||||||
} else if (requestOperation == LDAP_REQ_SEARCH) {
|
} else if (requestOperation == LDAP_REQ_SEARCH) {
|
||||||
String dn = reqBer.parseString(isLdapV3());
|
String dn = reqBer.parseString(isLdapV3());
|
||||||
int scope = reqBer.parseEnumeration();
|
int scope = reqBer.parseEnumeration();
|
||||||
/*int deref =*/ reqBer.parseEnumeration();
|
int derefAliases = reqBer.parseEnumeration();
|
||||||
int sizeLimit = reqBer.parseInt();
|
int sizeLimit = reqBer.parseInt();
|
||||||
if (sizeLimit > 100 || sizeLimit == 0) {
|
if (sizeLimit > 100 || sizeLimit == 0) {
|
||||||
sizeLimit = 100;
|
sizeLimit = 100;
|
||||||
}
|
}
|
||||||
/* int timelimit = */reqBer.parseInt();
|
int timelimit = reqBer.parseInt();
|
||||||
/* boolean attrsOnly = */reqBer.parseBoolean();
|
boolean typesOnly = reqBer.parseBoolean();
|
||||||
|
Map<String, String> criteria = parseFilter(reqBer);
|
||||||
|
Set<String> returningAttributes = parseReturningAttributes(reqBer);
|
||||||
|
|
||||||
int size = 0;
|
int size = 0;
|
||||||
DavGatewayTray.debug("LDAP_REQ_SEARCH base="+dn+" scope: "+scope+" sizelimit: "+sizeLimit);
|
DavGatewayTray.debug("LDAP_REQ_SEARCH base="+dn+" scope: "+scope+" sizelimit: "+sizeLimit+
|
||||||
|
" returning attributes: "+returningAttributes);
|
||||||
|
|
||||||
if (scope == SCOPE_BASE_OBJECT) {
|
if (scope == SCOPE_BASE_OBJECT) {
|
||||||
if ("".equals(dn)) {
|
if ("".equals(dn)) {
|
||||||
@ -303,13 +324,11 @@ public class LdapConnection extends AbstractConnection {
|
|||||||
String uid = dn.substring("uid=".length(), dn.indexOf(','));
|
String uid = dn.substring("uid=".length(), dn.indexOf(','));
|
||||||
Map<String, Map<String, String>> persons = session.galFind("AN", uid);
|
Map<String, Map<String, String>> persons = session.galFind("AN", uid);
|
||||||
size = persons.size();
|
size = persons.size();
|
||||||
sendPersons(currentMessageId, persons);
|
sendPersons(currentMessageId, persons, returningAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (BASE_CONTEXT.equalsIgnoreCase(dn) && session != null) {
|
} else if (BASE_CONTEXT.equalsIgnoreCase(dn) && session != null) {
|
||||||
|
|
||||||
Map<String, String> criteria = parseFilter(reqBer);
|
|
||||||
|
|
||||||
Map<String, Map<String, String>> persons = new HashMap<String, Map<String, String>>();
|
Map<String, Map<String, String>> persons = new HashMap<String, Map<String, String>>();
|
||||||
if ("*".equals(criteria.get("objectclass"))) {
|
if ("*".equals(criteria.get("objectclass"))) {
|
||||||
// full search
|
// full search
|
||||||
@ -344,7 +363,7 @@ public class LdapConnection extends AbstractConnection {
|
|||||||
|
|
||||||
size = persons.size();
|
size = persons.size();
|
||||||
DavGatewayTray.debug("LDAP_REQ_SEARCH found "+size+" results");
|
DavGatewayTray.debug("LDAP_REQ_SEARCH found "+size+" results");
|
||||||
sendPersons(currentMessageId, persons);
|
sendPersons(currentMessageId, persons, returningAttributes);
|
||||||
DavGatewayTray.debug("LDAP_REQ_SEARCH end");
|
DavGatewayTray.debug("LDAP_REQ_SEARCH end");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,33 +440,63 @@ public class LdapConnection extends AbstractConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Set<String> parseReturningAttributes(BerDecoder reqBer) throws IOException {
|
||||||
|
Set<String> returningAttributes = new HashSet<String>();
|
||||||
|
int[] seqSize = new int[1];
|
||||||
|
reqBer.parseSeq(seqSize);
|
||||||
|
int end = reqBer.getParsePosition() + seqSize[0];
|
||||||
|
while (reqBer.getParsePosition() < end && reqBer.bytesLeft() > 0) {
|
||||||
|
returningAttributes.add(reqBer.parseString(isLdapV3()).toLowerCase());
|
||||||
|
}
|
||||||
|
return returningAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert to LDAP attributes and send entry
|
* Convert to LDAP attributes and send entry
|
||||||
* @param currentMessageId current Message Id
|
* @param currentMessageId current Message Id
|
||||||
* @param persons persons Map
|
* @param persons persons Map
|
||||||
* @throws IOException on error
|
* @throws IOException on error
|
||||||
*/
|
*/
|
||||||
protected void sendPersons(int currentMessageId, Map<String, Map<String, String>> persons) throws IOException {
|
protected void sendPersons(int currentMessageId, Map<String, Map<String, String>> persons, Set<String> returningAttributes) throws IOException {
|
||||||
|
boolean needObjectClasses = returningAttributes.contains("objectclass");
|
||||||
|
boolean returnAllAttributes = returningAttributes.size() == 0;
|
||||||
for (Map<String, String> person : persons.values()) {
|
for (Map<String, String> person : persons.values()) {
|
||||||
// add detailed information, only if few results
|
boolean needDetails = returnAllAttributes;
|
||||||
if (persons.size() <=10) {
|
if (!needDetails) {
|
||||||
session.galLookup(person);
|
for (String attributeName : EXTENDED_ATTRIBUTES) {
|
||||||
|
if (returningAttributes.contains(attributeName)) {
|
||||||
|
needDetails = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add detailed information, only if few results
|
||||||
|
if (needDetails && persons.size() <= 10) {
|
||||||
|
session.galLookup(person);
|
||||||
|
}
|
||||||
|
|
||||||
|
returningAttributes.add("uid");
|
||||||
|
|
||||||
Map<String, Object> ldapPerson = new HashMap<String, Object>();
|
Map<String, Object> ldapPerson = new HashMap<String, Object>();
|
||||||
for (Map.Entry<String, String> entry : ATTRIBUTE_MAP.entrySet()) {
|
for (Map.Entry<String, String> entry : ATTRIBUTE_MAP.entrySet()) {
|
||||||
String ldapAttribute = entry.getKey();
|
String ldapAttribute = entry.getKey();
|
||||||
String exchangeAttribute = entry.getValue();
|
String exchangeAttribute = entry.getValue();
|
||||||
String value = person.get(exchangeAttribute);
|
String value = person.get(exchangeAttribute);
|
||||||
if (value != null) {
|
if (value != null
|
||||||
|
&& (returnAllAttributes || returningAttributes.contains(ldapAttribute.toLowerCase()))) {
|
||||||
ldapPerson.put(ldapAttribute, value);
|
ldapPerson.put(ldapAttribute, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (needObjectClasses) {
|
||||||
|
ldapPerson.put("objectClass", PERSON_OBJECT_CLASSES);
|
||||||
|
}
|
||||||
|
|
||||||
sendEntry(currentMessageId, "uid=" + ldapPerson.get("uid") + "," + BASE_CONTEXT, ldapPerson);
|
sendEntry(currentMessageId, "uid=" + ldapPerson.get("uid") + "," + BASE_CONTEXT, ldapPerson);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send Root DSE
|
* Send Root DSE
|
||||||
* @param currentMessageId current message id
|
* @param currentMessageId current message id
|
||||||
@ -530,7 +579,7 @@ public class LdapConnection extends AbstractConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void sendResponse() throws IOException {
|
protected void sendResponse() throws IOException {
|
||||||
//Ber.dumpBER(System.out, ">\n", responseBer.getBuf(), 0, responseBer.getDataLen());
|
Ber.dumpBER(System.out, ">\n", responseBer.getBuf(), 0, responseBer.getDataLen());
|
||||||
os.write(responseBer.getBuf(), 0, responseBer.getDataLen());
|
os.write(responseBer.getBuf(), 0, responseBer.getDataLen());
|
||||||
os.flush();
|
os.flush();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user