Fixes history corrupting records when they contain utf chars < 0x20, reported on the maiinglist by Danny van Heumen. Adds tests to reproduce this case.

ice4sip 5097
Damian Minkov 12 years ago
parent 7959e53827
commit 8ef362f081

@ -334,6 +334,14 @@ public void purgeLocallyStoredHistory(HistoryID id)
} }
} }
/**
* Clears locally(in memory) cached histories.
*/
public void purgeLocallyCachedHistories()
{
histories.clear();
}
/** /**
* Checks the ids of the parent, do they exist in the supplied history ids. * Checks the ids of the parent, do they exist in the supplied history ids.
* If it exist the history is sub history of the on with the supplied ids. * If it exist the history is sub history of the on with the supplied ids.

@ -20,6 +20,8 @@
import org.jitsi.util.xml.XMLUtils; import org.jitsi.util.xml.XMLUtils;
import org.w3c.dom.*; import org.w3c.dom.*;
import com.google.common.xml.*;
/** /**
* @author Alexander Pelov * @author Alexander Pelov
*/ */
@ -122,13 +124,17 @@ private void addRecord(String[] propertyNames,
{ {
if (propertyValues[i] != null) if (propertyValues[i] != null)
{ {
propertyName = propertyName.replaceFirst(CDATA_SUFFIX, ""); propertyName =
propertyName.replaceFirst(CDATA_SUFFIX, "");
Element propertyElement = this.currentDoc Element propertyElement = this.currentDoc
.createElement(propertyName); .createElement(propertyName);
Text value = this.currentDoc Text value = this.currentDoc
.createCDATASection(propertyValues[i].replaceAll("\0", " ")); .createCDATASection(
XmlEscapers.xmlContentEscaper().escape(
propertyValues[i].replaceAll("\0", " ")
));
propertyElement.appendChild(value); propertyElement.appendChild(value);
elem.appendChild(propertyElement); elem.appendChild(propertyElement);
@ -142,7 +148,10 @@ private void addRecord(String[] propertyNames,
.createElement(propertyName); .createElement(propertyName);
Text value = this.currentDoc Text value = this.currentDoc
.createTextNode(propertyValues[i].replaceAll("\0", " ")); .createTextNode(
XmlEscapers.xmlContentEscaper().escape(
propertyValues[i].replaceAll("\0", " ")
));
propertyElement.appendChild(value); propertyElement.appendChild(value);
elem.appendChild(propertyElement); elem.appendChild(propertyElement);
@ -217,8 +226,8 @@ private void createNewDoc(Date date, boolean loadLastFile)
} }
/** /**
* Updates a record by searching for record with idProperty which have idValue * Updates a record by searching for record with idProperty which have
* and updating/creating the property with newValue. * idValue and updating/creating the property with newValue.
* *
* @param idProperty name of the id property * @param idProperty name of the id property
* @param idValue value of the id property * @param idValue value of the id property

@ -10,6 +10,8 @@ Import-Package: org.osgi.framework,
org.jitsi.util.xml, org.jitsi.util.xml,
net.java.sip.communicator.service.history, net.java.sip.communicator.service.history,
net.java.sip.communicator.service.history.records, net.java.sip.communicator.service.history.records,
com.google.common.escape,
com.google.common.xml,
org.w3c.dom, org.w3c.dom,
org.xml.sax, org.xml.sax,
javax.xml.parsers, javax.xml.parsers,

@ -79,7 +79,7 @@ public History createHistory(HistoryID id, HistoryRecordStructure recordStructur
throws IllegalArgumentException, IOException; throws IllegalArgumentException, IOException;
/** /**
* Permamently removes local stored History * Permanently removes local stored History
* *
* @param id HistoryID * @param id HistoryID
* @throws IOException * @throws IOException
@ -87,6 +87,12 @@ public History createHistory(HistoryID id, HistoryRecordStructure recordStructur
*/ */
public void purgeLocallyStoredHistory(HistoryID id) throws IOException; public void purgeLocallyStoredHistory(HistoryID id) throws IOException;
/**
* Clears locally(in memory) cached histories.
*/
public void purgeLocallyCachedHistories();
/** /**
* Moves the content of oldId history to the content of the newId. * Moves the content of oldId history to the content of the newId.
* *

@ -11,6 +11,7 @@
import junit.framework.*; import junit.framework.*;
import net.java.sip.communicator.impl.protocol.mock.*; import net.java.sip.communicator.impl.protocol.mock.*;
import net.java.sip.communicator.service.contactlist.*; import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.history.*;
import net.java.sip.communicator.service.msghistory.*; import net.java.sip.communicator.service.msghistory.*;
import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.service.protocol.event.*;
@ -18,6 +19,8 @@
import org.osgi.framework.*; import org.osgi.framework.*;
import com.google.common.xml.*;
/** /**
* Tests message history. * Tests message history.
* First installs the MoxkProtocolProvider to be able to send some messages * First installs the MoxkProtocolProvider to be able to send some messages
@ -53,6 +56,8 @@ public class TestMsgHistoryService
private static ServiceReference msgHistoryServiceRef = null; private static ServiceReference msgHistoryServiceRef = null;
public static MessageHistoryService msgHistoryService = null; public static MessageHistoryService msgHistoryService = null;
public static HistoryService historyService = null;
private static MockContact testContact = null; private static MockContact testContact = null;
private static ServiceReference metaCLref = null; private static ServiceReference metaCLref = null;
@ -138,6 +143,14 @@ public void setupContact()
(MessageHistoryService)MsgHistoryServiceLick.bc. (MessageHistoryService)MsgHistoryServiceLick.bc.
getService(msgHistoryServiceRef); getService(msgHistoryServiceRef);
ServiceReference historyServiceRef =
MsgHistoryServiceLick.bc.
getServiceReference(HistoryService.class.getName());
historyService =
(HistoryService)MsgHistoryServiceLick.bc.
getService(historyServiceRef);
// fill in a contact to comunicate with // fill in a contact to comunicate with
MockContactGroup root = MockContactGroup root =
(MockContactGroup)mockPresOpSet.getServerStoredContactListRoot(); (MockContactGroup)mockPresOpSet.getServerStoredContactListRoot();
@ -180,7 +193,8 @@ public void setupContact()
mockBImOpSet.createMessage("test message word2" + Math.random()), mockBImOpSet.createMessage("test message word2" + Math.random()),
mockBImOpSet.createMessage("test message word3" + Math.random()), mockBImOpSet.createMessage("test message word3" + Math.random()),
mockBImOpSet.createMessage("test message word4" + Math.random()), mockBImOpSet.createMessage("test message word4" + Math.random()),
mockBImOpSet.createMessage("test message word5" + Math.random()) mockBImOpSet.createMessage("test message word5" + Math.random()),
mockBImOpSet.createMessage("Hello \u0002World\u0002!")
}; };
} }
@ -380,6 +394,38 @@ public void readRecords()
msgs.contains(messagesToSend[2].getContent())); msgs.contains(messagesToSend[2].getContent()));
} }
/**
* Tests some special chars insert and read.
*/
public void specialChars()
{
mockBImOpSet.deliverMessage(TEST_CONTACT_NAME_1, messagesToSend[5]);
waitWrite(500);
historyService.purgeLocallyCachedHistories();
/**
* Must return exactly the last 3 messages
*/
Collection<EventObject> rs
= msgHistoryService.findLast(testMetaContact, 3);
assertTrue("Nothing found 8", !rs.isEmpty());
List<String> msgs = getMessages(rs);
assertEquals("Messages must be 3", 3, msgs.size());
assertTrue("Message no found",
msgs.contains(messagesToSend[3].getContent()));
assertTrue("Message no found",
msgs.contains(messagesToSend[4].getContent()));
// For now we are stripping in history the special content chars
// in order to avoid breaking the history records in the xml
assertTrue("Message no found",
msgs.contains(XmlEscapers.xmlContentEscaper().escape(
messagesToSend[5].getContent())));
}
private static void waitWrite(long timeout) private static void waitWrite(long timeout)
{ {
synchronized (lock) synchronized (lock)

@ -13,6 +13,8 @@ Import-Package: junit.framework,
net.java.sip.communicator.impl.protocol.mock, net.java.sip.communicator.impl.protocol.mock,
net.java.sip.communicator.service.protocol, net.java.sip.communicator.service.protocol,
net.java.sip.communicator.service.protocol.event,org.jitsi.service.protocol.event, net.java.sip.communicator.service.protocol.event,org.jitsi.service.protocol.event,
com.google.common.xml,
com.google.common.escape,
org.osgi.framework, org.osgi.framework,
org.w3c.dom, org.w3c.dom,
javax.xml.parsers, javax.xml.parsers,

Loading…
Cancel
Save