Skip to content

Commit

Permalink
ZCS-991 ZCO fails to parse GetContactResponse with SMIME feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Rohan Ambasta authored and grishick committed Mar 23, 2017
1 parent 367fd45 commit 735b240
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 13 deletions.
1 change: 1 addition & 0 deletions common/src/java/com/zimbra/common/soap/MailConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ private MailConstants() {
public static final String A_INVALID = "invalid";
public static final String A_REMINDER = "reminder";
public static final String A_RETURN_HIDDEN_ATTRS = "returnHiddenAttrs";
public static final String A_RETURN_CERT_INFO = "returnCertInfo";
public static final String A_MAX_MEMBERS = "maxMembers";
public static final String A_TOO_MANY_MEMBERS = "tooManyMembers";
public static final String A_ACTIVESYNC_DISABLED = "activesyncdisabled";
Expand Down
12 changes: 12 additions & 0 deletions soap/src/java/com/zimbra/soap/mail/message/GetContactsRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ public class GetContactsRequest {
@XmlAttribute(name=MailConstants.A_RETURN_HIDDEN_ATTRS /* returnHiddenAttrs */, required=false)
private ZmBoolean returnHiddenAttrs;

/**
* @zm-api-field-tag return-certificate-info
* @zm-api-field-description Whether to return smime certificate info
* <br />
*/
@XmlAttribute(name=MailConstants.A_RETURN_CERT_INFO /* returnCertInfo */, required=false)
private ZmBoolean returnCertInfo;

/**
* @zm-api-field-tag max-members
* @zm-api-field-description Max members
Expand Down Expand Up @@ -185,6 +193,9 @@ public void setDerefGroupMember(Boolean derefGroupMember) {
public void setReturnHiddenAttrs(Boolean returnHiddenAttrs) {
this.returnHiddenAttrs = ZmBoolean.fromBool(returnHiddenAttrs);
}
public void setReturnCertInfo(Boolean returnCertInfo) {
this.returnCertInfo = ZmBoolean.fromBool(returnCertInfo);
}
public void setMaxMembers(Long maxMembers) {
this.maxMembers = maxMembers;
}
Expand Down Expand Up @@ -226,6 +237,7 @@ public void addContact(Id contact) {
public String getSortBy() { return sortBy; }
public Boolean getDerefGroupMember() { return ZmBoolean.toBool(derefGroupMember); }
public Boolean getReturnHiddenAttrs() { return ZmBoolean.toBool(returnHiddenAttrs); }
public Boolean getReturnCertInfo() { return ZmBoolean.toBool(returnCertInfo); }
public Long getMaxMembers() { return maxMembers; }
public List<AttributeName> getAttributes() {
return Collections.unmodifiableList(attributes);
Expand Down
16 changes: 15 additions & 1 deletion store/docs/soap.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2780,7 +2780,7 @@ NOTE: should we return modified attrs in response?
----------

<GetContactsRequest [sortBy="nameAsc|nameDesc"] [sync="1"] [l="{folder-id}"] [derefGroupMember="1"]
[returnHiddenAttrs="1"] [maxMembers="{max-members}"]>
[returnHiddenAttrs="1"] [maxMembers="{max-members}"] [returnCertInfo="1"]>
<a n="..."/>*
<ma n="..."/>*
<cn id="{contact-id}[,{contact-id}...]"/>*
Expand Down Expand Up @@ -2809,10 +2809,24 @@ NOTE: should we return modified attrs in response?
do not return any members under <cn> for the entry.
Instead, return a "tooManyMembers="1" on the <cn>.

{returnCertInfo} : whether to return the certificate information block for the contact. Default is 0

<GetContactsResponse>
<cn [md="{metadata-change-date}"] [tooManyMembers="1"]>...</cn>*
</GetContactsResponse>

Certificate information is returned as <certificate> element
If returnCertInfo is 0, certificate information is not returned
If returnCertInfo is 1, certificate information is returned as shown in the below example -

<GetContactsResponse xmlns="urn:zimbraMail">
<cn id="680" fileAsStr="group1" d="1308612784000" rev="900" l="7">
<a n="nickname">group one</a>
<a n="type">group</a>
<a n="fileAs">8:group1</a>
<certificate>...</certificate>
</cn>
</GetContactsResponse>

Contact group members are returned as <m> elements.
If derefGroupMember is not "1", group members are returned in the ordered they were inserted
Expand Down
6 changes: 4 additions & 2 deletions store/src/java/com/zimbra/cs/service/mail/GetContacts.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ public Element handle(Element request, Map<String, Object> context) throws Servi
maxMembers = request.getAttributeLong(MailConstants.A_MAX_MEMBERS, DEFAULT_MAX_MEMBERS);
}

boolean returnCertInfo = request.getAttributeBool(MailConstants.A_RETURN_CERT_INFO, false);

Element response = zsc.createElement(MailConstants.GET_CONTACTS_RESPONSE);

// want to return modified date only on sync-related requests
Expand Down Expand Up @@ -165,15 +167,15 @@ public Element handle(Element request, Map<String, Object> context) throws Servi
}
ToXML.encodeContact(response, ifmt, octxt, con, contactGroup,
memberAttrs, false, attrs, fields, migratedDlist,
returnHiddenAttrs, maxMembers);
returnHiddenAttrs, maxMembers, returnCertInfo);
}
}
}
} else {
for (Contact con : mbox.getContactList(octxt, folderId, sort)) {
if (con != null) {
ToXML.encodeContact(response, ifmt, octxt, con, null, null,
false, attrs, fields, null, returnHiddenAttrs, maxMembers);
false, attrs, fields, null, returnHiddenAttrs, maxMembers, returnCertInfo);
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions store/src/java/com/zimbra/cs/service/mail/ToXML.java
Original file line number Diff line number Diff line change
Expand Up @@ -720,13 +720,13 @@ public static Element encodeContact(Element parent, ItemIdFormatter ifmt, Operat
boolean summary, Collection<String> attrFilter, int fields)
throws ServiceException {
return encodeContact(parent, ifmt, octxt, contact, null, null, summary,
attrFilter, fields, null, false, GetContacts.NO_LIMIT_MAX_MEMBERS);
attrFilter, fields, null, false, GetContacts.NO_LIMIT_MAX_MEMBERS, true);
}

public static Element encodeContact(Element parent, ItemIdFormatter ifmt, OperationContext octxt, Contact contact,
ContactGroup contactGroup, Collection<String> memberAttrFilter, boolean summary,
Collection<String> attrFilter, int fields, String migratedDlist,
boolean returnHiddenAttrs, long maxMembers)
boolean returnHiddenAttrs, long maxMembers, boolean returnCertInfo)
throws ServiceException {
Element el = parent.addElement(MailConstants.E_CONTACT);
el.addAttribute(MailConstants.A_ID, ifmt.formatItemId(contact));
Expand Down Expand Up @@ -785,7 +785,7 @@ public static Element encodeContact(Element parent, ItemIdFormatter ifmt, Operat
// an existing attribute with null or empty string value?
String value = contact.get(name);
if (!Strings.isNullOrEmpty(value)) {
encodeContactAttr(el, name, value, contact, encodeContactGroupMembersBasic, octxt);
encodeContactAttr(el, name, value, contact, encodeContactGroupMembersBasic, octxt, returnCertInfo);
} else if (attachments != null) {
for (Attachment attach : attachments) {
if (attach.getName().equals(name)) {
Expand Down Expand Up @@ -814,7 +814,7 @@ public static Element encodeContact(Element parent, ItemIdFormatter ifmt, Operat
}

if (name != null && !name.trim().isEmpty() && !Strings.isNullOrEmpty(value)) {
encodeContactAttr(el, name, value, contact, encodeContactGroupMembersBasic, octxt);
encodeContactAttr(el, name, value, contact, encodeContactGroupMembersBasic, octxt, returnCertInfo);
}
}
if (attachments != null) {
Expand All @@ -825,7 +825,7 @@ public static Element encodeContact(Element parent, ItemIdFormatter ifmt, Operat
}

if (migratedDlist != null) {
encodeContactAttr(el, ContactConstants.A_dlist, migratedDlist, contact, false, octxt);
encodeContactAttr(el, ContactConstants.A_dlist, migratedDlist, contact, false, octxt, returnCertInfo);
} else if (contactGroup != null) {
encodeContactGroup(el, contactGroup, memberAttrFilter, ifmt, octxt, summary, fields);
}
Expand All @@ -834,14 +834,14 @@ public static Element encodeContact(Element parent, ItemIdFormatter ifmt, Operat
}

private static void encodeContactAttr(Element elem, String name, String value,
Contact contact, boolean encodeContactGroupMembers, OperationContext octxt) {
Contact contact, boolean encodeContactGroupMembers, OperationContext octxt, boolean returnCertInfo) {
if (Contact.isMultiValueAttr(value)) {
try {
for (String v : Contact.parseMultiValueAttr(value)) {
if (Contact.isUrlField(name)) {
v = DefangFilter.sanitize(v, true);
} else if (Contact.isSMIMECertField(name)) {
encodeCertificate(octxt, elem, name, value, contact.getEmailAddresses());
encodeCertificate(octxt, elem, name, value, contact.getEmailAddresses(), returnCertInfo);
continue;
}
elem.addKeyValuePair(name, v);
Expand All @@ -866,17 +866,17 @@ private static void encodeContactAttr(Element elem, String name, String value,
if (Contact.isUrlField(name)) {
value = DefangFilter.sanitize(value, true);
} else if (Contact.isSMIMECertField(name)) {
encodeCertificate(octxt, elem, name, value, contact.getEmailAddresses());
encodeCertificate(octxt, elem, name, value, contact.getEmailAddresses(), returnCertInfo);
return;
}
elem.addKeyValuePair(name, value);
}
}

private static void encodeCertificate(OperationContext octxt, Element elem, String name, String value, List<String> emailAddresses) {
private static void encodeCertificate(OperationContext octxt, Element elem, String name, String value, List<String> emailAddresses, boolean returnCertInfo) {
Account account = octxt.getAuthenticatedUser();
elem.addKeyValuePair(name, value);
if (SmimeHandler.getHandler() != null) {
if (SmimeHandler.getHandler() != null && returnCertInfo) {
SmimeHandler.getHandler().encodeCertificate(account, elem, value, octxt.getmResponseProtocol(), emailAddresses);
}
}
Expand Down

0 comments on commit 735b240

Please sign in to comment.