package com.aionemu.packetsamurai.protocol;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javolution.util.FastList;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import com.aionemu.packetsamurai.PacketSamurai;
import com.aionemu.packetsamurai.Util;
import com.aionemu.packetsamurai.parser.DataStructure;
import com.aionemu.packetsamurai.parser.PartType;
import com.aionemu.packetsamurai.parser.PartTypeManager;
import com.aionemu.packetsamurai.parser.formattree.ForPart;
import com.aionemu.packetsamurai.parser.formattree.Part;
import com.aionemu.packetsamurai.parser.formattree.PartContainer;
import com.aionemu.packetsamurai.parser.formattree.SwitchCaseBlock;
import com.aionemu.packetsamurai.parser.formattree.SwitchPart;
import com.aionemu.packetsamurai.parser.parttypes.RawPartType;
import com.aionemu.packetsamurai.parser.valuereader.Reader;
import com.aionemu.packetsamurai.protocol.protocoltree.PacketFamilly;
import com.aionemu.packetsamurai.protocol.protocoltree.PacketFormat;
import com.aionemu.packetsamurai.protocol.protocoltree.ProtocolNode;
import com.aionemu.packetsamurai.protocol.protocoltree.PacketFamilly.packetDirection;
import com.aionemu.packetsamurai.session.DataPacket;
import com.sun.org.apache.xerces.internal.impl.Constants;
/**
*
* @author Gilles Duboscq
*
*/
public class Protocol
{
private PacketFamilly _serverPackets;
private PacketFamilly _clientPackets;
private int _port; // this can be used to specify a tcp or udp port
private int _sizeBytes; // this is the number of bytes used to specify the size of packets (2 is here as a default value that will be changed if specified)
private int _checksumSize = 0;
private boolean _loaded = false;
private boolean _strictLength = false;
private boolean _analyzerEnabled = true;
private String _encryption;
private String _name;
private String _filename;
private String _packetBufferType = "DefaultPacketBuffer";
private static final Comparator<ProtocolNode> PROTOCOL_NODE_COMPARATOR = new Comparator<ProtocolNode>()
{
public int compare(ProtocolNode o1, ProtocolNode o2)
{
return o1.getID() - o2.getID();
}
};
public Protocol(String pFile)
{
_loaded = false;
_filename = pFile;
loadProtocol(pFile);
}
public Protocol(int sizeBytes, String name, int port, String encryption)
{
_sizeBytes = sizeBytes;
_name = name;
_port = port;
_encryption = encryption;
_clientPackets = new PacketFamilly("ClientPackets");
_clientPackets.setDirection(packetDirection.clientPacket);
_serverPackets = new PacketFamilly("ServerPackets");
_serverPackets.setDirection(packetDirection.serverPacket);
}
public Protocol(int sizeBytes, String name, int port)
{
this(sizeBytes, name, port, "Null");
}
public void saveProtocol(String fileName)
{
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setIgnoringComments(true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
DOMImplementationLS implLS = (DOMImplementationLS) docBuilder.getDOMImplementation();
LSSerializer domWriter = implLS.createLSSerializer();
LSOutput output = implLS.createLSOutput();
domWriter.getDomConfig().setParameter(Constants.DOM_FORMAT_PRETTY_PRINT, Boolean.TRUE);
Element root = doc.createElement("protocol");
root.setAttribute("port", Integer.toString(_port));
root.setAttribute("sizebytes", Integer.toString(_sizeBytes));
root.setAttribute("crypt", _encryption);
root.setAttribute("strictlength", Boolean.toString(_strictLength));
root.setAttribute("name", _name);
root.setAttribute("packetbuffer", _packetBufferType);
root.setAttribute("checksumSize", Integer.toString(_checksumSize));
if(_serverPackets != null)
{
Element serverPacketFamilly = doc.createElement("packetfamilly");
serverPacketFamilly.setAttribute("way","ServerPackets");
serverPacketFamilly.setAttribute("switchtype",_serverPackets.getSwitchType().getName());
// sort elements in family
FastList<ProtocolNode> nodes = new FastList<ProtocolNode>(_serverPackets.getNodes().values());
Collections.sort(nodes, PROTOCOL_NODE_COMPARATOR);
for(ProtocolNode node : nodes)
{
buildDOM(node, serverPacketFamilly, doc);
}
root.appendChild(serverPacketFamilly);
}
else
{
PacketSamurai.getUserInterface().log("Server Packets were not loaded, skipped while saving");
}
if(_clientPackets != null)
{
Element clientPacketFamilly = doc.createElement("packetfamilly");
clientPacketFamilly.setAttribute("way","ClientPackets");
clientPacketFamilly.setAttribute("switchtype",_clientPackets.getSwitchType().getName());
// sort elements in family
FastList<ProtocolNode> nodes = new FastList<ProtocolNode>(_clientPackets.getNodes().values());
Collections.sort(nodes, PROTOCOL_NODE_COMPARATOR);
for(ProtocolNode node : nodes)
{
buildDOM(node, clientPacketFamilly, doc);
}
root.appendChild(clientPacketFamilly);
} else { PacketSamurai.getUserInterface().log("Client Packets were not loaded, skipped while saving"); }
doc.appendChild(root);
OutputStream outputStream = new FileOutputStream(new File(fileName));
output.setByteStream(outputStream);
output.setEncoding("UTF-8");
domWriter.write(doc, output);
outputStream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public PacketFormat getFormat(DataPacket packet, PacketId _packetid)
{
if(packet.getDirection() == packetDirection.serverPacket)
{
if (_serverPackets == null)
return null;
int i = packet.readIntType(_serverPackets.getSwitchType());
if(_checksumSize != 0)
packet.getByteBuffer().position(packet.getByteBuffer().position()+_checksumSize);
_packetid.add(i,_serverPackets.getSwitchType());
ProtocolNode node = _serverPackets.getNodes().get(i);
while(node instanceof PacketFamilly)
{
PacketFamilly familly = (PacketFamilly)node;
i = packet.readIntType(familly.getSwitchType());
_packetid.add(i,familly.getSwitchType());
node = familly.getNodes().get(i);
}
return (PacketFormat)node;
}
else if(packet.getDirection() == packetDirection.clientPacket)
{
int i = packet.readIntType(_clientPackets.getSwitchType());
if(_checksumSize != 0)
packet.getByteBuffer().position(packet.getByteBuffer().position()+_checksumSize);
_packetid.add(i,_clientPackets.getSwitchType());
ProtocolNode node = _clientPackets.getNodes().get(i);
while(node instanceof PacketFamilly)
{
PacketFamilly familly = (PacketFamilly)node;
i = packet.readIntType(familly.getSwitchType());
_packetid.add(i,familly.getSwitchType());
node = familly.getNodes().get(i);
}
return (PacketFormat)node;
}
return null;
}
public PacketFamilly getServerPacketsFamilly()
{
return _serverPackets;
}
public PacketFamilly getClientPacketsFamilly()
{
return _clientPackets;
}
public int getPort()
{
return _port;
}
public int getSizeBytes()
{
return _sizeBytes;
}
public int getChecksumSize()
{
return _checksumSize;
}
public void setPort(int port)
{
_port = port;
}
public void setSizeBytes(int size)
{
_sizeBytes = size;
}
public void setEncryption(String enc)
{
_encryption = enc;
}
public String getEncryption()
{
return _encryption;
}
public boolean isLoaded()
{
return _loaded;
}
public String getName()
{
return _name;
}
public void setName(String name)
{
_name = name;
}
public String getFileName()
{
return _filename;
}
public void saveProtocol()
{
if(_filename == null)
saveProtocol(ProtocolManager.getInstance().getProtocolsDirectory()+"/protocol"+_name+".xml");
else
saveProtocol(_filename);
}
public long getMaxPacketLength()
{
return (long)Math.pow(256, _sizeBytes);
}
public String toString()
{
return "Protocol "+this.getName()+" ("+this.getPort()+")";
}
public String getPacketBufferType()
{
return _packetBufferType;
}
public boolean isStrictLength()
{
return _strictLength;
}
public boolean isAnalyzerEnabled()
{
return _analyzerEnabled;
}
@Deprecated
public List<DataStructure> parseFile(String fileName) throws IOException
{
FileInputStream fis = new FileInputStream(new File(fileName));
List<DataStructure> list = new FastList<DataStructure>();
while(fis.available() > 0)
{
packetDirection dir;
if(fis.read() == 0)
{
dir = packetDirection.clientPacket;
}
else
{
dir = packetDirection.serverPacket;
}
byte[] timeByte = new byte[8];
fis.read(timeByte,0,8);
long time = new BigInteger(timeByte).longValue();
int lengthHi = 0;
int lengthLo = 0;
lengthLo = fis.read();
lengthHi = fis.read();
int length = lengthHi*256 + lengthLo;
byte[] data = new byte [length];
fis.read(data,0,length);
list.add(new DataPacket(data,dir,time, this));
}
return list;
}
private void loadProtocol(String pFile)
{
Document doc = null;
try
{
File file = new File(pFile);
if(!file.exists())
{
_clientPackets = new PacketFamilly("ClientPackets");
_clientPackets.setDirection(packetDirection.clientPacket);
_serverPackets = new PacketFamilly("ServerPackets");
_serverPackets.setDirection(packetDirection.serverPacket);
PacketSamurai.getUserInterface().log("Protocol file didnt exist ("+pFile+"), creating new protocol.");
_filename = null;
return;
}
FileInputStream fis = new FileInputStream(file);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(false);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
docBuilder.setErrorHandler(new XMLErrorHandler());
try
{
doc = docBuilder.parse(fis);
}
catch (SAXParseException e)
{
Protocol.report("ERROR", e);
return;
}
Node root = doc.getDocumentElement();
if(!root.getNodeName().equals("protocol"))
{
PacketSamurai.getUserInterface().log("Error malformed protocol : root node should be called 'protocol'.");
return;
}
NamedNodeMap attr = root.getAttributes();
Node node = attr.getNamedItem("sizebytes");
if(node != null)
{
try
{
_sizeBytes = Integer.parseInt(node.getNodeValue());
}
catch(NumberFormatException nfe)
{
PacketSamurai.getUserInterface().log("Warning: The sizebyte attribute of protocol must be an integer. Couldnt read the attribute provided, falling back to the default value");
_sizeBytes = 2 ;
}
}
else
{
_sizeBytes = 2 ;
}
node = attr.getNamedItem("port");
if(node != null)
{
try
{
_port = Integer.parseInt(node.getNodeValue());
}
catch(NumberFormatException nfe)
{
PacketSamurai.getUserInterface().log("Warning: The port attribute of protocol must be an integer. Couldnt read the attribute provided");
}
}
node = attr.getNamedItem("crypt");
if(node != null)
{
_encryption = node.getNodeValue();
}
else
{
_encryption = "Null";
}
node = attr.getNamedItem("strictlength");
if(node != null)
{
_strictLength = Boolean.parseBoolean(node.getNodeValue());
}
node = attr.getNamedItem("analyzerEnabled");
if(node != null)
{
_analyzerEnabled = Boolean.parseBoolean(node.getNodeValue());
}
node = attr.getNamedItem("packetbuffer");
if(node != null)
{
_packetBufferType = node.getNodeValue();
}
node = attr.getNamedItem("checksumSize");
if(node != null)
{
_checksumSize = Integer.parseInt(node.getNodeValue());
}
node = attr.getNamedItem("name");
if(node != null)
{
_name = node.getNodeValue();
}
else
{
PacketSamurai.getUserInterface().log("Error while loading "+pFile+" : protocol has no 'name' attribute");
return;
}
for (Node n = root.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("packetfamilly".equalsIgnoreCase(n.getNodeName()))
{
PacketFamilly familly = parseFamilly(n, true);
if(familly != null)
{
switch(familly.getDirection())
{
case clientPacket:
_clientPackets = familly;
//set a default name if necessary
if(_clientPackets.getName() == null)
_clientPackets.setName("ClientPackets");
//Main.getInstance().log("Client Familly Ok");
break;
case serverPacket:
_serverPackets = familly;
// set a default name if necessary
if(_serverPackets.getName() == null)
_serverPackets.setName("ServerPackets");
//Main.getInstance().log("Server Familly Ok");
break;
default:
PacketSamurai.getUserInterface().log("Error packetfamilly doesnt have a valid way");
}
}
else
{
PacketSamurai.getUserInterface().log("Error packetfamilly returned is null there was an error");
}
}
}
_loaded = true;
}
catch (Exception e)
{
PacketSamurai.getUserInterface().log("Error while parsing protocol "+pFile);
e.printStackTrace();
}
}
private PacketFamilly parseFamilly(Node n, boolean isRoot)
{
PacketFamilly newFamilly;
NamedNodeMap attrs = n.getAttributes();
Node atr;
if(isRoot)
{
newFamilly = new PacketFamilly();
}
else
{
atr = attrs.getNamedItem("id");
if(atr == null)
{
PacketSamurai.getUserInterface().log("Error, packetfamilly is not root and has no id. skipping it:");
return null;
}
newFamilly = new PacketFamilly(Integer.decode(atr.getNodeValue()));
}
//-------
atr = attrs.getNamedItem("way");
if(atr == null)
{
if(isRoot)
{
PacketSamurai.getUserInterface().log("Error, Root packetfamilly doesnt have 'way'. skipping it");
return null;
}
}
else
{
String way = atr.getNodeValue();
if(way.equals("ServerPackets"))
{
newFamilly.setDirection(packetDirection.serverPacket);
}
else if(way.equals("ClientPackets"))
{
newFamilly.setDirection(packetDirection.clientPacket);
}
}
//--------
atr = attrs.getNamedItem("switchtype");
if(atr == null)
{
PacketSamurai.getUserInterface().log("Error, packetfamilly doesnt have 'switchtype'. skipping it");
return null;
}
PartType idPart = PartTypeManager.getInstance().getType(atr.getNodeValue());
newFamilly.setSwitchType(idPart);
newFamilly.addIdPartAtEnd(idPart);
atr = attrs.getNamedItem("name");
if(atr != null)
{
newFamilly.setName(atr.getNodeValue());
}
for (Node o = n.getFirstChild(); o != null; o = o.getNextSibling())
{
if ("packet".equalsIgnoreCase(o.getNodeName()))
{
PacketFormat format = parseFormat(o);
if(format != null)
{
format.addIdPartsAtBegining(newFamilly.getIdParts(),newFamilly.getIDs());
newFamilly.addNode(format);
}
}
else if ("packetfamilly".equalsIgnoreCase(o.getNodeName()))
{
PacketFamilly familly = parseFamilly(o, false);
if(familly != null)
{
familly.addIdPartsAtBegining(newFamilly.getIdParts(),newFamilly.getIDs());
newFamilly.addNode(familly);
}
}
}
return newFamilly;
}
private PacketFormat parseFormat(Node n)
{
PacketFormat newFormat;
NamedNodeMap attrs = n.getAttributes();
Node atr;
atr = attrs.getNamedItem("id");
if(atr == null)
{
PacketSamurai.getUserInterface().log("Error, packet doesnt have 'id'. skipping it");
return null;
}
int id = Integer.decode(atr.getNodeValue());
String name;
atr = attrs.getNamedItem("name");
if(atr == null)
{
PacketSamurai.getUserInterface().log("Warning, packet doesnt have 'name'");
name = "";
}
else
{
name = atr.getNodeValue();
}
newFormat = new PacketFormat(id, name);
newFormat.setContainingProtocol(this);
boolean parseRet = false;
try
{
parseRet = parseParts(n, newFormat.getDataFormat().getMainBlock());
}
catch (IllegalStateException e)
{
PacketSamurai.getUserInterface().log("Error: parsing format: "+newFormat.toString()+" - Details: "+e.getMessage());
}
if (!parseRet)
{
return null;
}
return newFormat;
}
private boolean parseParts(Node n, PartContainer pc)
{
NamedNodeMap attrs;
Node atr;
for (Node o = n.getFirstChild(); o != null; o = o.getNextSibling())
{
if ("part".equalsIgnoreCase(o.getNodeName()))
{
Part pp = parsePart(o, pc);
if(pp == null)
return false;
pc.addPart(pp);
}
else if ("for".equalsIgnoreCase(o.getNodeName()))
{
attrs = o.getAttributes();
int forId;
atr = attrs.getNamedItem("id");
if(atr == null)
{
PacketSamurai.getUserInterface().log("Error, for doesnt have 'id'. skipping packet");
return false;
}
forId = Integer.parseInt(atr.getNodeValue());
atr = attrs.getNamedItem("analyzername");
String analyzerName = "";
if (atr != null)
{
analyzerName = atr.getNodeValue();
}
ForPart newForPart = new ForPart(forId, analyzerName);
newForPart.setParentContainer(pc);
newForPart.setContainingFormat(pc.getContainingFormat());
if(parseParts(o, newForPart.getModelBlock()))
{
pc.addPart(newForPart);
}
else
{
return false;
}
}
else if("switch".equalsIgnoreCase(o.getNodeName()))
{
attrs = o.getAttributes();
int switchId;
atr = attrs.getNamedItem("id");
if(atr == null)
{
PacketSamurai.getUserInterface().log("Error, switch doesnt have 'id'. skipping packet");
return false;
}
switchId = Integer.parseInt(atr.getNodeValue());
atr = attrs.getNamedItem("analyzername");
String analyzerName = "";
if (atr != null)
{
analyzerName = atr.getNodeValue();
}
SwitchPart newSwitchBlock = new SwitchPart(switchId, analyzerName);
newSwitchBlock.setParentContainer(pc);
newSwitchBlock.setContainingFormat(pc.getContainingFormat());
for(Node caseNode = o.getFirstChild(); caseNode != null; caseNode = caseNode.getNextSibling())
{
if("case".equalsIgnoreCase(caseNode.getNodeName()))
{
attrs = caseNode.getAttributes();
String comment = null;
atr = attrs.getNamedItem("comment");
if(atr != null)
{
comment = atr.getNodeValue();
}
atr = attrs.getNamedItem("analyzername");
analyzerName = "";
if (atr != null)
{
analyzerName = atr.getNodeValue();
}
atr = attrs.getNamedItem("id");
if(atr == null)
{
PacketSamurai.getUserInterface().log("Error, case doesnt have 'id'. skipping packet");
return false;
}
SwitchCaseBlock newSwitchCase = null;
if(atr.getNodeValue().equalsIgnoreCase("default"))
{
newSwitchCase = new SwitchCaseBlock(newSwitchBlock, analyzerName);
}
else
{
int caseId;
try
{
caseId = Integer.decode(atr.getNodeValue());
newSwitchCase = new SwitchCaseBlock(newSwitchBlock, caseId, analyzerName);
}
catch (NumberFormatException e)
{
PacketSamurai.getUserInterface().log("Warning, case doesnt have a valid 'id'. making it default");
newSwitchCase = new SwitchCaseBlock(newSwitchBlock, analyzerName);
}
}
if(comment != null)
newSwitchCase.setComment(comment);
newSwitchCase.setParentContainer(pc);
newSwitchCase.setContainingFormat(pc.getContainingFormat());
if(parseParts(caseNode, newSwitchCase))
{
newSwitchBlock.addCase(newSwitchCase);
}
else
{
return false;
}
}
}
pc.addPart(newSwitchBlock);
}
}
return true;
}
private Part parsePart(Node n, PartContainer pc)
{
String partName;
NamedNodeMap attrs = n.getAttributes();
Node atr = attrs.getNamedItem("name");
if(atr == null)
{
PacketSamurai.getUserInterface().log("Warning, part doesnt have 'name'");
partName = "";
}
else
{
partName = atr.getNodeValue();
}
int partId;
atr = attrs.getNamedItem("id");
if(atr == null)
{
partId = -1;
}
else
{
try
{
partId = Integer.parseInt(atr.getNodeValue());
}
catch(NumberFormatException nfe)
{
PacketSamurai.getUserInterface().log("Warning: parts id must be an integer");
partId = -1;
}
}
atr = attrs.getNamedItem("type");
if(atr == null)
{
PacketSamurai.getUserInterface().log("Error, part doesnt have 'type'. skipping packet");
return null;
}
String type = atr.getNodeValue();
int size = 0;
int sizeid = -1;
boolean dynBSize = false;
atr = attrs.getNamedItem("size");
if(atr != null)
{
size = Integer.decode(atr.getNodeValue());
}
else
{
atr = attrs.getNamedItem("sizeid");
if(atr != null)
{
sizeid = Integer.parseInt(atr.getNodeValue());
dynBSize = true;
}
}
Reader r = null;
String partComment = null;
for (Node subNode = n.getFirstChild(); subNode != null; subNode = subNode.getNextSibling())
{
if ("comment".equals(subNode.getNodeName()))
{
if(partComment != null)
{
PacketSamurai.getUserInterface().log("Warning, part '"+(partName)+"' has mutiple comments");
}
partComment = subNode.getTextContent();
}
if ("reader".equals(subNode.getNodeName()))
{
if(r != null)
PacketSamurai.getUserInterface().log("Warning, part '"+(partName)+"' has mutiple readers");
NamedNodeMap attrs2 = subNode.getAttributes();
atr = attrs2.getNamedItem("type");
if(atr == null)
{
PacketSamurai.getUserInterface().log("Warning, part '"+(partName)+"' has a reader with no type");
continue;
}
//try default package
Class<?> clazz = null;
try
{
clazz = Class.forName("com.aionemu.packetsamurai.parser.valuereader."+atr.getNodeValue()+"Reader");
}
catch (DOMException e)
{
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
}
if (clazz == null)
{
PacketSamurai.getUserInterface().log("Warning, part '"+(partName)+"' reader's could not be found in either parser or custom packages");
continue;
}
try
{
r = (Reader) clazz.newInstance();
if(!r.loadReaderFromXML(subNode)) //drop reader if loading went wrong
r = null;
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
}
if(partComment == null)
partComment = "";
String partLookUpType;
atr = attrs.getNamedItem("lookuptype");
if(atr == null)
{
partLookUpType = "";
}
else
{
partLookUpType = atr.getNodeValue();
}
String partAnalyzerName;
atr = attrs.getNamedItem("analyzername");
if (atr == null)
{
partAnalyzerName = "";
}
else
{
partAnalyzerName = atr.getNodeValue();
}
Part pp = new Part(PartTypeManager.getInstance().getType(type), partId, partName, partComment, partLookUpType, partAnalyzerName);
if (dynBSize)
{
pp.setBSizeId(sizeid);
pp.setDynamicBSize(true);
}
else
{
pp.setBSize(size);
pp.setDynamicBSize(false);
}
pp.setReader(r);
return pp;
}
private void processParts(List<Part> parts, Element newNode, Document document)
{
for(Part part : parts)
{
Element partNode;
if(part instanceof ForPart)
{
ForPart block = (ForPart)part;
partNode = document.createElement("for");
partNode.setAttribute("id",String.valueOf(block.getForId()));
processParts(block.getModelBlock().getParts(), partNode, document);
}
else if(part instanceof SwitchPart)
{
SwitchPart block = (SwitchPart) part;
partNode = document.createElement("switch");
partNode.setAttribute("id",String.valueOf(block.getSwitchId()));
for(SwitchCaseBlock sCase : block.getCases(true))
{
Element caseNode = document.createElement("case");
if(sCase.isDefault())
caseNode.setAttribute("id", "default");
else
caseNode.setAttribute("id", Integer.toString(sCase.getSwitchCase()));
processParts(sCase.getParts(), caseNode, document);
partNode.appendChild(caseNode);
}
}
else
{
partNode = document.createElement("part");
partNode.setAttribute("type",part.getType().getName());
if(part.getId() != -1)
partNode.setAttribute("id",String.valueOf(part.getId()));
if(part.getName() != null && part.getName().length() > 0)
partNode.setAttribute("name",part.getName());
if(part.getComment() != null && part.getComment().length() > 0)
partNode.setAttribute("comment",part.getComment());
if(part.getAnalyzerName() != null && part.getAnalyzerName().length() > 0)
partNode.setAttribute("analyzername", part.getLookUpType());
if(part.getType() instanceof RawPartType)
{
if(part.isDynamicBSize())
partNode.setAttribute("sizeid", String.valueOf(part.getBSizeId()));
else if(part.getBSize() != 0)
partNode.setAttribute("size", String.valueOf(part.getBSize()));
}
Reader reader = part.getReader();
if(reader !=null)
{
Element readerNode = document.createElement("reader");
readerNode.setAttribute("type", Util.getReaderName(reader.getClass()) );
reader.saveReaderToXML(readerNode, document);
partNode.appendChild(readerNode);
}
}
newNode.appendChild(partNode);
}
}
private void buildDOM(ProtocolNode node, Element packetFamilly, Document document)
{
if(node instanceof PacketFormat)
{
PacketFormat format = (PacketFormat)node;
Element newNode = document.createElement("packet");
newNode.setAttribute("id","0x"+Integer.toHexString(format.getID()));
newNode.setAttribute("name",format.getName());
processParts(format.getDataFormat().getMainBlock().getParts(), newNode, document);
packetFamilly.appendChild(newNode);
}
else if(node instanceof PacketFamilly)
{
PacketFamilly familly = (PacketFamilly)node;
Element newNode = document.createElement("packetfamilly");
newNode.setAttribute("switchtype",familly.getSwitchType().getName());
newNode.setAttribute("id","0x"+Integer.toHexString(familly.getID()));
// sort elements in family
FastList<ProtocolNode> nodes = new FastList<ProtocolNode>(familly.getNodes().values());
Collections.sort(nodes, PROTOCOL_NODE_COMPARATOR);
for(ProtocolNode pnode : nodes)
{
buildDOM(pnode, newNode, document);
}
packetFamilly.appendChild(newNode);
}
}
public static void report(String severity, SAXParseException e)
{
PacketSamurai.getUserInterface().log(severity+": "+e.getMessage()+" (Line "+e.getLineNumber()+", Column: "+e.getColumnNumber()+")");
}
class XMLErrorHandler implements ErrorHandler
{
public void error(SAXParseException e) throws SAXException
{
Protocol.report("Error", e);
}
public void fatalError(SAXParseException e) throws SAXException
{
Protocol.report("Fatal", e);
}
public void warning(SAXParseException e) throws SAXException
{
Protocol.report("Warning", e);
}
}
}