public StringTableItem GetString(string stringTableValue) { StringTableItem returnValue = null; foreach (string stringTableItem in stringTableValueDictionary.Keys) { if (stringTableValue.Contains(stringTableItem)) { if (returnValue == null || stringTableValue.IndexOf(stringTableItem) < stringTableValue.IndexOf(returnValue.Value) || stringTableItem.Length > returnValue.Value.Length) { returnValue = new StringTableItem(stringTableValueDictionary[stringTableItem], stringTableItem); } } } return(returnValue); }
private void DecodeWBXML(byte[] bytes) { currentTagCodePage = 0; currentAttributeCodePage = 0; bool isAttribute = false; bool tagHasAttributes = false; bool tagHasContent = false; XmlNode activeNode = this; XmlAttribute activeAttribute = null; var byteQueue = new Queue <byte>(bytes); //Get the WBXML version number; versionNumber = (byteQueue.Dequeue() / 10.0) + 1.0; //Get the value of the public identifier publicIdentifier = GetInt(byteQueue); if (publicIdentifier == 0) { //TODO the publicIdentifier is defined as string inside the stringtable int publicIdentifierStringTableIndex = GetInt(byteQueue); } //Get the charset for text encoding textEncoding = IANACharacterSets.GetEncoding(GetInt(byteQueue)); XmlDeclaration declaration = CreateXmlDeclaration("1.0", textEncoding.WebName, null); activeNode.AppendChild(declaration); //Get the string table (use of the string table is not implemented) int stringTableLength = GetInt(byteQueue); if (stringTableLength > 0) { var byteStringTableQueue = new Queue <byte>(); for (int i = 0; i < stringTableLength; i++) { byteStringTableQueue.Enqueue(byteQueue.Dequeue()); } var stringTableList = new List <string>(); while (byteStringTableQueue.Count > 0) { string stringTableItem = GetString(byteStringTableQueue); stringTableList.Add(stringTableItem); } stringTable = new StringTable(stringTableList.ToArray()); } //WBXML body while (byteQueue.Count > 0) { byte byteItem = byteQueue.Dequeue(); if (globalTokens.Contains(byteItem)) { GlobalTokens.Names globalToken = globalTokens.GetToken(byteItem); switch (globalToken) { case GlobalTokens.Names.SWITCH_PAGE: currentTagCodePage = byteQueue.Dequeue(); break; case GlobalTokens.Names.END: if (isAttribute) { isAttribute = false; activeAttribute = null; if (!tagHasContent) { activeNode = activeNode.ParentNode; } } else { activeNode = activeNode.ParentNode; } break; case GlobalTokens.Names.ENTITY: //TODO ENTITY is not implemented yet int entityLength = GetInt(byteQueue); break; case GlobalTokens.Names.STR_I: if (isAttribute) { activeAttribute.InnerText += GetString(byteQueue); } else { activeNode.AppendChild(CreateTextNode(GetString(byteQueue))); } break; case GlobalTokens.Names.LITERAL: case GlobalTokens.Names.LITERAL_A: case GlobalTokens.Names.LITERAL_AC: case GlobalTokens.Names.LITERAL_C: //TODO LITERALs are not implemented yet int literalReference = GetInt(byteQueue); break; case GlobalTokens.Names.EXT_I_0: case GlobalTokens.Names.EXT_I_1: case GlobalTokens.Names.EXT_I_2: //TODO EXT_I_x are not implemented yet string extiString = GetString(byteQueue); break; case GlobalTokens.Names.PI: //TODO PI is not implemented yet var piByteList = new List <byte>(); while (byteQueue.Peek() != (byte)GlobalTokens.Names.END) { piByteList.Add(byteQueue.Dequeue()); } byteQueue.Dequeue(); break; case GlobalTokens.Names.EXT_T_0: case GlobalTokens.Names.EXT_T_1: case GlobalTokens.Names.EXT_T_2: //TODO EXT_T_x are not implemented yet int exttReference = GetInt(byteQueue); break; case GlobalTokens.Names.STR_T: int strtReference = GetInt(byteQueue); if (stringTable.ContainsString(strtReference)) { StringTableItem stringTableItem = stringTable.GetString(strtReference); if (isAttribute) { activeAttribute.InnerText += stringTableItem.Value; } else { activeNode.AppendChild(CreateTextNode(stringTableItem.Value)); } } break; case GlobalTokens.Names.EXT_0: case GlobalTokens.Names.EXT_1: case GlobalTokens.Names.EXT_2: //TODO EXT_x are not implemented yet break; case GlobalTokens.Names.OPAQUE: int opaqueLength = GetInt(byteQueue); byte[] opaqueByteArray = GetByteArray(byteQueue, opaqueLength); var opaqueHexList = new List <string>(); foreach (byte opaqueByteItem in opaqueByteArray) { opaqueHexList.Add(opaqueByteItem.ToString("X2")); } activeNode.InnerText = String.Join("", opaqueHexList.ToArray()); break; } } else if (!isAttribute) { tagHasAttributes = IsBitSet(byteItem, 7); tagHasContent = IsBitSet(byteItem, 6); byteItem &= 127; byteItem &= 63; string tagValue; if (tagCodeSpace.GetCodePage(currentTagCodePage).ContainsTag(byteItem)) { tagValue = tagCodeSpace.GetCodePage(currentTagCodePage).GetTag(byteItem).Name; } else { tagValue = "Tag_" + byteItem.ToString("X2"); } XmlElement xmlElement = CreateElement(tagValue); activeNode.AppendChild(xmlElement); if (tagHasContent || tagHasAttributes) { activeNode = xmlElement; if (tagHasAttributes) { isAttribute = true; } } } else { if (byteItem < 128) { if (attributeCodeSpace.GetCodePage(currentAttributeCodePage).ContainsAttributeStart(byteItem)) { AttributeStart attributeStart = attributeCodeSpace.GetCodePage(currentAttributeCodePage).GetAttributeStart(byteItem); XmlAttribute xmlAttribute = CreateAttribute(attributeStart.Name); xmlAttribute.InnerText = attributeStart.Prefix; activeNode.Attributes.Append(xmlAttribute); activeAttribute = xmlAttribute; } else { XmlAttribute xmlAttribute = CreateAttribute("attribute_" + byteItem.ToString("X2")); activeNode.Attributes.Append(xmlAttribute); activeAttribute = xmlAttribute; } } else { if (attributeCodeSpace.GetCodePage(currentAttributeCodePage).ContainsAttributeValue(byteItem)) { AttributeValue attributeValue = attributeCodeSpace.GetCodePage(currentAttributeCodePage).GetAttributeValue(byteItem); activeAttribute.InnerText += attributeValue.Value; } } } } }
private byte[] EncodeNode(XmlNode node) { var bytesList = new List <byte>(); switch (node.NodeType) { case XmlNodeType.Element: bool hasAttributes = node.Attributes.Count > 0; bool hasContent = node.HasChildNodes; int codePage = tagCodeSpace.ContainsTag(currentTagCodePage, node.Name); if (codePage >= 0) { if (currentTagCodePage != codePage) { bytesList.Add((byte)GlobalTokens.Names.SWITCH_PAGE); bytesList.Add((byte)codePage); currentTagCodePage = codePage; } byte keyValue = tagCodeSpace.GetCodePage(currentTagCodePage).GetTag(node.Name).Token; if (hasAttributes) { keyValue |= 128; } if (hasContent) { keyValue |= 64; } bytesList.Add(keyValue); } else { // TODO: better exception type throw new Exception("Unknown tag: " + node.Name); } if (hasAttributes) { foreach (XmlAttribute attribute in node.Attributes) { bytesList.AddRange(EncodeNode(attribute)); } bytesList.Add((byte)GlobalTokens.Names.END); } if (hasContent) { bytesList.AddRange(EncodeNodes(node.ChildNodes)); bytesList.Add((byte)GlobalTokens.Names.END); } break; case XmlNodeType.Text: bool isOpaqueData = false; if (opaqueDataExpressions.Count > 0) { foreach (OpaqueDataExpression expression in OpaqueDataExpressions) { if (expression.TagName.Equals(node.ParentNode.Name)) { if (node.ParentNode.SelectSingleNode(expression.Expression) != null) { isOpaqueData = true; break; } } } } if (isOpaqueData) { byte[] opaqueDataBytes = GetBytes(node.Value); bytesList.Add((byte)GlobalTokens.Names.OPAQUE); bytesList.AddRange(GetMultiByte(opaqueDataBytes.Length)); bytesList.AddRange(opaqueDataBytes); } else { string textValue = node.Value; while (textValue.Length > 0) { int stringTableIndex = textValue.Length; if (stringTable.ContainsString(textValue)) { StringTableItem stringTableItem = stringTable.GetString(textValue); stringTableIndex = textValue.IndexOf(stringTableItem.Value); if (stringTableIndex == 0) { bytesList.Add((byte)GlobalTokens.Names.STR_T); bytesList.AddRange(GetMultiByte(stringTableItem.Index)); textValue = textValue.Substring(stringTableItem.Value.Length); continue; } } bytesList.Add((byte)GlobalTokens.Names.STR_I); bytesList.AddRange(textEncoding.GetBytes(textValue.Substring(0, stringTableIndex))); bytesList.Add(0); textValue = textValue.Substring(stringTableIndex); } } break; case XmlNodeType.EntityReference: bytesList.Add((byte)GlobalTokens.Names.ENTITY); var reference = (XmlEntityReference)node; foreach (int stringItem in reference.InnerText.ToCharArray()) { bytesList.AddRange(GetMultiByte(stringItem)); } break; case XmlNodeType.Attribute: if (attributeCodeSpace.GetCodePage(currentAttributeCodePage).ContainsAttributeStart(node.Name, node.Value)) { AttributeStart attributeStart = attributeCodeSpace.GetCodePage(currentAttributeCodePage).GetAttributeStart(node.Name, node.Value); bytesList.Add(attributeStart.Token); string postAttributeValue = node.Value.Substring(attributeStart.Prefix.Length); while (postAttributeValue.Length > 0) { int attrValueIndex = postAttributeValue.Length; if ( attributeCodeSpace.GetCodePage(currentAttributeCodePage).ContainsAttributeValue( postAttributeValue)) { AttributeValue attrValue = attributeCodeSpace.GetCodePage(currentAttributeCodePage).GetAttributeValue( postAttributeValue); attrValueIndex = postAttributeValue.IndexOf(attrValue.Value); if (attrValueIndex == 0) { bytesList.Add(attrValue.Token); postAttributeValue = postAttributeValue.Substring(attrValue.Value.Length); continue; } } int stringTableIndex = postAttributeValue.Length; if (stringTable.ContainsString(postAttributeValue)) { StringTableItem stringTableItem = stringTable.GetString(postAttributeValue); stringTableIndex = postAttributeValue.IndexOf(stringTableItem.Value); if (stringTableIndex == 0) { bytesList.Add((byte)GlobalTokens.Names.STR_T); bytesList.AddRange(GetMultiByte(stringTableItem.Index)); postAttributeValue = postAttributeValue.Substring(stringTableItem.Value.Length); continue; } } int firstReferenceIndex = Math.Min(attrValueIndex, stringTableIndex); bytesList.Add((byte)GlobalTokens.Names.STR_I); bytesList.AddRange( textEncoding.GetBytes(postAttributeValue.Substring(0, firstReferenceIndex))); bytesList.Add(0); postAttributeValue = postAttributeValue.Substring(firstReferenceIndex); } } break; } return(bytesList.ToArray()); }