mirror of
https://github.com/moparisthebest/davmail
synced 2024-12-13 03:02:22 -05:00
Carddav: refactor VCard handling to merge with VCalendar code
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1316 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
1344e4c9bd
commit
3725a147c4
@ -2083,7 +2083,7 @@ public abstract class ExchangeSession {
|
||||
result.writeLine("CLASS:PRIVATE");
|
||||
} else if ("PRIVATE".equalsIgnoreCase(eventClass)) {
|
||||
result.writeLine("CLASS:CONFIDENTIAL");
|
||||
} else {
|
||||
} else if (eventClass != null) {
|
||||
result.writeLine("CLASS:" + eventClass);
|
||||
}
|
||||
}
|
||||
@ -2786,9 +2786,8 @@ public abstract class ExchangeSession {
|
||||
Map<String, String> properties = new HashMap<String, String>();
|
||||
properties.put("outlookmessageclass", "IPM.Contact");
|
||||
|
||||
VCardReader reader = new VCardReader(new StringReader(itemBody));
|
||||
VCardReader.Property property;
|
||||
while ((property = reader.readProperty()) != null) {
|
||||
VObject vcard = new VObject(new ICSBufferedReader(new StringReader(itemBody)));
|
||||
for (VProperty property:vcard.getProperties()) {
|
||||
if ("FN".equals(property.getKey())) {
|
||||
properties.put("cn", property.getValue());
|
||||
properties.put("subject", property.getValue());
|
||||
@ -3331,6 +3330,7 @@ public abstract class ExchangeSession {
|
||||
* @param end end date in Exchange zulu format
|
||||
* @param interval freebusy interval in minutes
|
||||
* @return freebusy data or null
|
||||
* @throws IOException on error
|
||||
*/
|
||||
protected abstract String getFreeBusyData(String attendee, String start, String end, int interval) throws IOException;
|
||||
|
||||
|
@ -1,238 +0,0 @@
|
||||
/*
|
||||
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
|
||||
* Copyright (C) 2010 Mickael Guessant
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package davmail.exchange;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* VCARD reader.
|
||||
*/
|
||||
public class VCardReader extends ICSBufferedReader {
|
||||
/**
|
||||
* VCard property
|
||||
*/
|
||||
public static class Property {
|
||||
protected String key;
|
||||
protected Map<String, Set<String>> params;
|
||||
protected List<String> values;
|
||||
|
||||
/**
|
||||
* Property key, without optional parameters (e.g. TEL).
|
||||
*
|
||||
* @return key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property value.
|
||||
*
|
||||
* @return value
|
||||
*/
|
||||
public String getValue() {
|
||||
if (values == null || values.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return values.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Property values.
|
||||
*
|
||||
* @return values
|
||||
*/
|
||||
public List<String> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public boolean hasParam(String paramName, String paramValue) {
|
||||
return params != null && params.containsKey(paramName) && params.get(paramName).contains(paramValue);
|
||||
}
|
||||
|
||||
protected void addParam(String paramName, Set<String> paramValues) {
|
||||
if (params == null) {
|
||||
params = new HashMap<String, Set<String>>();
|
||||
}
|
||||
if (params.get(paramName) == null) {
|
||||
params.put(paramName, paramValues);
|
||||
} else {
|
||||
params.get(paramName).addAll(paramValues);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void addValue(String value) {
|
||||
if (values == null) {
|
||||
values = new ArrayList<String>();
|
||||
}
|
||||
values.add(decodeValue(value));
|
||||
}
|
||||
|
||||
protected String decodeValue(String value) {
|
||||
if (value == null || (value.indexOf('\\') < 0 && value.indexOf(',') < 0)) {
|
||||
return value;
|
||||
} else {
|
||||
// decode value
|
||||
StringBuilder decodedValue = new StringBuilder();
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
char c = value.charAt(i);
|
||||
if (c == '\\') {
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
c = value.charAt(++i);
|
||||
if (c == 'n') {
|
||||
c = '\n';
|
||||
} else if (c == 'r') {
|
||||
c = '\r';
|
||||
}
|
||||
}
|
||||
// iPhone encodes category separator
|
||||
if (c == ',' &&
|
||||
// multivalued properties
|
||||
("N".equals(key) ||
|
||||
"ADR".equals(key) ||
|
||||
"CATEGORIES".equals(key) ||
|
||||
"NICKNAME".equals(key)
|
||||
)) {
|
||||
// convert multiple values to multiline values (e.g. street)
|
||||
c = '\n';
|
||||
}
|
||||
decodedValue.append(c);
|
||||
}
|
||||
return decodedValue.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
int dotIndex = key.indexOf('.');
|
||||
if (dotIndex < 0) {
|
||||
this.key = key;
|
||||
} else {
|
||||
this.key = key.substring(dotIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a VCARD reader on the provided reader
|
||||
*
|
||||
* @param in input reader
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public VCardReader(Reader in) throws IOException {
|
||||
super(in);
|
||||
String firstLine = readLine();
|
||||
if (firstLine == null || !"BEGIN:VCARD".equals(firstLine)) {
|
||||
throw new IOException("Invalid VCard body: " + firstLine);
|
||||
}
|
||||
}
|
||||
|
||||
protected static enum State {
|
||||
KEY, PARAM_NAME, PARAM_VALUE, QUOTED_PARAM_VALUE, VALUE, BACKSLASH
|
||||
}
|
||||
|
||||
public Property readProperty() throws IOException {
|
||||
Property property = null;
|
||||
String line = readLine();
|
||||
if (line != null && !"END:VCARD".equals(line)) {
|
||||
property = new Property();
|
||||
State state = State.KEY;
|
||||
String paramName = null;
|
||||
Set<String> paramValues = null;
|
||||
int startIndex = 0;
|
||||
for (int i = 0; i < line.length(); i++) {
|
||||
char currentChar = line.charAt(i);
|
||||
if (state == State.KEY) {
|
||||
if (currentChar == ':') {
|
||||
property.setKey(line.substring(startIndex, i));
|
||||
state = State.VALUE;
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ';') {
|
||||
property.setKey(line.substring(startIndex, i));
|
||||
state = State.PARAM_NAME;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
} else if (state == State.PARAM_NAME) {
|
||||
if (currentChar == '=') {
|
||||
paramName = line.substring(startIndex, i).toUpperCase();
|
||||
state = State.PARAM_VALUE;
|
||||
paramValues = new HashSet<String>();
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ';') {
|
||||
// param with no value
|
||||
paramName = line.substring(startIndex, i).toUpperCase();
|
||||
property.addParam(paramName, null);
|
||||
state = State.PARAM_NAME;
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ':') {
|
||||
// param with no value
|
||||
paramName = line.substring(startIndex, i).toUpperCase();
|
||||
property.addParam(paramName, null);
|
||||
state = State.VALUE;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
} else if (state == State.PARAM_VALUE) {
|
||||
if (currentChar == '"') {
|
||||
state = State.QUOTED_PARAM_VALUE;
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ':') {
|
||||
if (startIndex < i) {
|
||||
paramValues.add(line.substring(startIndex, i).toLowerCase());
|
||||
}
|
||||
property.addParam(paramName, paramValues);
|
||||
state = State.VALUE;
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ';') {
|
||||
if (startIndex < i) {
|
||||
paramValues.add(line.substring(startIndex, i).toLowerCase());
|
||||
}
|
||||
property.addParam(paramName, paramValues);
|
||||
state = State.PARAM_NAME;
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ',') {
|
||||
if (startIndex < i) {
|
||||
paramValues.add(line.substring(startIndex, i).toLowerCase());
|
||||
}
|
||||
startIndex = i + 1;
|
||||
}
|
||||
} else if (state == State.QUOTED_PARAM_VALUE) {
|
||||
if (currentChar == '"') {
|
||||
state = State.PARAM_VALUE;
|
||||
paramValues.add(line.substring(startIndex, i).toLowerCase());
|
||||
startIndex = i + 1;
|
||||
}
|
||||
} else if (state == State.VALUE) {
|
||||
if (currentChar == '\\') {
|
||||
state = State.BACKSLASH;
|
||||
} else if (currentChar == ';') {
|
||||
property.addValue(line.substring(startIndex, i));
|
||||
startIndex = i + 1;
|
||||
}
|
||||
} else if (state == State.BACKSLASH) {
|
||||
state = State.VALUE;
|
||||
}
|
||||
}
|
||||
property.addValue(line.substring(startIndex));
|
||||
}
|
||||
return property;
|
||||
}
|
||||
}
|
126
src/java/davmail/exchange/VObject.java
Normal file
126
src/java/davmail/exchange/VObject.java
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
|
||||
* Copyright (C) 2010 Mickael Guessant
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package davmail.exchange;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Base class for VCalendar, VTimezone, VEvent.
|
||||
*/
|
||||
public class VObject {
|
||||
/**
|
||||
* VObject properties
|
||||
*/
|
||||
ArrayList<VProperty> properties;
|
||||
/**
|
||||
* Inner VObjects (e.g. VEVENT, VALARM, ...)
|
||||
*/
|
||||
ArrayList<VObject> objects;
|
||||
/**
|
||||
* Object base name (VCALENDAR, VEVENT, VCARD...).
|
||||
*/
|
||||
public String type;
|
||||
|
||||
/**
|
||||
* Create VObject with given type
|
||||
*
|
||||
* @param beginProperty first line property
|
||||
* @param reader stream reader just after the BEGIN:TYPE line
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public VObject(VProperty beginProperty, BufferedReader reader) throws IOException {
|
||||
if (!"BEGIN".equals(beginProperty.getKey())) {
|
||||
throw new IOException("Invalid first line: " + beginProperty);
|
||||
}
|
||||
type = beginProperty.getValue();
|
||||
String endLine = "END:" + type;
|
||||
String line = reader.readLine();
|
||||
while (line != null && !endLine.equals(line)) {
|
||||
handleLine(line, reader);
|
||||
line = reader.readLine();
|
||||
}
|
||||
if (line == null) {
|
||||
throw new IOException("Unexpected end of stream");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create VObject from reader.
|
||||
*
|
||||
* @param reader stream reader just after the BEGIN:TYPE line
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public VObject(BufferedReader reader) throws IOException {
|
||||
this(new VProperty(reader.readLine()), reader);
|
||||
}
|
||||
|
||||
protected void handleLine(String line, BufferedReader reader) throws IOException {
|
||||
VProperty property = new VProperty(line);
|
||||
// inner object
|
||||
if ("BEGIN".equals(property.getKey())) {
|
||||
addObject(new VObject(property, reader));
|
||||
} else {
|
||||
addProperty(property);
|
||||
}
|
||||
}
|
||||
|
||||
protected void addObject(VObject object) {
|
||||
if (objects == null) {
|
||||
objects = new ArrayList<VObject>();
|
||||
}
|
||||
objects.add(object);
|
||||
}
|
||||
|
||||
protected void addProperty(VProperty property) {
|
||||
if (properties == null) {
|
||||
properties = new ArrayList<VProperty>();
|
||||
}
|
||||
properties.add(property);
|
||||
}
|
||||
|
||||
public void writeTo(ICSBufferedWriter writer) {
|
||||
writer.write("BEGIN:");
|
||||
writer.writeLine(type);
|
||||
if (properties != null) {
|
||||
for (VProperty property : properties) {
|
||||
writer.writeLine(property.toString());
|
||||
}
|
||||
}
|
||||
if (objects != null) {
|
||||
for (VObject object : objects) {
|
||||
object.writeTo(writer);
|
||||
}
|
||||
}
|
||||
writer.write("END:");
|
||||
writer.writeLine(type);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
ICSBufferedWriter writer = new ICSBufferedWriter();
|
||||
writeTo(writer);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
public List<VProperty> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
}
|
318
src/java/davmail/exchange/VProperty.java
Normal file
318
src/java/davmail/exchange/VProperty.java
Normal file
@ -0,0 +1,318 @@
|
||||
/*
|
||||
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
|
||||
* Copyright (C) 2010 Mickael Guessant
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package davmail.exchange;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* VCard property
|
||||
*/
|
||||
public class VProperty {
|
||||
protected static enum State {
|
||||
KEY, PARAM_NAME, PARAM_VALUE, QUOTED_PARAM_VALUE, VALUE, BACKSLASH
|
||||
}
|
||||
|
||||
protected class Param {
|
||||
String name;
|
||||
List<String> values;
|
||||
|
||||
public void addAll(List<String> paramValues) {
|
||||
if (values == null) {
|
||||
values = new ArrayList<String>();
|
||||
}
|
||||
values.addAll(paramValues);
|
||||
}
|
||||
}
|
||||
|
||||
protected String key;
|
||||
protected List<Param> params;
|
||||
protected List<String> values;
|
||||
|
||||
/**
|
||||
* Create VProperty from line.
|
||||
*
|
||||
* @param line card line
|
||||
*/
|
||||
public VProperty(String line) {
|
||||
if (line != null && !"END:VCARD".equals(line)) {
|
||||
State state = State.KEY;
|
||||
String paramName = null;
|
||||
List<String> paramValues = null;
|
||||
int startIndex = 0;
|
||||
for (int i = 0; i < line.length(); i++) {
|
||||
char currentChar = line.charAt(i);
|
||||
if (state == State.KEY) {
|
||||
if (currentChar == ':') {
|
||||
setKey(line.substring(startIndex, i));
|
||||
state = State.VALUE;
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ';') {
|
||||
setKey(line.substring(startIndex, i));
|
||||
state = State.PARAM_NAME;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
} else if (state == State.PARAM_NAME) {
|
||||
if (currentChar == '=') {
|
||||
paramName = line.substring(startIndex, i).toUpperCase();
|
||||
state = State.PARAM_VALUE;
|
||||
paramValues = new ArrayList<String>();
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ';') {
|
||||
// param with no value
|
||||
paramName = line.substring(startIndex, i).toUpperCase();
|
||||
addParam(paramName, null);
|
||||
state = State.PARAM_NAME;
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ':') {
|
||||
// param with no value
|
||||
paramName = line.substring(startIndex, i).toUpperCase();
|
||||
addParam(paramName, null);
|
||||
state = State.VALUE;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
} else if (state == State.PARAM_VALUE) {
|
||||
if (currentChar == '"') {
|
||||
state = State.QUOTED_PARAM_VALUE;
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ':') {
|
||||
if (startIndex < i) {
|
||||
paramValues.add(line.substring(startIndex, i));
|
||||
}
|
||||
addParam(paramName, paramValues);
|
||||
state = State.VALUE;
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ';') {
|
||||
if (startIndex < i) {
|
||||
paramValues.add(line.substring(startIndex, i));
|
||||
}
|
||||
addParam(paramName, paramValues);
|
||||
state = State.PARAM_NAME;
|
||||
startIndex = i + 1;
|
||||
} else if (currentChar == ',') {
|
||||
if (startIndex < i) {
|
||||
paramValues.add(line.substring(startIndex, i));
|
||||
}
|
||||
startIndex = i + 1;
|
||||
}
|
||||
} else if (state == State.QUOTED_PARAM_VALUE) {
|
||||
if (currentChar == '"') {
|
||||
state = State.PARAM_VALUE;
|
||||
paramValues.add(line.substring(startIndex, i));
|
||||
startIndex = i + 1;
|
||||
}
|
||||
} else if (state == State.VALUE) {
|
||||
if (currentChar == '\\') {
|
||||
state = State.BACKSLASH;
|
||||
} else if (currentChar == ';') {
|
||||
addValue(line.substring(startIndex, i));
|
||||
startIndex = i + 1;
|
||||
}
|
||||
} else if (state == State.BACKSLASH) {
|
||||
state = State.VALUE;
|
||||
}
|
||||
}
|
||||
addValue(line.substring(startIndex));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Property key, without optional parameters (e.g. TEL).
|
||||
*
|
||||
* @return key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property value.
|
||||
*
|
||||
* @return value
|
||||
*/
|
||||
public String getValue() {
|
||||
if (values == null || values.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return values.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Property values.
|
||||
*
|
||||
* @return values
|
||||
*/
|
||||
public List<String> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the property has a param named paramName with given value.
|
||||
*
|
||||
* @param paramName param name
|
||||
* @param paramValue param value
|
||||
* @return true if property has param name and value
|
||||
*/
|
||||
public boolean hasParam(String paramName, String paramValue) {
|
||||
return params != null && getParam(paramName) != null && containsIgnoreCase(getParam(paramName).values, paramValue);
|
||||
}
|
||||
|
||||
protected boolean containsIgnoreCase(List<String> stringCollection, String value) {
|
||||
for (String collectionValue : stringCollection) {
|
||||
if (value.equalsIgnoreCase(collectionValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void addParam(String paramName, List<String> paramValues) {
|
||||
if (params == null) {
|
||||
params = new ArrayList<Param>();
|
||||
}
|
||||
Param currentParam = getParam(paramName);
|
||||
if (currentParam == null) {
|
||||
currentParam = new Param();
|
||||
currentParam.name = paramName;
|
||||
params.add(currentParam);
|
||||
}
|
||||
currentParam.addAll(paramValues);
|
||||
}
|
||||
|
||||
protected Param getParam(String paramName) {
|
||||
if (params != null) {
|
||||
for (Param param:params) {
|
||||
if (paramName.equals(param.name)) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void addValue(String value) {
|
||||
if (values == null) {
|
||||
values = new ArrayList<String>();
|
||||
}
|
||||
values.add(decodeValue(value));
|
||||
}
|
||||
|
||||
protected String decodeValue(String value) {
|
||||
if (value == null || (value.indexOf('\\') < 0 && value.indexOf(',') < 0)) {
|
||||
return value;
|
||||
} else {
|
||||
// decode value
|
||||
StringBuilder decodedValue = new StringBuilder();
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
char c = value.charAt(i);
|
||||
if (c == '\\') {
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
c = value.charAt(++i);
|
||||
if (c == 'n') {
|
||||
c = '\n';
|
||||
} else if (c == 'r') {
|
||||
c = '\r';
|
||||
}
|
||||
}
|
||||
// iPhone encodes category separator
|
||||
if (c == ',' &&
|
||||
// multivalued properties
|
||||
("N".equals(key) ||
|
||||
"ADR".equals(key) ||
|
||||
"CATEGORIES".equals(key) ||
|
||||
"NICKNAME".equals(key)
|
||||
)) {
|
||||
// convert multiple values to multiline values (e.g. street)
|
||||
c = '\n';
|
||||
}
|
||||
decodedValue.append(c);
|
||||
}
|
||||
return decodedValue.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set property key.
|
||||
*
|
||||
* @param key property key
|
||||
*/
|
||||
public void setKey(String key) {
|
||||
int dotIndex = key.indexOf('.');
|
||||
if (dotIndex < 0) {
|
||||
this.key = key;
|
||||
} else {
|
||||
this.key = key.substring(dotIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(key);
|
||||
if (params != null) {
|
||||
for (Param param : params) {
|
||||
buffer.append(';').append(param.name);
|
||||
if (param.values != null) {
|
||||
buffer.append('=');
|
||||
for (String value : param.values) {
|
||||
appendParamValue(buffer, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer.append(':');
|
||||
if (values != null) {
|
||||
boolean firstValue = true;
|
||||
for (String value : values) {
|
||||
if (firstValue) {
|
||||
firstValue = false;
|
||||
} else {
|
||||
buffer.append(';');
|
||||
}
|
||||
appendMultilineEncodedValue(buffer, value);
|
||||
}
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
protected void appendParamValue(StringBuilder buffer, String value) {
|
||||
if (Math.max(value.indexOf(';'), value.indexOf(',')) >= 0) {
|
||||
buffer.append('"').append(value).append('"');
|
||||
} else {
|
||||
buffer.append(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append and encode \n to \\n in value.
|
||||
*
|
||||
* @param buffer line buffer
|
||||
* @param value value
|
||||
*/
|
||||
protected void appendMultilineEncodedValue(StringBuilder buffer, String value) {
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
char c = value.charAt(i);
|
||||
if (c == '\n') {
|
||||
buffer.append("\\n");
|
||||
} else {
|
||||
buffer.append(value.charAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -258,7 +258,7 @@ public class TestExchangeSessionContact extends AbstractExchangeSessionTestCase
|
||||
|
||||
assertNull(contact.get("private"));
|
||||
|
||||
assertNull(contact.get("haspicture"));
|
||||
assertTrue(contact.get("haspicture") == null || "false".equals(contact.get("haspicture")));
|
||||
|
||||
assertNull(session.getContactPhoto(contact));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user