diff --git a/core/src/main/java/org/jivesoftware/smack/DirectoryRosterStore.java b/core/src/main/java/org/jivesoftware/smack/DirectoryRosterStore.java index 203b1ebd0..38065bf8e 100644 --- a/core/src/main/java/org/jivesoftware/smack/DirectoryRosterStore.java +++ b/core/src/main/java/org/jivesoftware/smack/DirectoryRosterStore.java @@ -28,7 +28,7 @@ import org.jivesoftware.smack.packet.RosterPacket; import org.jivesoftware.smack.packet.RosterPacket.Item; import org.jivesoftware.smack.util.Base32Encoder; import org.jivesoftware.smack.util.FileUtils; -import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; import org.xmlpull.v1.XmlPullParserFactory; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -189,6 +189,7 @@ public class DirectoryRosterStore implements RosterStore { return null; } + String parserName; String user = null; String name = null; String type = null; @@ -203,15 +204,31 @@ public class DirectoryRosterStore implements RosterStore { boolean done = false; while (!done) { int eventType = parser.next(); + parserName = parser.getName(); if (eventType == XmlPullParser.START_TAG) { - if (parser.getName().equals("item")) { - user = parser.getAttributeValue(null, "user"); - name = parser.getAttributeValue(null, "name"); - type = parser.getAttributeValue(null, "type"); - status = parser.getAttributeValue(null, "status"); + if (parserName.equals("item")) { + user = name = type = status = null; } - if (parser.getName().equals("group")) { - String group = parser.getAttributeValue(null, "name"); + else if (parserName.equals("user")) { + parser.next(); + user = parser.getText(); + } + else if (parserName.equals("name")) { + parser.next(); + name = parser.getText(); + } + else if (parserName.equals("type")) { + parser.next(); + type = parser.getText(); + } + else if (parserName.equals("status")) { + parser.next(); + status = parser.getText(); + } + else if (parserName.equals("group")) { + parser.next(); + parser.next(); + String group = parser.getText(); if (group != null) { groupNames.add(group); } @@ -222,7 +239,7 @@ public class DirectoryRosterStore implements RosterStore { } } else if (eventType == XmlPullParser.END_TAG) { - if (parser.getName().equals("item")) { + if (parserName.equals("item")) { done = true; } } @@ -271,30 +288,20 @@ public class DirectoryRosterStore implements RosterStore { private boolean addEntryRaw (Item item) { - StringBuilder s = new StringBuilder(); - s.append(""); - for (String group : item.getGroupNames()) { - s.append(""); - } - s.append(""); - return FileUtils.writeFile(getBareJidFile(item.getUser()), s.toString()); + xml.closeElement("item"); + + return FileUtils.writeFile(getBareJidFile(item.getUser()), xml.toString()); } diff --git a/core/src/main/java/org/jivesoftware/smack/util/StringUtils.java b/core/src/main/java/org/jivesoftware/smack/util/StringUtils.java index cea2a674f..07cab1082 100644 --- a/core/src/main/java/org/jivesoftware/smack/util/StringUtils.java +++ b/core/src/main/java/org/jivesoftware/smack/util/StringUtils.java @@ -283,17 +283,6 @@ public class StringUtils { return buf.toString(); } - /** - * Returns a string representing a XML attribute. The value parameter is escaped as necessary. In particular, - * white spaces are encoded as character references, such that they are not replaced by ' ' on parsing. - * @param name name of the XML attribute - * @param value value of the XML attribute - */ - public static String xmlAttrib(String name, String value) { - return name + "=\"" + escapeForXML(value, true) + "\""; - } - - /** * Escapes all necessary characters in the String so that it can be used * in an XML doc. @@ -301,11 +290,7 @@ public class StringUtils { * @param string the string to escape. * @return the string with appropriate characters escaped. */ - public static String escapeForXML(String string) { - return escapeForXML(string, false); - } - - public static String escapeForXML(final String string, final boolean escapeWhitespace) { + public static String escapeForXML(final String string) { if (string == null) { return null; } @@ -336,14 +321,6 @@ public class StringUtils { toAppend = APOS_ENCODE; break; default: - // includes \t, \n, \r - if (escapeWhitespace && (ch <= 0x1f || (0x7f <= ch && ch <= 0x9f))) { - StringBuilder sb = new StringBuilder(); - sb.append("&#x"); - sb.append(String.format("%X", (int) ch)); - sb.append(';'); - toAppend = sb; - } break; } if (toAppend != null) { diff --git a/core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java b/core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java new file mode 100644 index 000000000..5ca8538c8 --- /dev/null +++ b/core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java @@ -0,0 +1,133 @@ +/** + * + * Copyright 2014 Florian Schmaus + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smack.util; + +public class XmlStringBuilder implements Appendable, CharSequence { + + private final StringBuilder sb; + + public XmlStringBuilder() { + sb = new StringBuilder(); + } + + /** + * Does nothing if content is null. + * + * @param name + * @param content + * @return + */ + public XmlStringBuilder element(String name, String content) { + if (content == null) + return this; + openElement(name); + escape(content); + closeElement(name); + return this; + } + + public XmlStringBuilder element(String name, Enum content) { + if (content != null) { + element(name, content.name()); + } + return this; + } + + public XmlStringBuilder halfOpenElement(String name) { + sb.append('<').append(name); + return this; + } + + public XmlStringBuilder openElement(String name) { + halfOpenElement(name).append('>'); + return this; + } + + public XmlStringBuilder closeElement(String name) { + sb.append("'); + return this; + } + + public XmlStringBuilder emptyElementClose() { + sb.append("/>"); + return this; + } + + /** + * Does nothing if value is null. + * + * @param name + * @param value + * @return + */ + public XmlStringBuilder attribute(String name, String value) { + if (value == null) + return this; + sb.append(' ').append(name).append("='"); + escape(value); + sb.append('\''); + return this; + } + + public XmlStringBuilder xmlnsAttribute(String value) { + attribute("xmlns", value); + return this; + } + + public XmlStringBuilder escape(String text) { + sb.append(StringUtils.escapeForXML(text)); + return this; + } + + @Override + public XmlStringBuilder append(CharSequence csq) { + sb.append(csq); + return this; + } + + @Override + public XmlStringBuilder append(CharSequence csq, int start, int end) { + sb.append(csq, start, end); + return this; + } + + @Override + public XmlStringBuilder append(char c) { + sb.append(c); + return this; + } + + @Override + public int length() { + return sb.length(); + } + + @Override + public char charAt(int index) { + return sb.charAt(index); + } + + @Override + public CharSequence subSequence(int start, int end) { + return sb.subSequence(start, end); + } + + @Override + public String toString() { + return sb.toString(); + } +}