diff --git a/OpenMetaverse/Helpers.cs b/OpenMetaverse/Helpers.cs
index 07d0e3b7..f0b1bbf0 100644
--- a/OpenMetaverse/Helpers.cs
+++ b/OpenMetaverse/Helpers.cs
@@ -527,69 +527,5 @@ namespace OpenMetaverse
uint fixedState = (((byte)state & ATTACHMENT_MASK) >> 4) | (((byte)state & ~ATTACHMENT_MASK) << 4);
return (AttachmentPoint)fixedState;
}
-
- ///
- /// Parse a packet into human readable formatted key/value pairs
- ///
- /// the Packet to parse
- /// A string containing the packet block name, and key/value pairs of the data fields
- public static string PacketToString(Packet packet)
- {
- StringBuilder result = new StringBuilder();
-
- foreach(FieldInfo packetField in packet.GetType().GetFields())
- {
- object packetDataObject = packetField.GetValue(packet);
-
- result.AppendFormat("-- {0} --" + System.Environment.NewLine, packetField.Name);
- result.AppendFormat("-- {0} --" + System.Environment.NewLine, packet.Type);
- foreach(FieldInfo packetValueField in packetField.GetValue(packet).GetType().GetFields())
- {
- result.AppendFormat("{0}: {1}" + System.Environment.NewLine,
- packetValueField.Name, packetValueField.GetValue(packetDataObject));
- }
-
- // handle blocks that are arrays
- if (packetDataObject.GetType().IsArray)
- {
- foreach (object nestedArrayRecord in packetDataObject as Array)
- {
- foreach (FieldInfo packetArrayField in nestedArrayRecord.GetType().GetFields())
- {
- result.AppendFormat("{0} {1}" + System.Environment.NewLine,
- packetArrayField.Name, packetArrayField.GetValue(nestedArrayRecord));
- }
- }
- }
- else
- {
- // handle non array data blocks
- foreach (PropertyInfo packetPropertyField in packetField.GetValue(packet).GetType().GetProperties())
- {
- // Handle fields named "Data" specifically, this is generally binary data, we'll display it as hex values
- if (packetPropertyField.PropertyType.Equals(typeof(System.Byte[]))
- && packetPropertyField.Name.Equals("Data"))
- {
- result.AppendFormat("{0}: {1}" + System.Environment.NewLine,
- packetPropertyField.Name,
- Utils.BytesToHexString((byte[])packetPropertyField.GetValue(packetDataObject, null), packetPropertyField.Name));
- }
- // decode bytes into strings
- else if (packetPropertyField.PropertyType.Equals(typeof(System.Byte[])))
- {
- result.AppendFormat("{0}: {1}" + System.Environment.NewLine,
- packetPropertyField.Name,
- Utils.BytesToString((byte[])packetPropertyField.GetValue(packetDataObject, null)));
- }
- else
- {
- result.AppendFormat("{0}: {1}" + System.Environment.NewLine,
- packetPropertyField.Name, packetPropertyField.GetValue(packetDataObject, null));
- }
- }
- }
- }
- return result.ToString();
- }
}
}
diff --git a/OpenMetaverse/ObjectManager.cs b/OpenMetaverse/ObjectManager.cs
index 149ad38f..9f3afac6 100644
--- a/OpenMetaverse/ObjectManager.cs
+++ b/OpenMetaverse/ObjectManager.cs
@@ -57,6 +57,7 @@ namespace OpenMetaverse
[Flags]
public enum CompressedFlags : uint
{
+ None = 0x00,
/// Unknown
ScratchPad = 0x01,
/// Whether the object has a TreeSpecies
@@ -1351,7 +1352,7 @@ namespace OpenMetaverse
{
ObjectUpdatePacket update = (ObjectUpdatePacket)packet;
UpdateDilation(simulator, update.RegionData.TimeDilation);
-
+
for (int b = 0; b < update.ObjectData.Length; b++)
{
ObjectUpdatePacket.ObjectDataBlock block = update.ObjectData[b];
diff --git a/OpenMetaverse/PacketDecoder.cs b/OpenMetaverse/PacketDecoder.cs
new file mode 100644
index 00000000..4b65b770
--- /dev/null
+++ b/OpenMetaverse/PacketDecoder.cs
@@ -0,0 +1,1346 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+
+namespace OpenMetaverse.Packets
+{
+
+ public class PacketDecoder
+ {
+ ///
+ /// A custom decoder callback
+ ///
+ /// The key of the object
+ /// the data to decode
+ /// A string represending the fieldData
+ public delegate string CustomPacketDecoder(string fieldName, object fieldData);
+
+ private static Dictionary> Callbacks = new Dictionary>();
+
+ public PacketDecoder()
+ {
+ AddCallback("Color", DecodeColorField);
+ AddCallback("TextColor", DecodeColorField);
+ AddCallback("Timestamp", DecodeTimeStamp);
+ AddCallback("EstateCovenantReply.Data.CovenantTimestamp", DecodeTimeStamp);
+ AddCallback("CreationDate", DecodeTimeStamp);
+ AddCallback("BinaryBucket", DecodeBinaryBucket);
+ AddCallback("ParcelData.Data", DecodeParcelData);
+ AddCallback("LayerData.Data", DecodeParcelData);
+ AddCallback("ImageData.Data", DecodeImageData);
+ AddCallback("ObjectData.TextureEntry", DecodeTextureEntry);
+ AddCallback("ImprovedInstantMessage.MessageBlock.Dialog", DecodeDialog);
+
+ // Inventory/Permissions
+ AddCallback("BaseMask", DecodePermissionMask);
+ AddCallback("OwnerMask", DecodePermissionMask);
+ AddCallback("EveryoneMask", DecodePermissionMask);
+ AddCallback("NextOwnerMask", DecodePermissionMask);
+ AddCallback("GroupMask", DecodePermissionMask);
+
+ AddCallback("WearableType", DecodeWearableType);
+ AddCallback("InventoryData.Type", DecodeInventoryType);
+ AddCallback("InventoryData.InvType", DecodeInventoryInvType);
+ AddCallback("InventoryData.Flags", DecodeInventoryFlags);
+ AddCallback("SaleType", DecodeObjectSaleType);
+
+ AddCallback("Name", DecodeGenericByteArrayToFormattedString);
+ AddCallback("Description", DecodeGenericByteArrayToFormattedString);
+
+ AddCallback("ScriptControlChange.Data.Controls", DecodeScriptControls);
+
+ AddCallback("RegionFlags", DecodeRegionFlags);
+ AddCallback("SimAccess", DecodeSimAccess);
+ AddCallback("ControlFlags", DecodeControlFlags);
+
+ // ViewerEffect TypeData
+ AddCallback("ViewerEffect.Effect.TypeData", DecodeViewerEffectTypeData);
+ AddCallback("ViewerEffect.Effect.Type", DecodeViewerEffectType);
+
+ // Prim/ObjectUpdate decoders
+ AddCallback("ObjectUpdate.ObjectData.PCode", DecodeObjectPCode);
+ AddCallback("ObjectUpdate.ObjectData.Material", DecodeObjectMaterial);
+ AddCallback("ObjectUpdate.ObjectData.ClickAction", DecodeObjectClickAction);
+ AddCallback("ObjectData.UpdateFlags", DecodeObjectUpdateFlags);
+
+ AddCallback("ObjectUpdate.ObjectData.ObjectData", DecodeObjectData);
+ AddCallback("TextureAnim", DecodeObjectTextureAnim);
+ AddCallback("ObjectUpdate.ObjectData.NameValue", DecodeNameValue);
+ AddCallback("ObjectUpdate.ObjectData.Data", DecodeObjectData);
+
+ AddCallback("ObjectUpdate.ObjectData.Text", DecodeGenericByteArrayToFormattedString);
+ AddCallback("ObjectUpdate.ObjectData.MediaURL", DecodeGenericByteArrayToFormattedString);
+ AddCallback("ObjectUpdate.ObjectData.PSBlock", DecodeObjectParticleSystem);
+ AddCallback("ParticleSys", DecodeObjectParticleSystem);
+ AddCallback("ObjectUpdate.ObjectData.ExtraParams", DecodeObjectExtraParams);
+
+ AddCallback("ImprovedTerseObjectUpdate.ObjectData.Data", DecodeTerseUpdate);
+ AddCallback("ImprovedTerseObjectUpdate.ObjectData.TextureEntry", DecodeTerseTextureEntry);
+
+ AddCallback("ObjectUpdateCompressed.ObjectData.Data", DecodeObjectCompressedData);
+
+ // ChatFromSimulator
+ AddCallback("ChatData.SourceType", DecodeChatSourceType);
+ AddCallback("ChatData.ChatType", DecodeChatChatType);
+ AddCallback("ChatData.Audible", DecodeChatAudible);
+ AddCallback("AttachedSound.DataBlock.Flags", DecodeAttachedSoundFlags);
+
+ AddCallback("RequestImage.Type", DecodeImageType);
+ }
+
+ ///
+ /// Add a custom decoder callback
+ ///
+ /// The key of the field to decode
+ /// The custom decode handler
+ public void AddCallback(string key, CustomPacketDecoder customPacketHandler)
+ {
+ if (Callbacks.ContainsKey(key))
+ {
+ lock (Callbacks)
+ Callbacks[key].Add(customPacketHandler);
+ }
+ else
+ {
+ lock (Callbacks)
+ Callbacks.Add(key, new List() { customPacketHandler });
+ }
+ }
+
+ ///
+ /// Remove a custom decoder callback
+ ///
+ /// The key of the field to decode
+ /// The custom decode handler
+ public void RemoveCustomHandler(string key, CustomPacketDecoder customPacketHandler)
+ {
+ if (Callbacks.ContainsKey(key))
+ lock (Callbacks)
+ {
+ if (Callbacks[key].Contains(customPacketHandler))
+ Callbacks[key].Remove(customPacketHandler);
+ }
+ }
+
+ #region Custom Decoders
+
+ private static string DecodeTerseUpdate(string fieldName, object fieldData)
+ {
+ byte[] block = (byte[]) fieldData;
+ int i = 4;
+
+ StringBuilder result = new StringBuilder();
+
+ // LocalID
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "LocalID",
+ Utils.BytesToUInt(block, 0),
+ "Uint32");
+
+
+
+ // State
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "State",
+ block[i++],
+ "Byte");
+
+ // Avatar boolean
+ bool isAvatar = (block[i++] != 0);
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "IsAvatar",
+ isAvatar,
+ "Boolean");
+
+ // Collision normal for avatar
+ if (isAvatar)
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "CollisionPlane",
+ new Vector4(block, i),
+ "Vector4");
+
+ i += 16;
+ }
+
+ // Position
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Position",
+ new Vector3(block, i),
+ "Vector3");
+ i += 12;
+
+ // Velocity
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Velocity",
+ new Vector3(
+ Utils.UInt16ToFloat(block, i, -128.0f, 128.0f),
+ Utils.UInt16ToFloat(block, i + 2, -128.0f, 128.0f),
+ Utils.UInt16ToFloat(block, i + 4, -128.0f, 128.0f)),
+ "Vector3");
+ i += 6;
+
+ // Acceleration
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Acceleration",
+ new Vector3(
+ Utils.UInt16ToFloat(block, i, -64.0f, 64.0f),
+ Utils.UInt16ToFloat(block, i + 2, -64.0f, 64.0f),
+ Utils.UInt16ToFloat(block, i + 4, -64.0f, 64.0f)),
+ "Vector3");
+
+ i += 6;
+ // Rotation (theta)
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Rotation",
+ new Quaternion(
+ Utils.UInt16ToFloat(block, i, -1.0f, 1.0f),
+ Utils.UInt16ToFloat(block, i + 2, -1.0f, 1.0f),
+ Utils.UInt16ToFloat(block, i + 4, -1.0f, 1.0f),
+ Utils.UInt16ToFloat(block, i + 6, -1.0f, 1.0f)),
+ "Quaternion");
+ i += 8;
+ // Angular velocity (omega)
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "AngularVelocity",
+ new Vector3(
+ Utils.UInt16ToFloat(block, i, -64.0f, 64.0f),
+ Utils.UInt16ToFloat(block, i + 2, -64.0f, 64.0f),
+ Utils.UInt16ToFloat(block, i + 4, -64.0f, 64.0f)),
+ "Vector3");
+ //pos += 6;
+ // TODO: What is in these 6 bytes?
+ return result.ToString();
+ }
+
+ private static string DecodeObjectCompressedData(string fieldName, object fieldData)
+ {
+ StringBuilder result = new StringBuilder();
+ byte[] block = (byte[])fieldData;
+ int i = 0;
+
+ // UUID
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ID",
+ new UUID(block, 0),
+ "UUID");
+ i += 16;
+
+ // Local ID
+ uint LocalID = (uint)(block[i++] + (block[i++] << 8) +
+ (block[i++] << 16) + (block[i++] << 24));
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "LocalID",
+ LocalID,
+ "Uint32");
+ // PCode
+ PCode pcode = (PCode)block[i++];
+
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
+ "PCode",
+ (int)pcode,
+ "(" + pcode + ")",
+ "PCode");
+
+ // State
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "State",
+ block[i++],
+ "Byte");
+
+ // TODO: CRC
+
+ i += 4;
+ // Material
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
+ "Material",
+ block[i],
+ "(" + (Material)block[i++] + ")",
+ "Material");
+
+ // Click action
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
+ "ClickAction",
+ block[i],
+ "(" + (ClickAction)block[i++] + ")",
+ "ClickAction");
+
+ // Scale
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Scale",
+ new Vector3(block, i),
+ "Vector3");
+ i += 12;
+
+ // Position
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Position",
+ new Vector3(block, i),
+ "Vector3");
+ i += 12;
+
+ // Rotation
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Rotation",
+ new Vector3(block, i),
+ "Vector3");
+
+ i += 12;
+ // Compressed flags
+ CompressedFlags flags = (CompressedFlags)Utils.BytesToUInt(block, i);
+ result.AppendFormat("{0,30}: {1,-10} {2,-29} [{3}]" + Environment.NewLine,
+ "CompressedFlags",
+ Utils.BytesToUInt(block, i),
+ "(" + (CompressedFlags)Utils.BytesToUInt(block, i) + ")",
+ "UInt");
+ i += 4;
+
+ // Owners ID
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "OwnerID",
+ new UUID(block, i),
+ "UUID");
+ i += 16;
+
+ // Angular velocity
+ if ((flags & CompressedFlags.HasAngularVelocity) != 0)
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "AngularVelocity",
+ new Vector3(block, i),
+ "Vector3");
+ i += 12;
+ }
+
+ // Parent ID
+ if ((flags & CompressedFlags.HasParent) != 0)
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ParentID",
+ (uint)(block[i++] + (block[i++] << 8) +
+ (block[i++] << 16) + (block[i++] << 24)),
+ "UInt");
+ }
+
+ // Tree data
+ if ((flags & CompressedFlags.Tree) != 0)
+ {
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
+ "TreeSpecies",
+ block[i++],
+ "(" + (Tree)block[i] + ")",
+ "Tree");
+ }
+
+ // Scratch pad
+ else if ((flags & CompressedFlags.ScratchPad) != 0)
+ {
+ int size = block[i++];
+ byte[] scratch = new byte[size];
+ Buffer.BlockCopy(block, i, scratch, 0, size);
+ result.AppendFormat("{0,30}: {1,-40} [ScratchPad[]]" + Environment.NewLine,
+ "ScratchPad",
+ Utils.BytesToHexString(scratch, String.Format("{0,30}", "Data")));
+ i += size;
+ }
+
+ // Floating text
+ if ((flags & CompressedFlags.HasText) != 0)
+ {
+ string text = String.Empty;
+ while (block[i] != 0)
+ {
+ text += (char)block[i];
+ i++;
+ }
+ i++;
+
+ // Floating text
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Text",
+ text,
+ "string");
+
+ // Text color
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "TextColor",
+ new Color4(block, i, false),
+ "Color4");
+ i += 4;
+ }
+
+ // Media URL
+ if ((flags & CompressedFlags.MediaURL) != 0)
+ {
+ string text = String.Empty;
+ while (block[i] != 0)
+ {
+ text += (char)block[i];
+ i++;
+ }
+ i++;
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "MediaURL",
+ text,
+ "string");
+ }
+
+ // Particle system
+ if ((flags & CompressedFlags.HasParticles) != 0)
+ {
+ Primitive.ParticleSystem p = new Primitive.ParticleSystem(block, i);
+ result.AppendLine(DecodeObjectParticleSystem("ParticleSystem", p));
+ i += 86;
+ }
+
+ // Extra parameters TODO:
+ Primitive prim = new Primitive();
+ i += prim.SetExtraParamsFromBytes(block, i);
+
+ //Sound data
+ if ((flags & CompressedFlags.HasSound) != 0)
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "SoundID",
+ new UUID(block, i),
+ "UUID");
+ i += 16;
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "SoundGain",
+ Utils.BytesToFloat(block, i),
+ "Float");
+ i += 4;
+
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
+ "SoundFlags",
+ block[i++],
+ "(" + (SoundFlags)block[i] + ")",
+ "SoundFlags");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "SoundRadius",
+ Utils.BytesToFloat(block, i),
+ "Float");
+ i += 4;
+ }
+
+ // Name values
+ if ((flags & CompressedFlags.HasNameValues) != 0)
+ {
+ string text = String.Empty;
+ while (block[i] != 0)
+ {
+ text += (char)block[i];
+ i++;
+ }
+ i++;
+
+ // Parse the name values
+ if (text.Length > 0)
+ {
+ string[] lines = text.Split('\n');
+ NameValue[] nameValues = new NameValue[lines.Length];
+
+ for (int j = 0; j < lines.Length; j++)
+ {
+ if (!String.IsNullOrEmpty(lines[j]))
+ {
+ NameValue nv = new NameValue(lines[j]);
+ nameValues[j] = nv;
+ }
+ }
+ DecodeNameValue("NameValues", nameValues);
+ }
+ }
+
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
+ "PathCurve",
+ block[i],
+ "(" + (PathCurve)block[i++] + ")",
+ "PathCurve");
+
+ ushort pathBegin = Utils.BytesToUInt16(block, i);
+ i += 2;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathBegin",
+ Primitive.UnpackBeginCut(pathBegin),
+ "float");
+
+ ushort pathEnd = Utils.BytesToUInt16(block, i);
+ i += 2;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathEnd",
+ Primitive.UnpackEndCut(pathEnd),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathScaleX",
+ Primitive.UnpackPathScale(block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathScaleY",
+ Primitive.UnpackPathScale(block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathShearX",
+ Primitive.UnpackPathShear((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathShearY",
+ Primitive.UnpackPathShear((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathTwist",
+ Primitive.UnpackPathTwist((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathTwistBegin",
+ Primitive.UnpackPathTwist((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathRadiusOffset",
+ Primitive.UnpackPathTwist((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathTaperX",
+ Primitive.UnpackPathTaper((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathTaperY",
+ Primitive.UnpackPathTaper((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathRevolutions",
+ Primitive.UnpackPathRevolutions(block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathSkew",
+ Primitive.UnpackPathTwist((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ProfileCurve",
+ block[i++],
+ "float");
+
+ ushort profileBegin = Utils.BytesToUInt16(block, i);
+ i += 2;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ProfileBegin",
+ Primitive.UnpackBeginCut(profileBegin),
+ "float");
+
+ ushort profileEnd = Utils.BytesToUInt16(block, i);
+ i += 2;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ProfileEnd",
+ Primitive.UnpackEndCut(profileEnd),
+ "float");
+
+ ushort profileHollow = Utils.BytesToUInt16(block, i);
+ i += 2;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ProfileHollow",
+ Primitive.UnpackProfileHollow(profileHollow),
+ "float");
+
+ int textureEntryLength = (int)Utils.BytesToUInt(block, i);
+ i += 4;
+ //prim.Textures = new Primitive.TextureEntry(block, i, textureEntryLength);
+ String s = DecodeTextureEntry("TextureEntry", new Primitive.TextureEntry(block, i, textureEntryLength));
+ result.AppendLine(s);
+ i += textureEntryLength;
+
+ // Texture animation
+ if ((flags & CompressedFlags.TextureAnimation) != 0)
+ {
+ i += 4;
+ string a = DecodeObjectTextureAnim("TextureAnimation", new Primitive.TextureAnimation(block, i));
+ result.AppendLine(a);
+ }
+
+ return result.ToString();
+ }
+
+ private static string DecodeObjectData(string fieldName, object fieldData)
+ {
+ byte[] data = (byte[])fieldData;
+ if (data.Length == 1)
+ {
+ return String.Format("{0,30}: {1,2} {2,-38} [{3}]",
+ fieldName + " (Tree Species)",
+ fieldData,
+ "(" + (Tree)(byte)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+ else if (data.Length == 60)
+ {
+ /* TODO: these are likely useful packed fields,
+ * need to unpack them */
+ return Utils.BytesToHexString((byte[])fieldData, String.Format("{0,30}", fieldName));
+ }
+ else
+ {
+ return Utils.BytesToHexString((byte[])fieldData, String.Format("{0,30}", fieldName));
+ }
+ }
+
+ private static string DecodeObjectTextureAnim(string fieldName, object fieldData)
+ {
+ StringBuilder result = new StringBuilder();
+ Primitive.TextureAnimation TextureAnim;
+ if (fieldData is Primitive.TextureAnimation)
+ TextureAnim = (Primitive.TextureAnimation)fieldData;
+ else
+ TextureAnim = new Primitive.TextureAnimation((byte[])fieldData, 0);
+
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ GenericTypeDecoder(TextureAnim, ref result);
+ result.AppendFormat("{0,30}", "");
+
+ return result.ToString();
+
+ }
+ private static string DecodeGenericByteArrayToFormattedString(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-40} [Byte[]]", fieldName, Utils.BytesToString((byte[])fieldData));
+ }
+
+ private static string DecodeNameValue(string fieldName, object fieldData)
+ {
+ string nameValue = Utils.BytesToString((byte[])fieldData);
+ NameValue[] nameValues = null;
+ if (nameValue.Length > 0)
+ {
+ string[] lines = nameValue.Split('\n');
+ nameValues = new NameValue[lines.Length];
+
+ for (int i = 0; i < lines.Length; i++)
+ {
+ if (!String.IsNullOrEmpty(lines[i]))
+ {
+ NameValue nv = new NameValue(lines[i]);
+ nameValues[i] = nv;
+ }
+ }
+ }
+
+ StringBuilder result = new StringBuilder();
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ if (nameValues != null)
+ {
+ for (int i = 0; i < nameValues.Length; i++)
+ {
+ result.AppendFormat(
+ "{0,30}: Name={1} Value={2} Class={3} Type={4} Sendto={5}" + Environment.NewLine, "NameValue",
+ nameValues[i].Name, nameValues[i].Value, nameValues[i].Class, nameValues[i].Type, nameValues[i].Sendto);
+ }
+ }
+ result.AppendFormat("{0,30}", "");
+ return result.ToString();
+ }
+
+ private static string DecodeObjectExtraParams(string fieldName, object fieldData)
+ {
+
+ byte[] data = (byte[])fieldData;
+
+ int i = 0;
+ //int totalLength = 1;
+
+ Primitive.FlexibleData Flexible = null;
+ Primitive.LightData Light = null;
+ Primitive.SculptData Sculpt = null;
+
+ byte extraParamCount = data[i++];
+
+ for (int k = 0; k < extraParamCount; k++)
+ {
+ ExtraParamType type = (ExtraParamType)Utils.BytesToUInt16(data, i);
+ i += 2;
+
+ uint paramLength = Utils.BytesToUInt(data, i);
+ i += 4;
+
+ if (type == ExtraParamType.Flexible)
+ Flexible = new Primitive.FlexibleData(data, i);
+ else if (type == ExtraParamType.Light)
+ Light = new Primitive.LightData(data, i);
+ else if (type == ExtraParamType.Sculpt)
+ Sculpt = new Primitive.SculptData(data, i);
+
+ i += (int)paramLength;
+ //totalLength += (int)paramLength + 6;
+ }
+
+ StringBuilder result = new StringBuilder();
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ if (Flexible != null)
+ {
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(Flexible, ref result);
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ }
+
+ if (Sculpt != null)
+ {
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(Sculpt, ref result);
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ }
+
+ if (Light != null)
+ {
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(Light, ref result);
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ }
+
+ result.AppendFormat("{0,30}", "");
+ return result.ToString();
+ }
+
+ private static string DecodeObjectParticleSystem(string fieldName, object fieldData)
+ {
+ StringBuilder result = new StringBuilder();
+ Primitive.ParticleSystem ParticleSys;
+ if (fieldData is Primitive.ParticleSystem)
+ ParticleSys = (Primitive.ParticleSystem)fieldData;
+ else
+ ParticleSys = new Primitive.ParticleSystem((byte[])fieldData, 0);
+
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(ParticleSys, ref result);
+ result.AppendFormat("{0,30}", "");
+
+ return result.ToString();
+ }
+
+ private static void GenericTypeDecoder(object obj, ref StringBuilder result)
+ {
+ FieldInfo[] fields = obj.GetType().GetFields();
+
+ foreach (FieldInfo field in fields)
+ {
+ String special;
+ if (SpecialDecoder("a" + "." + "b" + "." + field.Name,
+ field.GetValue(obj), out special))
+ {
+ result.AppendLine(special);
+ }
+ else
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + System.Environment.NewLine, field.Name,
+ field.GetValue(obj), field.FieldType.Name);
+ }
+ }
+ }
+
+ private static string DecodeObjectPCode(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,2} {2,-38} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + (PCode)(byte)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeImageType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + (ImageType)(byte)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeImageCodec(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + (ImageCodec)(byte)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeObjectMaterial(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + (Material)(byte)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeObjectClickAction(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + (ClickAction)(byte)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeObjectUpdateFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + (PrimFlags)(uint)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeScriptControls(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [AgentManager.ControlFlags]",
+ fieldName,
+ (uint)fieldData,
+ "(" + (AgentManager.ControlFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeColorField(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-40} [Color4]",
+ fieldName,
+ fieldData.GetType().Name.Equals("Color4") ? (Color4)fieldData : new Color4((byte[])fieldData, 0, false));
+ }
+
+ private static string DecodeTimeStamp(string fieldName, object fieldData)
+ {
+ if (fieldData is Int32 && (int)fieldData > 0)
+ return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + Utils.UnixTimeToDateTime((int)fieldData) + ")",
+ fieldData.GetType().Name);
+ else if (fieldData is uint && (uint)fieldData > 0)
+ return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + Utils.UnixTimeToDateTime((uint)fieldData) + ")",
+ fieldData.GetType().Name);
+ else
+ return String.Format("{0,30}: {1,-40} [{2}]",
+ fieldName,
+ fieldData,
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeBinaryBucket(string fieldName, object fieldData)
+ {
+ byte[] bytes = (byte[])fieldData;
+ string bucket = String.Empty;
+ if (bytes.Length == 1)
+ {
+ bucket = String.Format("{0}", bytes[0]);
+ }
+ else if (bytes.Length == 17)
+ {
+ bucket = String.Format("{0} {1,-40} ({2}) [Byte[]]",
+ new UUID(bytes, 1),
+ bytes[0],
+ (AssetType)bytes[0]);
+ }
+ else
+ {
+ bucket = Utils.BytesToString(bytes);
+ }
+ return String.Format("{0,30}: {1,-40} [Byte[]]", fieldName, bucket);
+ }
+
+ private static string DecodeParcelData(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}",
+ Utils.BytesToHexString((byte[])fieldData,
+ String.Format("{0,30}", fieldName)));
+ }
+
+ private static string DecodeWearableType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30} {1,-2} {2,-38} [WearableType]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (WearableType)fieldData + ")");
+ }
+
+ private static string DecodeInventoryType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [AssetType]",
+ fieldName,
+ (sbyte)fieldData,
+ "(" + (AssetType)(sbyte)fieldData + ")");
+ }
+
+ private static string DecodeInventoryInvType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [InventoryType]",
+ fieldName,
+ (sbyte)fieldData,
+ "(" + (InventoryType)fieldData + ")");
+ }
+
+ private static string DecodeInventoryFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [FixMe]",
+ fieldName,
+ fieldData,
+ "(" + fieldData + ")");
+ }
+
+ private static string DecodeObjectSaleType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [SaleType]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (SaleType)fieldData + ")");
+ }
+
+ private static string DecodeRegionFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [RegionFlags]",
+ fieldName,
+ fieldData,
+ "(" + (RegionFlags)(uint)fieldData + ")",
+ fieldData.GetType().Name);
+
+ }
+
+ private static string DecodeSimAccess(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [SimAccess]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (SimAccess)fieldData + ")");
+ }
+
+ private static string DecodeAttachedSoundFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [SoundFlags]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (SoundFlags)fieldData + ")");
+ }
+
+
+ private static string DecodeChatSourceType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [SourceType]",
+ fieldName,
+ fieldData,
+ "(" + (SourceType)(byte)fieldData + ")");
+ }
+
+ private static string DecodeChatChatType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [ChatType]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (ChatType)fieldData + ")");
+ }
+
+ private static string DecodeChatAudible(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-38} [ChatAudibleLevel]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (ChatAudibleLevel)(byte)fieldData + ")");
+ }
+
+ private static string DecodeImageData(string fieldName, object fieldData)
+ {
+ return String.Format("{0,10}",
+ Utils.BytesToHexString((byte[])fieldData,
+ String.Format("{0,30}", fieldName)));
+ }
+
+ private string DecodeTerseTextureEntry(string fieldName, object fieldData)
+ {
+ byte[] block = (byte[]) fieldData;
+
+ Primitive.TextureEntry te = new Primitive.TextureEntry(block, 4, block.Length - 4);
+
+ StringBuilder result = new StringBuilder();
+
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ if (te.DefaultTexture != null)
+ {
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ GenericFieldsDecoder(te.DefaultTexture, ref result);
+ GenericPropertiesDecoder(te.DefaultTexture, ref result);
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ }
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ for (int i = 0; i < te.FaceTextures.Length; i++)
+ {
+ if (te.FaceTextures[i] != null)
+ {
+ result.AppendFormat("{0,30}[{1}]" + Environment.NewLine, "FaceTexture", i);
+ GenericFieldsDecoder(te.FaceTextures[i], ref result);
+ GenericPropertiesDecoder(te.FaceTextures[i], ref result);
+ }
+ }
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ result.AppendFormat("{0,30}", "");
+
+ return result.ToString();
+ }
+
+ private static string DecodeTextureEntry(string fieldName, object fieldData)
+ {
+ Primitive.TextureEntry te;
+ if (fieldData is Primitive.TextureEntry)
+ te = (Primitive.TextureEntry)fieldData;
+ else
+ {
+ byte[] tebytes = (byte[])fieldData;
+ te = new Primitive.TextureEntry(tebytes, 0, tebytes.Length);
+ }
+
+ StringBuilder result = new StringBuilder();
+
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ if (te.DefaultTexture != null)
+ {
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ GenericFieldsDecoder(te.DefaultTexture, ref result);
+ GenericPropertiesDecoder(te.DefaultTexture, ref result);
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ }
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ for (int i = 0; i < te.FaceTextures.Length; i++)
+ {
+ if (te.FaceTextures[i] != null)
+ {
+ result.AppendFormat("{0,30}[{1}]" + Environment.NewLine, "FaceTexture", i);
+ GenericFieldsDecoder(te.FaceTextures[i], ref result);
+ GenericPropertiesDecoder(te.FaceTextures[i], ref result);
+ }
+ }
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ result.AppendFormat("{0,30}", "");
+
+ return result.ToString();
+ }
+
+ private static void GenericFieldsDecoder(object obj, ref StringBuilder result)
+ {
+ Type parcelType = obj.GetType();
+ FieldInfo[] fields = parcelType.GetFields();
+ foreach (FieldInfo field in fields)
+ {
+ String special;
+ if (SpecialDecoder("a" + "." + "b" + "." + field.Name,
+ field.GetValue(obj), out special))
+ {
+ result.AppendLine(special);
+ }
+ else
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ field.Name,
+ field.GetValue(obj),
+ field.FieldType.Name);
+ }
+ }
+ }
+
+ private static void GenericPropertiesDecoder(object obj, ref StringBuilder result)
+ {
+ Type parcelType = obj.GetType();
+ PropertyInfo[] propertyInfos = parcelType.GetProperties();
+ foreach (PropertyInfo property in propertyInfos)
+ {
+ String special;
+ if (SpecialDecoder("a" + "." + "b" + "." + property.Name,
+ property.GetValue(obj, null), out special))
+ {
+ result.AppendLine(special);
+ }
+ else
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ property.Name,
+ property.GetValue(obj, null),
+ property.PropertyType.Name);
+ }
+ }
+ }
+
+ private static string DecodeDialog(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [{3}]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (InstantMessageDialog)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeControlFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + (AgentManager.ControlFlags)(uint)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodePermissionMask(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
+ fieldName,
+ (uint)fieldData,
+ "(" + (PermissionMask)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ public static string DecodeViewerEffectTypeData(string fieldName, object fieldData)
+ {
+ byte[] data = (byte[])fieldData;
+ StringBuilder sb = new StringBuilder();
+ if (data.Length == 56 || data.Length == 57)
+ {
+ UUID sourceAvatar = new UUID(data, 0);
+ UUID targetObject = new UUID(data, 16);
+ Vector3d targetPos = new Vector3d(data, 32);
+ sb.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine, fieldName, "Source AvatarID=" + sourceAvatar);
+ sb.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine, fieldName, "Target ObjectID=" + targetObject);
+
+
+ float lx, ly;
+ Helpers.GlobalPosToRegionHandle((float)targetPos.X, (float)targetPos.Y, out lx, out ly);
+
+ sb.AppendFormat("{0,30}: {1,-40} [Vector3d]", fieldName, targetPos);
+
+ if (data.Length == 57)
+ {
+ sb.AppendLine();
+ sb.AppendFormat("{0,30}: {1,-17} {2,-22} [Byte]", fieldName, "Point At Type=" + data[56],
+ "(" + (PointAtType)data[56] + ")");
+ }
+
+ return sb.ToString();
+ }
+ else
+ {
+ return String.Format("{0,30}: (No Decoder) Length={1}" + System.Environment.NewLine, fieldName, data.Length) + Utils.BytesToHexString(data, String.Format("{0,30}", ""));
+ }
+ }
+
+ public static string DecodeViewerEffectType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + (EffectType)(byte)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+ #endregion
+
+ ///
+ /// Creates a formatted string containing the values of a Packet
+ ///
+ /// The Packet
+ /// A formatted string of values of the nested items in the Packet object
+ /// should be made generic enough to decode IMessage objects too.
+ public string PacketToString(Packet packet)
+ {
+ StringBuilder result = new StringBuilder();
+
+ result.AppendFormat("Packet Type: {0}" + System.Environment.NewLine, packet.Type);
+ result.AppendLine("[Packet Header]");
+ // payload
+ result.AppendFormat("Sequence: {0}" + System.Environment.NewLine, packet.Header.Sequence);
+ result.AppendFormat(" Options: {0}" + System.Environment.NewLine, InterpretOptions(packet.Header));
+ result.AppendLine();
+
+ result.AppendLine("[Packet Payload]");
+
+ FieldInfo[] fields = packet.GetType().GetFields();
+
+ for (int i = 0; i < fields.Length; i++)
+ {
+ if (fields[i].Name == "Type" || fields[i].Name == "Header")
+ continue;
+
+ if (fields[i].FieldType.IsArray)
+ {
+ result.AppendFormat("{0,30} []" + Environment.NewLine, "-- " + fields[i].Name + " --");
+ RecursePacketArray(fields[i], packet, ref result);
+ }
+ else
+ {
+ result.AppendFormat("{0,30}" + Environment.NewLine, "-- " + fields[i].Name + " --");
+ RecursePacketField(fields[i], packet, ref result);
+ }
+ }
+ return result.ToString();
+ }
+
+ private static string InterpretOptions(Header header)
+ {
+ return "["
+ + (header.AppendedAcks ? "Ack" : " ")
+ + " "
+ + (header.Resent ? "Res" : " ")
+ + " "
+ + (header.Reliable ? "Rel" : " ")
+ + " "
+ + (header.Zerocoded ? "Zer" : " ")
+ + "]"
+ ;
+ }
+
+ private static void RecursePacketArray(FieldInfo fieldInfo, object packet, ref StringBuilder result)
+ {
+ var packetDataObject = fieldInfo.GetValue(packet);
+
+ foreach (object nestedArrayRecord in packetDataObject as Array)
+ {
+ FieldInfo[] fields = nestedArrayRecord.GetType().GetFields();
+
+ for (int i = 0; i < fields.Length; i++)
+ {
+ String special;
+ if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + fields[i].Name,
+ fields[i].GetValue(nestedArrayRecord), out special))
+ {
+ result.AppendLine(special);
+ }
+ else if (fields[i].FieldType.IsArray) // default for an array (probably a byte[])
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + System.Environment.NewLine,
+ fields[i].Name,
+ fields[i].GetValue(nestedArrayRecord),
+ fields[i].GetValue(nestedArrayRecord).GetType().Name);
+ }
+ else // default for a field
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + System.Environment.NewLine,
+ fields[i].Name,
+ fields[i].GetValue(nestedArrayRecord),
+ fields[i].GetValue(nestedArrayRecord).GetType().Name);
+ }
+ }
+
+ // Handle Properties
+ foreach (PropertyInfo propertyInfo in nestedArrayRecord.GetType().GetProperties())
+ {
+ if (propertyInfo.Name.Equals("Length"))
+ continue;
+
+ string special;
+ if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + propertyInfo.Name,
+ propertyInfo.GetValue(nestedArrayRecord, null),
+ out special))
+ {
+ result.AppendLine(special);
+ }
+ else
+ {
+ result.AppendFormat("{0, 30}: {1,-40} [{2}]c" + Environment.NewLine,
+ propertyInfo.Name,
+ /*Utils.BytesToString((byte[])*/propertyInfo.GetValue(nestedArrayRecord, null)/*)*/,
+ propertyInfo.PropertyType.Name);
+ }
+ }
+ result.AppendFormat("{0,32}" + Environment.NewLine, "***");
+ }
+ }
+
+ private static void RecursePacketField(FieldInfo fieldInfo, object packet, ref StringBuilder result)
+ {
+ object packetDataObject = fieldInfo.GetValue(packet);
+
+ // handle Fields
+ foreach (FieldInfo packetValueField in fieldInfo.GetValue(packet).GetType().GetFields())
+ {
+ string special;
+ if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + packetValueField.Name,
+ packetValueField.GetValue(packetDataObject),
+ out special))
+ {
+ result.AppendLine(special);
+ }
+ else
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ packetValueField.Name, packetValueField.GetValue(packetDataObject), packetValueField.FieldType.Name);
+ }
+ }
+
+ // Handle Properties
+ foreach (PropertyInfo propertyInfo in packetDataObject.GetType().GetProperties())
+ {
+ if (propertyInfo.Name.Equals("Length"))
+ continue;
+
+ string special;
+ if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + propertyInfo.Name,
+ propertyInfo.GetValue(packetDataObject, null),
+ out special))
+ {
+ result.AppendLine(special);
+ }
+ else if (propertyInfo.GetValue(packetDataObject, null).GetType() == typeof(byte[]))
+ {
+ result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine,
+ propertyInfo.Name,
+ Utils.BytesToString((byte[])propertyInfo.GetValue(packetDataObject, null)),
+ propertyInfo.PropertyType.Name);
+ }
+ else
+ {
+ result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine,
+ propertyInfo.Name,
+ propertyInfo.GetValue(packetDataObject, null),
+ propertyInfo.PropertyType.Name);
+ }
+ }
+ }
+
+ private static bool SpecialDecoder(string decoderKey, object fieldData, out string result)
+ {
+ result = string.Empty;
+ string[] keys = decoderKey.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
+ string[] keyList = { decoderKey, decoderKey.Replace("Packet", ""), keys[1] + "." + keys[2], keys[2] };
+ foreach (string key in keyList)
+ {
+
+ bool ok = true;
+ if (fieldData is byte[])
+ {
+ byte[] fd = (byte[])fieldData;
+ ok = fd.Length > 0;
+ if (!ok)
+ {
+ // bypass the decoder since we were passed an empty byte array
+ result = String.Format("{0,30}:", keys[2]);
+ return true;
+ }
+ }
+
+ if (ok && Callbacks.ContainsKey(key)) // fieldname e.g: Plane
+ {
+ foreach (CustomPacketDecoder decoder in Callbacks[key])
+ result = decoder(keys[2], fieldData);
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/OpenMetaverse/Primitives/Primitive.cs b/OpenMetaverse/Primitives/Primitive.cs
index bd804341..baffd795 100644
--- a/OpenMetaverse/Primitives/Primitive.cs
+++ b/OpenMetaverse/Primitives/Primitive.cs
@@ -267,7 +267,11 @@ namespace OpenMetaverse
///
Plane = 3,
///
- Cylinder = 4
+ Cylinder = 4,
+ ///
+ Invert = 64,
+ ///
+ Mirror = 128
}
///
@@ -888,7 +892,7 @@ namespace OpenMetaverse
///
public bool Invert
{
- get { return ((type & 64) != 0); }
+ get { return ((type & (byte)SculptType.Invert) != 0); }
}
///
@@ -896,7 +900,7 @@ namespace OpenMetaverse
///
public bool Mirror
{
- get { return ((type & 128) != 0); }
+ get { return ((type & (byte)SculptType.Mirror) != 0); }
}
///
diff --git a/OpenMetaverse/SoundManager.cs b/OpenMetaverse/SoundManager.cs
index 33d51a34..449ed0a7 100644
--- a/OpenMetaverse/SoundManager.cs
+++ b/OpenMetaverse/SoundManager.cs
@@ -30,11 +30,12 @@ using OpenMetaverse.Packets;
namespace OpenMetaverse
{
+
public class SoundManager
{
public readonly GridClient Client;
- public delegate void AttachSoundCallback(UUID soundID, UUID ownerID, UUID objectID, float gain, byte flags);
+ public delegate void AttachSoundCallback(UUID soundID, UUID ownerID, UUID objectID, float gain, SoundFlags flags);
public delegate void AttachedSoundGainChangeCallback(UUID objectID, float gain);
public delegate void SoundTriggerCallback(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, float gain, ulong regionHandle, Vector3 position);
public delegate void PreloadSoundCallback(UUID soundID, UUID ownerID, UUID objectID);
@@ -125,7 +126,7 @@ namespace OpenMetaverse
AttachedSoundPacket sound = (AttachedSoundPacket)packet;
if (OnAttachSound != null)
{
- try { OnAttachSound(sound.DataBlock.SoundID, sound.DataBlock.OwnerID, sound.DataBlock.ObjectID, sound.DataBlock.Gain, sound.DataBlock.Flags); }
+ try { OnAttachSound(sound.DataBlock.SoundID, sound.DataBlock.OwnerID, sound.DataBlock.ObjectID, sound.DataBlock.Gain, (SoundFlags)sound.DataBlock.Flags); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
diff --git a/Programs/GridProxy/GridProxy.cs b/Programs/GridProxy/GridProxy.cs
index 21f2d017..6229d0cc 100644
--- a/Programs/GridProxy/GridProxy.cs
+++ b/Programs/GridProxy/GridProxy.cs
@@ -31,7 +31,7 @@
*/
// #define DEBUG_SEQUENCE
-//#define DEBUG_CAPS
+// #define DEBUG_CAPS
// #define DEBUG_THREADS
using System;
@@ -48,6 +48,8 @@ using OpenMetaverse;
using OpenMetaverse.Http;
using OpenMetaverse.StructuredData;
using OpenMetaverse.Packets;
+using log4net;
+using Logger=Nwc.XmlRpc.Logger;
namespace GridProxy
{
@@ -216,7 +218,7 @@ namespace GridProxy
displayAddress = endPoint.Address;
loginURI = "http://" + displayAddress + ":" + endPoint.Port + "/";
- Log("proxy ready at " + loginURI, false);
+ OpenMetaverse.Logger.Log("Proxy ready at " + loginURI, Helpers.LogLevel.Info);
}
}
@@ -232,9 +234,9 @@ namespace GridProxy
// KeepAlive: blocks until the proxy is free to shut down
public void KeepAlive()
{
-#if DEBUG_THREADS
- Console.WriteLine(">T> KeepAlive");
-#endif
+
+ OpenMetaverse.Logger.Log(">T> KeepAlive", Helpers.LogLevel.Debug);
+
lock (keepAliveLock) { };
if (loginServer.Connected)
@@ -245,13 +247,7 @@ namespace GridProxy
loginServer.Close();
-
-
-
-#if DEBUG_THREADS
- Console.WriteLine("T> RunLoginProxy");
-#endif
+ OpenMetaverse.Logger.Log(">T> RunLoginProxy", Helpers.LogLevel.Debug);
+
try
{
for (; ; )
@@ -395,21 +383,18 @@ namespace GridProxy
{
Thread connThread = new Thread((ThreadStart)delegate
{
-#if DEBUG_THREADS
- Console.WriteLine(">T> ProxyHTTP");
-#endif
+ OpenMetaverse.Logger.Log(">T> ProxyHTTP", Helpers.LogLevel.Debug);
ProxyHTTP(client);
-#if DEBUG_THREADS
- Console.WriteLine(" " + packet.Type + " #" + packet.Header.Sequence);
-#endif
+ OpenMetaverse.Logger.Log("-> " + packet.Type + " #" + packet.Header.Sequence, Helpers.LogLevel.Debug);
// check for ACKs we're waiting for
packet = CheckAcks(packet, Direction.Outgoing, ref length, ref needsCopy);
@@ -1705,8 +1662,7 @@ namespace GridProxy
}
catch (Exception e)
{
- proxy.Log("exception in outgoing delegate: " + e.Message, true);
- proxy.Log(e.StackTrace, true);
+ OpenMetaverse.Logger.Log("exception in outgoing delegate", Helpers.LogLevel.Error, e);
}
if (packet != null)
@@ -1727,7 +1683,7 @@ namespace GridProxy
}
catch (Exception e)
{
- Console.WriteLine(e.ToString());
+ OpenMetaverse.Logger.Log("Proxy error sending packet", Helpers.LogLevel.Error, e);
}
finally
{
@@ -1737,9 +1693,9 @@ namespace GridProxy
socket.BeginReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None,
ref clientEndPoint, new AsyncCallback(ReceiveFromClient), null);
}
- catch (Exception e)
+ catch (SocketException e)
{
- Console.WriteLine(e.Message);
+ OpenMetaverse.Logger.Log("Socket Shutdown: " + e.SocketErrorCode, Helpers.LogLevel.Warning);
}
}
}
@@ -2059,8 +2015,7 @@ namespace GridProxy
// LogPacket: log a packet dump
private Packet LogPacket(Packet packet, string type)
{
- Log(type + " packet:", true);
- Log(packet, true);
+ OpenMetaverse.Logger.Log(type + " packet:\n" + packet, Helpers.LogLevel.Info);
return packet;
}
diff --git a/Programs/GridProxy/GridProxyLoader.cs b/Programs/GridProxy/GridProxyLoader.cs
index d3416484..1e7da2fd 100644
--- a/Programs/GridProxy/GridProxyLoader.cs
+++ b/Programs/GridProxy/GridProxyLoader.cs
@@ -10,6 +10,7 @@ using Nwc.XmlRpc;
using OpenMetaverse;
using OpenMetaverse.Packets;
using GridProxy;
+using Logger=OpenMetaverse.Logger;
namespace GridProxy
@@ -90,7 +91,9 @@ namespace GridProxy
{
string sw = arg.Substring(0, ipos);
string val = arg.Substring(ipos + 1);
- Console.WriteLine("arg '" + sw + "' val '" + val + "'");
+
+ Logger.Log("arg '" + sw + "' val '" + val + "'", Helpers.LogLevel.Debug);
+
if (sw == "--load")
{
//externalPlugin = true;
@@ -114,7 +117,7 @@ namespace GridProxy
}
catch (Exception e)
{
- Console.WriteLine(e.ToString());
+ Logger.Log("LoadPlugin exception", Helpers.LogLevel.Error, e);
}
}
}
@@ -136,7 +139,7 @@ namespace GridProxy
}
catch (Exception e)
{
- Console.WriteLine(e.ToString());
+ Logger.Log("LoadPlugin exception", Helpers.LogLevel.Error, e);
}
}
@@ -196,7 +199,10 @@ namespace GridProxy
return packet;
}
- // SayToUser: send a message to the user as in-world chat
+ ///
+ /// Send a message to the viewer
+ ///
+ /// A string containing the message to send
public void SayToUser(string message)
{
ChatFromSimulatorPacket packet = new ChatFromSimulatorPacket();
@@ -210,10 +216,8 @@ namespace GridProxy
packet.ChatData.Message = Utils.StringToBytes(message);
proxy.InjectPacket(packet, Direction.Incoming);
}
-
}
-
public abstract class ProxyPlugin : MarshalByRefObject
{
// public abstract ProxyPlugin(ProxyFrame main);
diff --git a/Programs/GridProxy/Plugins/Analyst.cs b/Programs/GridProxy/Plugins/Analyst.cs
index 7997a8bd..393d9767 100644
--- a/Programs/GridProxy/Plugins/Analyst.cs
+++ b/Programs/GridProxy/Plugins/Analyst.cs
@@ -52,6 +52,8 @@ public class Analyst : ProxyPlugin
private Dictionary> modifiedPackets = new Dictionary>();
private Assembly openmvAssembly;
private StreamWriter output;
+
+ private PacketDecoder DecodePacket = new PacketDecoder();
public Analyst(ProxyFrame frame)
{
@@ -827,7 +829,7 @@ public class Analyst : ProxyPlugin
// LogPacket: dump a packet to the console
private void LogPacket(Packet packet, IPEndPoint endPoint, Direction direction)
{
- string packetText = Helpers.PacketToString(packet);
+ string packetText = DecodePacket.PacketToString(packet);
if (logGrep == null || (logGrep != null && Regex.IsMatch(packetText, logGrep)))
{
diff --git a/Programs/WinGridProxy/FireEventAppender.cs b/Programs/WinGridProxy/FireEventAppender.cs
new file mode 100644
index 00000000..79a522ab
--- /dev/null
+++ b/Programs/WinGridProxy/FireEventAppender.cs
@@ -0,0 +1,82 @@
+#region Copyright & License
+//
+// Copyright 2001-2004 The Apache Software Foundation
+//
+// 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.
+//
+#endregion
+
+using System;
+using log4net.Core;
+
+namespace WinGridProxy
+{
+ public delegate void MessageLoggedEventHandler(object sender, MessageLoggedEventArgs e);
+
+ public class MessageLoggedEventArgs : EventArgs
+ {
+ private LoggingEvent m_loggingEvent;
+
+ public MessageLoggedEventArgs(LoggingEvent loggingEvent)
+ {
+ m_loggingEvent = loggingEvent;
+ }
+ public LoggingEvent LoggingEvent
+ {
+ get { return m_loggingEvent; }
+ }
+ }
+
+ public class FireEventAppender : log4net.Appender.AppenderSkeleton
+ {
+ private static FireEventAppender m_instance;
+
+ private FixFlags m_fixFlags = FixFlags.All;
+
+ // Event handler
+ public event MessageLoggedEventHandler MessageLoggedEvent;
+
+ // Easy singleton, gets the last instance created
+ public static FireEventAppender Instance
+ {
+ get { return m_instance; }
+ }
+
+ public FireEventAppender()
+ {
+ // Store the instance created
+ m_instance = this;
+ }
+
+ virtual public FixFlags Fix
+ {
+ get { return m_fixFlags; }
+ set { m_fixFlags = value; }
+ }
+
+ override protected void Append(LoggingEvent loggingEvent)
+ {
+ // Because we the LoggingEvent may be used beyond the lifetime
+ // of the Append() method we must fix any volatile data in the event
+ loggingEvent.Fix = this.Fix;
+
+ // Raise the event
+ MessageLoggedEventHandler handler = MessageLoggedEvent;
+ if (handler != null)
+ {
+ handler(this, new MessageLoggedEventArgs(loggingEvent));
+ }
+ }
+
+ }
+}
diff --git a/Programs/WinGridProxy/FormWinGridProxy.Designer.cs b/Programs/WinGridProxy/FormWinGridProxy.Designer.cs
index 874e4e93..3dbb5293 100644
--- a/Programs/WinGridProxy/FormWinGridProxy.Designer.cs
+++ b/Programs/WinGridProxy/FormWinGridProxy.Designer.cs
@@ -40,6 +40,13 @@
this.label1 = new System.Windows.Forms.Label();
this.panelMainWindow = new System.Windows.Forms.Panel();
this.splitContainerSessionsTabs = new System.Windows.Forms.SplitContainer();
+ this.listViewSessions = new WinGridProxy.ListViewNoFlicker();
+ this.columnHeaderCounter = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderProtocol = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderType = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderSize = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderUrl = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderContentType = new System.Windows.Forms.ColumnHeader();
this.contextMenuStripSessions = new System.Windows.Forms.ContextMenuStrip(this.components);
this.toolStripMenuItemAutoScroll = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator();
@@ -73,6 +80,7 @@
this.imageList1 = new System.Windows.Forms.ImageList(this.components);
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPageSummary = new System.Windows.Forms.TabPage();
+ this.richTextBoxDebugLog = new System.Windows.Forms.RichTextBox();
this.panelStats = new System.Windows.Forms.Panel();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.labelPacketsTotal = new System.Windows.Forms.Label();
@@ -92,8 +100,14 @@
this.splitContainerFilters = new System.Windows.Forms.SplitContainer();
this.checkBoxCheckAllPackets = new System.Windows.Forms.CheckBox();
this.grpUDPFilters = new System.Windows.Forms.GroupBox();
+ this.listViewPacketFilters = new WinGridProxy.ListViewNoFlicker();
+ this.columnHeaderPacketName = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderPacketType = new System.Windows.Forms.ColumnHeader();
this.checkBoxCheckAllMessages = new System.Windows.Forms.CheckBox();
this.grpCapsFilters = new System.Windows.Forms.GroupBox();
+ this.listViewMessageFilters = new WinGridProxy.ListViewNoFlicker();
+ this.columnHeaderName = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderMessageType = new System.Windows.Forms.ColumnHeader();
this.tabPageInspect = new System.Windows.Forms.TabPage();
this.splitContainerInspectorTab = new System.Windows.Forms.SplitContainer();
this.tabControlInspectorRequest = new System.Windows.Forms.TabControl();
@@ -212,19 +226,6 @@
this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator();
this.autoColorizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.colorDialog1 = new System.Windows.Forms.ColorDialog();
- this.listViewSessions = new WinGridProxy.ListViewNoFlicker();
- this.columnHeaderCounter = new System.Windows.Forms.ColumnHeader();
- this.columnHeaderProtocol = new System.Windows.Forms.ColumnHeader();
- this.columnHeaderType = new System.Windows.Forms.ColumnHeader();
- this.columnHeaderSize = new System.Windows.Forms.ColumnHeader();
- this.columnHeaderUrl = new System.Windows.Forms.ColumnHeader();
- this.columnHeaderContentType = new System.Windows.Forms.ColumnHeader();
- this.listViewPacketFilters = new WinGridProxy.ListViewNoFlicker();
- this.columnHeaderPacketName = new System.Windows.Forms.ColumnHeader();
- this.columnHeaderPacketType = new System.Windows.Forms.ColumnHeader();
- this.listViewMessageFilters = new WinGridProxy.ListViewNoFlicker();
- this.columnHeaderName = new System.Windows.Forms.ColumnHeader();
- this.columnHeaderMessageType = new System.Windows.Forms.ColumnHeader();
this.panelProxyConfig.SuspendLayout();
this.panelMainWindow.SuspendLayout();
this.splitContainerSessionsTabs.Panel1.SuspendLayout();
@@ -382,6 +383,59 @@
this.splitContainerSessionsTabs.SplitterWidth = 5;
this.splitContainerSessionsTabs.TabIndex = 0;
//
+ // listViewSessions
+ //
+ this.listViewSessions.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeaderCounter,
+ this.columnHeaderProtocol,
+ this.columnHeaderType,
+ this.columnHeaderSize,
+ this.columnHeaderUrl,
+ this.columnHeaderContentType});
+ this.listViewSessions.ContextMenuStrip = this.contextMenuStripSessions;
+ this.listViewSessions.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.listViewSessions.FullRowSelect = true;
+ this.listViewSessions.GridLines = true;
+ this.listViewSessions.HideSelection = false;
+ this.listViewSessions.Location = new System.Drawing.Point(0, 0);
+ this.listViewSessions.Name = "listViewSessions";
+ this.listViewSessions.Size = new System.Drawing.Size(469, 428);
+ this.listViewSessions.SmallImageList = this.imageList1;
+ this.listViewSessions.TabIndex = 0;
+ this.listViewSessions.UseCompatibleStateImageBehavior = false;
+ this.listViewSessions.View = System.Windows.Forms.View.Details;
+ this.listViewSessions.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.listViewSessions_ItemSelectionChanged);
+ //
+ // columnHeaderCounter
+ //
+ this.columnHeaderCounter.Text = "#";
+ this.columnHeaderCounter.Width = 54;
+ //
+ // columnHeaderProtocol
+ //
+ this.columnHeaderProtocol.Text = "Protocol";
+ this.columnHeaderProtocol.Width = 59;
+ //
+ // columnHeaderType
+ //
+ this.columnHeaderType.Text = "Packet Type";
+ this.columnHeaderType.Width = 151;
+ //
+ // columnHeaderSize
+ //
+ this.columnHeaderSize.Text = "Bytes";
+ this.columnHeaderSize.Width = 64;
+ //
+ // columnHeaderUrl
+ //
+ this.columnHeaderUrl.Text = "Host/Address";
+ this.columnHeaderUrl.Width = 312;
+ //
+ // columnHeaderContentType
+ //
+ this.columnHeaderContentType.Text = "Content Type";
+ this.columnHeaderContentType.Width = 250;
+ //
// contextMenuStripSessions
//
this.contextMenuStripSessions.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -596,7 +650,7 @@
//
this.markToolStripMenuItem1.DropDown = this.contextMenuStripMark;
this.markToolStripMenuItem1.Name = "markToolStripMenuItem1";
- this.markToolStripMenuItem1.Size = new System.Drawing.Size(152, 22);
+ this.markToolStripMenuItem1.Size = new System.Drawing.Size(143, 22);
this.markToolStripMenuItem1.Text = "Mark";
//
// toolStripSeparator16
@@ -635,6 +689,7 @@
//
// tabPageSummary
//
+ this.tabPageSummary.Controls.Add(this.richTextBoxDebugLog);
this.tabPageSummary.Controls.Add(this.panelStats);
this.tabPageSummary.Location = new System.Drawing.Point(4, 28);
this.tabPageSummary.Name = "tabPageSummary";
@@ -644,6 +699,22 @@
this.tabPageSummary.Text = "Summary";
this.tabPageSummary.UseVisualStyleBackColor = true;
//
+ // richTextBoxDebugLog
+ //
+ this.richTextBoxDebugLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.richTextBoxDebugLog.BackColor = System.Drawing.SystemColors.ControlLightLight;
+ this.richTextBoxDebugLog.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.richTextBoxDebugLog.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.richTextBoxDebugLog.Location = new System.Drawing.Point(6, 101);
+ this.richTextBoxDebugLog.Name = "richTextBoxDebugLog";
+ this.richTextBoxDebugLog.ReadOnly = true;
+ this.richTextBoxDebugLog.ShowSelectionMargin = true;
+ this.richTextBoxDebugLog.Size = new System.Drawing.Size(592, 289);
+ this.richTextBoxDebugLog.TabIndex = 3;
+ this.richTextBoxDebugLog.Text = "";
+ //
// panelStats
//
this.panelStats.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@@ -854,6 +925,35 @@
this.grpUDPFilters.TabStop = false;
this.grpUDPFilters.Text = "UDP Packets";
//
+ // listViewPacketFilters
+ //
+ this.listViewPacketFilters.CheckBoxes = true;
+ this.listViewPacketFilters.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeaderPacketName,
+ this.columnHeaderPacketType});
+ this.listViewPacketFilters.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.listViewPacketFilters.FullRowSelect = true;
+ this.listViewPacketFilters.GridLines = true;
+ this.listViewPacketFilters.Location = new System.Drawing.Point(3, 16);
+ this.listViewPacketFilters.MultiSelect = false;
+ this.listViewPacketFilters.Name = "listViewPacketFilters";
+ this.listViewPacketFilters.Size = new System.Drawing.Size(286, 338);
+ this.listViewPacketFilters.Sorting = System.Windows.Forms.SortOrder.Ascending;
+ this.listViewPacketFilters.TabIndex = 0;
+ this.listViewPacketFilters.UseCompatibleStateImageBehavior = false;
+ this.listViewPacketFilters.View = System.Windows.Forms.View.Details;
+ this.listViewPacketFilters.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listViewPacketFilters_ItemChecked);
+ this.listViewPacketFilters.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listViewFilterSorter_ColumnClick);
+ //
+ // columnHeaderPacketName
+ //
+ this.columnHeaderPacketName.Text = "Packet Name";
+ this.columnHeaderPacketName.Width = 215;
+ //
+ // columnHeaderPacketType
+ //
+ this.columnHeaderPacketType.Text = "Type";
+ //
// checkBoxCheckAllMessages
//
this.checkBoxCheckAllMessages.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
@@ -882,6 +982,36 @@
this.grpCapsFilters.TabStop = false;
this.grpCapsFilters.Text = "Capabilities Messages";
//
+ // listViewMessageFilters
+ //
+ this.listViewMessageFilters.CheckBoxes = true;
+ this.listViewMessageFilters.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeaderName,
+ this.columnHeaderMessageType});
+ this.listViewMessageFilters.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.listViewMessageFilters.FullRowSelect = true;
+ this.listViewMessageFilters.GridLines = true;
+ this.listViewMessageFilters.Location = new System.Drawing.Point(3, 16);
+ this.listViewMessageFilters.MultiSelect = false;
+ this.listViewMessageFilters.Name = "listViewMessageFilters";
+ this.listViewMessageFilters.Size = new System.Drawing.Size(284, 338);
+ this.listViewMessageFilters.Sorting = System.Windows.Forms.SortOrder.Ascending;
+ this.listViewMessageFilters.TabIndex = 1;
+ this.listViewMessageFilters.UseCompatibleStateImageBehavior = false;
+ this.listViewMessageFilters.View = System.Windows.Forms.View.Details;
+ this.listViewMessageFilters.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listViewMessageFilters_ItemChecked);
+ this.listViewMessageFilters.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listViewFilterSorter_ColumnClick);
+ //
+ // columnHeaderName
+ //
+ this.columnHeaderName.Text = "Message Name";
+ this.columnHeaderName.Width = 181;
+ //
+ // columnHeaderMessageType
+ //
+ this.columnHeaderMessageType.Text = "Type";
+ this.columnHeaderMessageType.Width = 92;
+ //
// tabPageInspect
//
this.tabPageInspect.Controls.Add(this.splitContainerInspectorTab);
@@ -952,6 +1082,7 @@
this.richTextBoxDecodedRequest.Size = new System.Drawing.Size(591, 143);
this.richTextBoxDecodedRequest.TabIndex = 0;
this.richTextBoxDecodedRequest.Text = "";
+ this.richTextBoxDecodedRequest.TextChanged += new System.EventHandler(this.richTextBoxDecodedRequest_TextChanged);
//
// tabPageRawRequest
//
@@ -1104,6 +1235,7 @@
this.richTextBoxDecodedResponse.Size = new System.Drawing.Size(591, 176);
this.richTextBoxDecodedResponse.TabIndex = 0;
this.richTextBoxDecodedResponse.Text = "";
+ this.richTextBoxDecodedResponse.TextChanged += new System.EventHandler(this.richTextBoxDecodedRequest_TextChanged);
//
// tabPageInspectorRAWResponse
//
@@ -1295,14 +1427,14 @@
//
this.removeToolStripMenuItem2.DropDown = this.contextMenuStripRemove;
this.removeToolStripMenuItem2.Name = "removeToolStripMenuItem2";
- this.removeToolStripMenuItem2.Size = new System.Drawing.Size(152, 22);
+ this.removeToolStripMenuItem2.Size = new System.Drawing.Size(143, 22);
this.removeToolStripMenuItem2.Text = "Remove";
//
// selectToolStripMenuItem1
//
this.selectToolStripMenuItem1.DropDown = this.contextMenuStripSelect;
this.selectToolStripMenuItem1.Name = "selectToolStripMenuItem1";
- this.selectToolStripMenuItem1.Size = new System.Drawing.Size(152, 22);
+ this.selectToolStripMenuItem1.Size = new System.Drawing.Size(143, 22);
this.selectToolStripMenuItem1.Text = "Select";
//
// toolStripLabelHexEditorRequest
@@ -1477,7 +1609,7 @@
//
this.copyToolStripMenuItem1.DropDown = this.contextMenuStripCopy;
this.copyToolStripMenuItem1.Name = "copyToolStripMenuItem1";
- this.copyToolStripMenuItem1.Size = new System.Drawing.Size(152, 22);
+ this.copyToolStripMenuItem1.Size = new System.Drawing.Size(143, 22);
this.copyToolStripMenuItem1.Text = "Copy";
this.copyToolStripMenuItem1.Visible = false;
//
@@ -1519,18 +1651,18 @@
// toolStripSeparator10
//
this.toolStripSeparator10.Name = "toolStripSeparator10";
- this.toolStripSeparator10.Size = new System.Drawing.Size(149, 6);
+ this.toolStripSeparator10.Size = new System.Drawing.Size(140, 6);
//
// toolStripSeparator12
//
this.toolStripSeparator12.Name = "toolStripSeparator12";
- this.toolStripSeparator12.Size = new System.Drawing.Size(149, 6);
+ this.toolStripSeparator12.Size = new System.Drawing.Size(140, 6);
//
// findToolStripMenuItem
//
this.findToolStripMenuItem.Name = "findToolStripMenuItem";
this.findToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F)));
- this.findToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+ this.findToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
this.findToolStripMenuItem.Text = "Find";
this.findToolStripMenuItem.Click += new System.EventHandler(this.findSessions_Click);
//
@@ -1938,118 +2070,6 @@
this.autoColorizeToolStripMenuItem.Text = "Auto Colorize";
this.autoColorizeToolStripMenuItem.Click += new System.EventHandler(this.autoColorizeToolStripMenuItem_Click);
//
- // listViewSessions
- //
- this.listViewSessions.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
- this.columnHeaderCounter,
- this.columnHeaderProtocol,
- this.columnHeaderType,
- this.columnHeaderSize,
- this.columnHeaderUrl,
- this.columnHeaderContentType});
- this.listViewSessions.ContextMenuStrip = this.contextMenuStripSessions;
- this.listViewSessions.Dock = System.Windows.Forms.DockStyle.Fill;
- this.listViewSessions.FullRowSelect = true;
- this.listViewSessions.GridLines = true;
- this.listViewSessions.HideSelection = false;
- this.listViewSessions.Location = new System.Drawing.Point(0, 0);
- this.listViewSessions.Name = "listViewSessions";
- this.listViewSessions.Size = new System.Drawing.Size(469, 428);
- this.listViewSessions.SmallImageList = this.imageList1;
- this.listViewSessions.TabIndex = 0;
- this.listViewSessions.UseCompatibleStateImageBehavior = false;
- this.listViewSessions.View = System.Windows.Forms.View.Details;
- this.listViewSessions.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.listViewSessions_ItemSelectionChanged);
- //
- // columnHeaderCounter
- //
- this.columnHeaderCounter.Text = "#";
- this.columnHeaderCounter.Width = 54;
- //
- // columnHeaderProtocol
- //
- this.columnHeaderProtocol.Text = "Protocol";
- this.columnHeaderProtocol.Width = 59;
- //
- // columnHeaderType
- //
- this.columnHeaderType.Text = "Packet Type";
- this.columnHeaderType.Width = 151;
- //
- // columnHeaderSize
- //
- this.columnHeaderSize.Text = "Bytes";
- this.columnHeaderSize.Width = 64;
- //
- // columnHeaderUrl
- //
- this.columnHeaderUrl.Text = "Host/Address";
- this.columnHeaderUrl.Width = 312;
- //
- // columnHeaderContentType
- //
- this.columnHeaderContentType.Text = "Content Type";
- this.columnHeaderContentType.Width = 250;
- //
- // listViewPacketFilters
- //
- this.listViewPacketFilters.CheckBoxes = true;
- this.listViewPacketFilters.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
- this.columnHeaderPacketName,
- this.columnHeaderPacketType});
- this.listViewPacketFilters.Dock = System.Windows.Forms.DockStyle.Fill;
- this.listViewPacketFilters.FullRowSelect = true;
- this.listViewPacketFilters.GridLines = true;
- this.listViewPacketFilters.Location = new System.Drawing.Point(3, 16);
- this.listViewPacketFilters.MultiSelect = false;
- this.listViewPacketFilters.Name = "listViewPacketFilters";
- this.listViewPacketFilters.Size = new System.Drawing.Size(286, 338);
- this.listViewPacketFilters.Sorting = System.Windows.Forms.SortOrder.Ascending;
- this.listViewPacketFilters.TabIndex = 0;
- this.listViewPacketFilters.UseCompatibleStateImageBehavior = false;
- this.listViewPacketFilters.View = System.Windows.Forms.View.Details;
- this.listViewPacketFilters.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listViewPacketFilters_ItemChecked);
- this.listViewPacketFilters.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listViewFilterSorter_ColumnClick);
- //
- // columnHeaderPacketName
- //
- this.columnHeaderPacketName.Text = "Packet Name";
- this.columnHeaderPacketName.Width = 215;
- //
- // columnHeaderPacketType
- //
- this.columnHeaderPacketType.Text = "Type";
- //
- // listViewMessageFilters
- //
- this.listViewMessageFilters.CheckBoxes = true;
- this.listViewMessageFilters.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
- this.columnHeaderName,
- this.columnHeaderMessageType});
- this.listViewMessageFilters.Dock = System.Windows.Forms.DockStyle.Fill;
- this.listViewMessageFilters.FullRowSelect = true;
- this.listViewMessageFilters.GridLines = true;
- this.listViewMessageFilters.Location = new System.Drawing.Point(3, 16);
- this.listViewMessageFilters.MultiSelect = false;
- this.listViewMessageFilters.Name = "listViewMessageFilters";
- this.listViewMessageFilters.Size = new System.Drawing.Size(284, 338);
- this.listViewMessageFilters.Sorting = System.Windows.Forms.SortOrder.Ascending;
- this.listViewMessageFilters.TabIndex = 1;
- this.listViewMessageFilters.UseCompatibleStateImageBehavior = false;
- this.listViewMessageFilters.View = System.Windows.Forms.View.Details;
- this.listViewMessageFilters.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listViewMessageFilters_ItemChecked);
- this.listViewMessageFilters.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listViewFilterSorter_ColumnClick);
- //
- // columnHeaderName
- //
- this.columnHeaderName.Text = "Message Name";
- this.columnHeaderName.Width = 181;
- //
- // columnHeaderMessageType
- //
- this.columnHeaderMessageType.Text = "Type";
- this.columnHeaderMessageType.Width = 92;
- //
// FormWinGridProxy
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -2319,6 +2339,7 @@
private System.Windows.Forms.ComboBox comboBoxListenAddress;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemPlugins;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator14;
+ private System.Windows.Forms.RichTextBox richTextBoxDebugLog;
}
}
diff --git a/Programs/WinGridProxy/FormWinGridProxy.cs b/Programs/WinGridProxy/FormWinGridProxy.cs
index e4401862..a470bfa7 100644
--- a/Programs/WinGridProxy/FormWinGridProxy.cs
+++ b/Programs/WinGridProxy/FormWinGridProxy.cs
@@ -30,7 +30,7 @@ using System.Net;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
-
+using System.Text.RegularExpressions;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
@@ -43,6 +43,7 @@ using OpenMetaverse.StructuredData;
using OpenMetaverse.Interfaces;
using System.Xml;
using Nwc.XmlRpc;
+using Logger=OpenMetaverse.Logger;
namespace WinGridProxy
{
@@ -56,6 +57,7 @@ namespace WinGridProxy
ProxyManager proxy;
+ private PacketDecoder DecodePacket = new PacketDecoder();
private int PacketCounter;
@@ -73,12 +75,18 @@ namespace WinGridProxy
{
InitializeComponent();
+ Logger.Log("WinGridProxy ready", Helpers.LogLevel.Info);
+
+ if (FireEventAppender.Instance != null)
+ {
+ FireEventAppender.Instance.MessageLoggedEvent += new MessageLoggedEventHandler(Instance_MessageLoggedEvent);
+ }
+
// populate the listen box with IPs
IPHostEntry iphostentry = Dns.GetHostByName(Dns.GetHostName());
foreach (IPAddress address in iphostentry.AddressList)
comboBoxListenAddress.Items.Add(address.ToString());
-
ProxyManager.OnPacketLog += ProxyManager_OnPacketLog;
ProxyManager.OnMessageLog += ProxyManager_OnMessageLog;
ProxyManager.OnLoginResponse += ProxyManager_OnLoginResponse;
@@ -956,7 +964,7 @@ namespace WinGridProxy
}
else
{
- result.AppendFormat("{0, 30}: {1} ({2})" + System.Environment.NewLine,
+ result.AppendFormat("{0, 30}: {1} ({2})" + Environment.NewLine,
nestedField.Name,
nestedField.GetValue(nestedArrayObject),
nestedField.GetValue(nestedArrayObject).GetType().Name);
@@ -968,7 +976,7 @@ namespace WinGridProxy
{
if (messageField.FieldType.IsEnum)
{
- result.AppendFormat("{0, 30}: {1} {2} ({3})" + System.Environment.NewLine,
+ result.AppendFormat("{0, 30}: {1} {2} ({3})" + Environment.NewLine,
messageField.Name,
Enum.Format(messageField.GetValue(message).GetType(),
messageField.GetValue(message), "D"),
@@ -989,159 +997,6 @@ namespace WinGridProxy
return result.ToString();
}
- private static string InterpretOptions(Header header)
- {
- return "["
- + (header.AppendedAcks ? "Ack" : " ")
- + " "
- + (header.Resent ? "Res" : " ")
- + " "
- + (header.Reliable ? "Rel" : " ")
- + " "
- + (header.Zerocoded ? "Zer" : " ")
- + "]"
- ;
- }
-
- ///
- /// Creates a formatted string containing the values of a Packet
- ///
- /// The Packet
- /// A formatted string of values of the nested items in the Packet object
- /// TODO: This is overly complex. Static helpers should be created to clean this up and it
- /// should be made generic enough to decode IMessage objects too.
- public static string PacketToString(Packet packet)
- {
- StringBuilder result = new StringBuilder();
-
- result.AppendFormat("Packet Type: {0}" + System.Environment.NewLine, packet.Type);
- result.AppendLine("[Packet Header]");
- // payload
- result.AppendFormat("Sequence: {0}" + System.Environment.NewLine, packet.Header.Sequence);
- result.AppendFormat(" Options: {0}" + System.Environment.NewLine, InterpretOptions(packet.Header));
- result.AppendLine();
-
- result.AppendLine("[Packet Payload]");
- foreach (FieldInfo packetField in packet.GetType().GetFields())
- {
- object packetDataObject = packetField.GetValue(packet);
-
- result.AppendFormat("-- {0,20} --" + System.Environment.NewLine, packetField.Name);
- foreach (FieldInfo packetValueField in packetField.GetValue(packet).GetType().GetFields())
- {
- result.AppendFormat("{0,30}: {1}" + System.Environment.NewLine,
- packetValueField.Name, packetValueField.GetValue(packetDataObject));
- }
-
- // handle blocks that are arrays
- if (packetDataObject.GetType().IsArray)
- {
- foreach (object nestedArrayRecord in packetDataObject as Array)
- {
- // handle properties
- foreach (PropertyInfo propertyInfo in nestedArrayRecord.GetType().GetProperties())
- {
- if (propertyInfo.GetValue(nestedArrayRecord, null).GetType() == typeof(byte[]))
- {
- result.AppendFormat("{0, 30}: {1}" + Environment.NewLine,
- propertyInfo.Name,
- Utils.BytesToString((byte[])propertyInfo.GetValue(nestedArrayRecord, null)));
- }
- }
-
- // handle fields
- foreach (FieldInfo packetArrayField in nestedArrayRecord.GetType().GetFields())
- {
- if (packetArrayField.GetValue(nestedArrayRecord).GetType() == typeof(Byte[]))
- {
- result.AppendFormat("{0,30}: {1}" + Environment.NewLine,
- packetArrayField.Name,
- new Color4((byte[])packetArrayField.GetValue(nestedArrayRecord), 0, false));
- }
- else
- {
- result.AppendFormat("{0,30}: {1}" + Environment.NewLine,
- packetArrayField.Name, packetArrayField.GetValue(nestedArrayRecord));
- }
- }
- }
- }
-
- else
- {
- // handle non array data blocks
- foreach (PropertyInfo packetPropertyField in packetField.GetValue(packet).GetType().GetProperties())
- {
- // Handle fields named "Data" specifically, this is generally binary data, we'll display it as hex values
- if (packetPropertyField.PropertyType.Equals(typeof(Byte[]))
- && packetPropertyField.Name.Equals("Data"))
- {
- result.AppendFormat("{0}" + System.Environment.NewLine,
- Utils.BytesToHexString((byte[])packetPropertyField.GetValue(packetDataObject, null),
- packetPropertyField.Name));
- }
- // decode bytes into strings
- else if (packetPropertyField.PropertyType.Equals(typeof(Byte[])))
- {
- // Handle TextureEntry fields specifically
- if (packetPropertyField.Name.Equals("TextureEntry"))
- {
- byte[] tebytes = (byte[])packetPropertyField.GetValue(packetDataObject, null);
-
- Primitive.TextureEntry te = new Primitive.TextureEntry(tebytes, 0, tebytes.Length);
- result.AppendFormat("{0,30}:\n{1}", packetPropertyField.Name, te.ToString());
- }
- else
- {
- // Decode the BinaryBucket
- if (packetPropertyField.Name.Equals("BinaryBucket"))
- {
- byte[] bytes = (byte[])packetPropertyField.GetValue(packetDataObject, null);
- string bbDecoded = String.Empty;
- if (bytes.Length == 1)
- {
- bbDecoded = String.Format("{0}", bytes[0]);
- }
- else if (bytes.Length == 17)
- {
- bbDecoded = String.Format("{0} {1} ({2})",
- new UUID(bytes, 1),
- bytes[0],
- (AssetType)bytes[0]);
- }
- else
- {
- bbDecoded = Utils.BytesToString(bytes);
- }
-
- result.AppendFormat("{0,30}: {1}" + System.Environment.NewLine,
- packetPropertyField.Name,
- bbDecoded);
- }
- else
- {
- result.AppendFormat("{0,30}: {1}" + System.Environment.NewLine,
- packetPropertyField.Name,
- Utils.BytesToString((byte[])packetPropertyField.GetValue(packetDataObject, null)));
- }
- }
- }
- else
- {
- // this seems to be limited to the length property, since all others have been previously handled
- if (packetPropertyField.Name != "Length")
- {
- result.AppendFormat("{0,30}: {1} [{2}]" + System.Environment.NewLine,
- packetPropertyField.Name, packetPropertyField.GetValue(packetDataObject, null),
- packetPropertyField.GetType());
- }
- }
- }
- }
- }
- return result.ToString();
- }
-
private void SaveAllSettings(string fileName)
{
Store.MessageSessions.Clear();
@@ -1336,8 +1191,7 @@ namespace WinGridProxy
else if (tag is Packet)
{
Packet packet = (Packet)tag;
-
- return PacketToString(packet);
+ return DecodePacket.PacketToString(packet);
}
else if (tag is CapsRequest)
{
@@ -1561,7 +1415,6 @@ namespace WinGridProxy
private void autoColorizeToolStripMenuItem_Click(object sender, EventArgs e)
{
-
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
//listview.BackColor = colorDialog1.Color;
@@ -1573,5 +1426,59 @@ namespace WinGridProxy
FormPluginManager pluginManager = new FormPluginManager(proxy.Proxy);
pluginManager.ShowDialog();
}
+
+ void Instance_MessageLoggedEvent(object sender, MessageLoggedEventArgs e)
+ {
+ if(this.IsDisposed || this.Disposing)
+ return;
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(delegate()
+ {
+ Instance_MessageLoggedEvent(sender, e);
+ }));
+ }
+ else
+ {
+ string s = String.Format("{0} [{1}] {2} {3}", e.LoggingEvent.TimeStamp, e.LoggingEvent.Level,
+ e.LoggingEvent.RenderedMessage, e.LoggingEvent.ExceptionObject);
+ richTextBoxDebugLog.AppendText(s + "\n");
+ }
+ }
+
+ private void richTextBoxDecodedRequest_TextChanged(object sender, EventArgs e)
+ {
+ RichTextBox m_rtb = (RichTextBox) sender;
+ Regex typesRegex = new Regex(@"\[(?\w+|\w+\[\])\]|\((?.*)\)|\s-- (?\w+|\w+ \[\]) --\s|(?\s\*\*\*\s)|(?\s<\w+>\s|\s<\/\w+>\s)|(?\s\w+\[\d+\]\s)", RegexOptions.ExplicitCapture);
+
+ MatchCollection matches = typesRegex.Matches(m_rtb.Text);
+ foreach(Match match in matches)
+ {
+ m_rtb.SelectionStart = match.Index +1;
+ m_rtb.SelectionLength = match.Length -2;
+ m_rtb.SelectionFont = new Font(m_rtb.Font.FontFamily, m_rtb.Font.Size, FontStyle.Bold);
+
+ if (!String.IsNullOrEmpty(match.Groups["Type"].Value))
+ m_rtb.SelectionColor = Color.Blue;
+ else if (!String.IsNullOrEmpty(match.Groups["Enum"].Value))
+ m_rtb.SelectionColor = Color.FromArgb(43, 145, 175);
+ else if (!String.IsNullOrEmpty(match.Groups["Header"].Value))
+ {
+ m_rtb.SelectionColor = Color.Green;
+ m_rtb.SelectionBackColor = Color.LightSteelBlue;
+ }
+ else if (!String.IsNullOrEmpty(match.Groups["BlockSep"].Value))
+ m_rtb.SelectionColor = Color.Gold;
+ else if (!String.IsNullOrEmpty(match.Groups["Tag"].Value))
+ {
+ m_rtb.SelectionColor = Color.White;
+ m_rtb.SelectionBackColor = Color.Black;
+ }
+ else if (!String.IsNullOrEmpty(match.Groups["BlockCounter"].Value))
+ m_rtb.SelectionColor = Color.Green;
+
+ }
+ }
}
}
diff --git a/Programs/WinGridProxy/FormWinGridProxy.resx b/Programs/WinGridProxy/FormWinGridProxy.resx
index bc044b9f..986ae6e8 100644
--- a/Programs/WinGridProxy/FormWinGridProxy.resx
+++ b/Programs/WinGridProxy/FormWinGridProxy.resx
@@ -120,15 +120,6 @@
524, 17
-
- 185, 54
-
-
- 17, 54
-
-
- 705, 17
-
309, 17
@@ -187,6 +178,21 @@
116, 17
+
+ 185, 54
+
+
+ 17, 54
+
+
+ 705, 17
+
+
+ 414, 17
+
+
+ 116, 17
+
17, 17
@@ -206,9 +212,6 @@
s1c0gHPmbrPTpHNJKOCo2G1mZs20zcwUJ5yp1AB5+8/zEwgF5GMVDxh4AAAAAElFTkSuQmCC
-
- 919, 17
-
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
@@ -226,6 +229,9 @@
AAAAAElFTkSuQmCC
+
+ 919, 17
+
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
diff --git a/Programs/examples/TestClient/Commands/WhoCommand.cs b/Programs/examples/TestClient/Commands/WhoCommand.cs
index a4ea2a34..dc5615e6 100644
--- a/Programs/examples/TestClient/Commands/WhoCommand.cs
+++ b/Programs/examples/TestClient/Commands/WhoCommand.cs
@@ -27,8 +27,8 @@ namespace OpenMetaverse.TestClient
delegate(Avatar av)
{
result.AppendLine();
- result.AppendFormat("{0} (Group: {1}, Location: {2}, UUID: {3})",
- av.Name, av.GroupName, av.Position, av.ID.ToString());
+ result.AppendFormat("{0} (Group: {1}, Location: {2}, UUID: {3} LocalID: {4})",
+ av.Name, av.GroupName, av.Position, av.ID, av.LocalID);
}
);
}
diff --git a/bin/WinGridProxy.exe.config b/bin/WinGridProxy.exe.config
new file mode 100644
index 00000000..dca8fcae
--- /dev/null
+++ b/bin/WinGridProxy.exe.config
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/prebuild.xml b/prebuild.xml
index 8c60e6e9..c4ced7ed 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -1 +1 @@
-
TRACE;DEBUG
false
false
true
4
false
1591,1574,0419,0618
bin
true
true
false
TRACE
true
false
true
4
false
1591,1574,0419,0618
bin
false
true
false
../bin/
../bin/
../bin/
../bin/
../bin/
OpenMetaverseTypes.XML
../bin/
../bin/
../bin/
OpenMetaverse.StructuredData.XML
../bin/
../bin/
../bin/
OpenMetaverse.Http.XML
../bin/
../bin/
../bin/
OpenMetaverse.XML
../bin/
../bin/
../bin/
OpenMetaverse.Utilities.XML
../bin/
../bin/
../bin/
../bin/
../../bin/
../../bin/
../../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
OpenMetaverse.GUI.XML
../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
\ No newline at end of file
+
TRACE;DEBUG
false
false
true
4
false
1591,1574,0419,0618
bin
true
true
false
TRACE
true
false
true
4
false
1591,1574,0419,0618
bin
false
true
false
../bin/
../bin/
../bin/
../bin/
../bin/
OpenMetaverseTypes.XML
../bin/
../bin/
../bin/
OpenMetaverse.StructuredData.XML
../bin/
../bin/
../bin/
OpenMetaverse.Http.XML
../bin/
../bin/
../bin/
OpenMetaverse.XML
../bin/
../bin/
../bin/
OpenMetaverse.Utilities.XML
../bin/
../bin/
../bin/
../bin/
../../bin/
../../bin/
../../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
../bin/
OpenMetaverse.GUI.XML
../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/
../../../bin/