corrade-vassal – Rev 16
?pathlinks?
/*
* Copyright (c) 2006-2014, openmetaverse.org
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.org nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Net;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Threading;
using GridProxy;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData;
using OpenMetaverse.Interfaces;
using System.Xml;
using Nwc.XmlRpc;
using Logger = OpenMetaverse.Logger;
namespace WinGridProxy
{
public partial class FormWinGridProxy : Form
{
// only allow one thread at a time to do file I/O operations
private object m_FileIOLockerObject = new object();
// Class for saving and restoring settings
private static SettingsStore Store = new SettingsStore();
private static bool m_ProxyRunning;
private Assembly m_CurrentAssembly = Assembly.GetExecutingAssembly();
ProxyManager proxy;
private FormPluginManager pluginManager;
private int PacketCounter;
// stats tracking
private int CapsInCounter;
private int CapsInBytes;
private int CapsOutCounter;
private int CapsOutBytes;
private int PacketsInCounter;
private int PacketsInBytes;
private int PacketsOutCounter;
private int PacketsOutBytes;
private List<ListViewItem> QueuedSessions;
private bool monoRuntime;
private const string PROTO_CAPABILITIES = "Cap";
private const string PROTO_EVENTMESSAGE = "Event";
private const string PROTO_PACKETSTRING = "UDP";
private const string PROTO_AUTHENTICATE = "https";
// some default colors for session items
private readonly Color Color_Login = Color.OldLace;
private readonly Color Color_Packet = Color.LightYellow;
private readonly Color Color_Cap = Color.Honeydew;
private readonly Color Color_Event = Color.AliceBlue;
public FormWinGridProxy()
{
InitializeComponent();
Logger.Log("WinGridProxy ready", Helpers.LogLevel.Info);
if (FireEventAppender.Instance != null)
{
FireEventAppender.Instance.MessageLoggedEvent += new MessageLoggedEventHandler(Instance_MessageLoggedEvent);
}
// Attempt to work around some mono bugs
monoRuntime = Type.GetType("Mono.Runtime") != null; // Officially supported way of detecting mono
if (monoRuntime)
{
Font fixedFont = new Font(FontFamily.GenericMonospace, 9f, FontStyle.Regular, GraphicsUnit.Point);
richTextBoxDecodedRequest.Font =
richTextBoxDecodedResponse.Font =
richTextBoxNotationRequest.Font =
richTextBoxNotationResponse.Font =
richTextBoxRawRequest.Font =
richTextBoxRawResponse.Font = fixedFont;
}
QueuedSessions = new List<ListViewItem>();
// populate the listen box with the known IP Addresses of this host
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;
ProxyManager.OnCapabilityAdded += ProxyManager_OnCapabilityAdded;
ProxyManager.OnEventMessageLog += ProxyManager_OnEventMessageLog;
}
#region Event Handlers for Messages/Packets
/// <summary>
/// Adds a new EventQueue message to the Message Filters listview.
/// </summary>
/// <param name="req"></param>
/// <param name="stage"></param>
void ProxyManager_OnEventMessageLog(CapsRequest req, CapsStage stage)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(() => ProxyManager_OnEventMessageLog(req, stage)));
}
else
{
ListViewItem foundCap = FindListViewItem(listViewMessageFilters, req.Info.CapType, false);
if (foundCap == null)
{
ListViewItem addedItem = listViewMessageFilters.Items.Add(new ListViewItem(req.Info.CapType,
listViewMessageFilters.Groups["EventQueueMessages"]));
addedItem.SubItems.Add(PROTO_EVENTMESSAGE);
addedItem.BackColor = Color_Event;
if (autoAddNewDiscoveredMessagesToolStripMenuItem.Checked)
addedItem.Checked = true;
}
else
{
ProxyManager_OnMessageLog(req, CapsStage.Response);
}
}
}
/// <summary>
/// Adds a new Capability message to the message filters listview
/// </summary>
private void ProxyManager_OnCapabilityAdded(CapInfo cap)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(() => ProxyManager_OnCapabilityAdded(cap)));
}
else
{
ListViewItem foundCap = FindListViewItem(listViewMessageFilters, cap.CapType, false);
if (foundCap == null)
{
ListViewItem addedItem = listViewMessageFilters.Items.Add(new ListViewItem(cap.CapType,
listViewMessageFilters.Groups["Capabilities"]));
addedItem.SubItems.Add(PROTO_CAPABILITIES);
addedItem.BackColor = Color_Cap;
if (autoAddNewDiscoveredMessagesToolStripMenuItem.Checked)
addedItem.Checked = true;
}
}
}
/// <summary>
/// Handle Login Requests/Responses
/// </summary>
private void ProxyManager_OnLoginResponse(object request, Direction direction)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(() => ProxyManager_OnLoginResponse(request, direction)));
}
else
{
string loginType;
if (request is XmlRpcRequest)
{
loginType = "Login Request";
}
else
{
loginType = "Login Response";
}
ListViewItem foundItem = FindListViewItem(listViewPacketFilters, loginType, false);
if (foundItem != null && foundItem.Checked == true)
{
PacketCounter++;
SessionLogin sessionLogin = new SessionLogin(request, direction, comboBoxLoginURL.Text, request.GetType().Name + " " + loginType);
ListViewItem sessionEntry = new ListViewItem(new string[] { PacketCounter.ToString(), sessionLogin.TimeStamp.ToString("HH:mm:ss.fff"),
sessionLogin.Protocol, sessionLogin.Name, sessionLogin.Length.ToString(), sessionLogin.Host, sessionLogin.ContentType });
sessionEntry.Tag = sessionLogin;
sessionEntry.ImageIndex = (int)sessionLogin.Direction;
AddSession(sessionEntry);
}
}
}
// Only raised when we've told GridProxy we want a specific packet type
private void ProxyManager_OnPacketLog(Packet packet, Direction direction, IPEndPoint endpoint)
{
PacketCounter++;
if (direction == Direction.Incoming)
{
PacketsInCounter++;
PacketsInBytes += packet.Length;
}
else
{
PacketsOutCounter++;
PacketsOutBytes += packet.Length;
}
SessionPacket sessionPacket = new SessionPacket(packet, direction, endpoint,
PacketDecoder.InterpretOptions(packet.Header) + " Seq: " + packet.Header.Sequence.ToString() + " Freq:" + packet.Header.Frequency.ToString());
ListViewItem sessionItem = new ListViewItem(new string[] { PacketCounter.ToString(), sessionPacket.TimeStamp.ToString("HH:mm:ss.fff"), sessionPacket.Protocol, sessionPacket.Name, sessionPacket.Length.ToString(), sessionPacket.Host, sessionPacket.ContentType });
sessionItem.Tag = sessionPacket;
sessionItem.ImageIndex = (int)sessionPacket.Direction;
AddSession(sessionItem);
}
/// <summary>
/// Handle Capabilities
/// </summary>
private void ProxyManager_OnMessageLog(CapsRequest req, CapsStage stage)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(() => ProxyManager_OnMessageLog(req, stage)));
}
else
{
ListViewItem found = FindListViewItem(listViewMessageFilters, req.Info.CapType, false);
if (found != null && found.Checked)
{
PacketCounter++;
int size = 0;
string contentType = String.Empty;
if (req.RawRequest != null)
{
size += req.RawRequest.Length;
contentType = req.RequestHeaders.Get("Content-Type"); //req.RequestHeaders["Content-Type"];
}
if (req.RawResponse != null)
{
size += req.RawResponse.Length;
contentType = req.ResponseHeaders.Get("Content-Type");
}
Direction direction;
if (stage == CapsStage.Request)
{
CapsOutCounter++;
CapsOutBytes += req.Request.ToString().Length;
direction = Direction.Outgoing;
}
else
{
CapsInCounter++;
CapsInBytes += req.Response.ToString().Length;
direction = Direction.Incoming;
}
string proto = found.SubItems[1].Text;
Session capsSession = null;
if (found.Group.Header.Equals("Capabilities"))
{
capsSession = new SessionCaps(req.RawRequest, req.RawResponse, req.RequestHeaders,
req.ResponseHeaders, direction, req.Info.URI, req.Info.CapType, proto, req.FullUri);
}
else
{
capsSession = new SessionEvent(req.RawResponse, req.ResponseHeaders, req.Info.URI, req.Info.CapType, proto);
}
string[] s = { PacketCounter.ToString(), capsSession.TimeStamp.ToString("HH:mm:ss.fff"), capsSession.Protocol, capsSession.Name, capsSession.Length.ToString(), capsSession.Host, capsSession.ContentType };
ListViewItem session = new ListViewItem(s);
session.ImageIndex = (int)direction;
session.Tag = capsSession;
session.BackColor = found.BackColor;
AddSession(session);
}
else
{
if (found == null)
{
// must be a new event not in KnownCaps, lets add it to the listview
ListViewItem addedItem = listViewMessageFilters.Items.Add(new ListViewItem(req.Info.CapType));
addedItem.BackColor = Color_Cap;
if (autoAddNewDiscoveredMessagesToolStripMenuItem.Checked)
addedItem.Checked = true;
}
}
}
}
#endregion
#region Helpers
private ListViewItem FindListViewItem(ListView listView, string key, bool searchAll)
{
foreach (ListViewItem item in listView.Items)
{
if (item.Text.Equals(key)
|| (searchAll && item.SubItems.ContainsKey(key)))
return item;
}
return null;
}
private static string FormatBytes(long bytes)
{
const int scale = 1024;
string[] orders = new string[] { "GB", "MB", "KB", "Bytes" };
long max = (long)Math.Pow(scale, orders.Length - 1);
foreach (string order in orders)
{
if (bytes > max)
return string.Format("{0:##.##} {1}", decimal.Divide(bytes, max), order);
max /= scale;
}
return "0";
}
#endregion
#region GUI Event Handlers
private void buttonStartProxy_Click(object sender, EventArgs e)
{
if (buttonStartProxy.Text.StartsWith("Start") && m_ProxyRunning.Equals(false))
{
proxy = new ProxyManager(textBoxProxyPort.Text, comboBoxListenAddress.Text, comboBoxLoginURL.Text);
// disable any gui elements
comboBoxListenAddress.Enabled = textBoxProxyPort.Enabled = comboBoxLoginURL.Enabled = false;
InitProxyFilters();
proxy.Start();
loadFilterSelectionsToolStripMenuItem.Enabled = saveFilterSelectionsToolStripMenuItem.Enabled = true;
// enable any gui elements
toolStripSplitButton1.Enabled =
toolStripMenuItemPlugins.Enabled = grpUDPFilters.Enabled = grpCapsFilters.Enabled = m_ProxyRunning = true;
buttonStartProxy.Text = "Stop Proxy";
buttonStartProxy.Checked = true;
if (enableStatisticsToolStripMenuItem.Checked && !timer1.Enabled)
timer1.Enabled = true;
}
else if (buttonStartProxy.Text.StartsWith("Stop") && m_ProxyRunning.Equals(true))
{
loadFilterSelectionsToolStripMenuItem.Enabled = saveFilterSelectionsToolStripMenuItem.Enabled = false;
// stop the proxy
proxy.Stop();
toolStripMenuItemPlugins.Enabled = grpUDPFilters.Enabled = grpCapsFilters.Enabled = m_ProxyRunning = false;
buttonStartProxy.Text = "Start Proxy";
buttonStartProxy.Checked = false;
comboBoxListenAddress.Enabled = textBoxProxyPort.Enabled = comboBoxLoginURL.Enabled = true;
if (!enableStatisticsToolStripMenuItem.Checked && timer1.Enabled)
timer1.Enabled = false;
}
}
private void checkBoxCheckAllPackets_CheckedChanged(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewPacketFilters.Items)
{
item.Checked = checkBoxCheckAllPackets.Checked;
}
}
private void listViewSessions_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (e.IsSelected && listViewSessions.SelectedItems.Count == 1)
{
tabControlMain.SelectTab("tabPageInspect");
object tag = e.Item.Tag;
if (tag is Session)
{
Session session = (Session)tag;
treeViewXmlResponse.Nodes.Clear();
treeViewXMLRequest.Nodes.Clear();
Be.Windows.Forms.DynamicByteProvider responseBytes = new Be.Windows.Forms.DynamicByteProvider(session.ToBytes(Direction.Incoming));
richTextBoxDecodedResponse.Text = session.ToPrettyString(Direction.Incoming);
richTextBoxRawResponse.Text = session.ToRawString(Direction.Incoming);
richTextBoxNotationResponse.Text = session.ToStringNotation(Direction.Incoming);
hexBoxResponse.ByteProvider = responseBytes;
updateTreeView(session.ToXml(Direction.Incoming), treeViewXmlResponse);
Be.Windows.Forms.DynamicByteProvider requestBytes = new Be.Windows.Forms.DynamicByteProvider(session.ToBytes(Direction.Outgoing));
richTextBoxDecodedRequest.Text = session.ToPrettyString(Direction.Outgoing);
richTextBoxRawRequest.Text = session.ToRawString(Direction.Outgoing);
richTextBoxNotationRequest.Text = session.ToStringNotation(Direction.Outgoing);
hexBoxRequest.ByteProvider = requestBytes;
updateTreeView(session.ToXml(Direction.Outgoing), treeViewXMLRequest);
RequestPosition_Changed(this, EventArgs.Empty);
ReplyPosition_Changed(this, EventArgs.Empty);
}
else
{
richTextBoxDecodedResponse.Text = "Unknown data object encountered: " + tag.GetType().ToString();
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (m_ProxyRunning)
proxy.Stop();
if (saveOptionsOnExitToolStripMenuItem.Checked)
SaveAllSettings("settings.osd");
}
// select all items in session list
private void sessionSelectAll_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewSessions.Items)
{
item.Selected = true;
}
}
// unselect all items in session list
private void sessionSelectNone_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewSessions.Items)
{
item.Selected = false;
}
}
// invert selection
private void sessionInvertSelection_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewSessions.Items)
{
item.Selected = !item.Selected;
}
}
// remove all sessions
private void sessionRemoveAll_Click(object sender, EventArgs e)
{
listViewSessions.Items.Clear();
}
// remove sessions that are currently selected
private void sessionRemoveSelected_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewSessions.Items)
{
if (item.Selected)
listViewSessions.Items.Remove(item);
}
}
// remove sessions that are not currently selected
private void sessionRemoveUnselected_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewSessions.Items)
{
if (!item.Selected)
listViewSessions.Items.Remove(item);
}
}
// Colorize selected sessions
private void sessionMarkSelected_Click(object sender, EventArgs e)
{
ToolStripMenuItem menu = (ToolStripMenuItem)sender;
foreach (ListViewItem item in listViewSessions.Items)
{
if (item.Selected)
item.BackColor = Color.FromName(menu.Text);
}
sessionSelectNone_Click(sender, e);
}
// Unmark selected sessions
private void sessionUnmarkSelected_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewSessions.Items)
{
if (item.Selected)
item.BackColor = Color.White;
}
sessionSelectNone_Click(sender, e);
}
private void aboutWinGridProxyToolStripMenuItem_Click(object sender, EventArgs e)
{
AboutBox1 about = new AboutBox1();
about.ShowDialog();
}
// Update Request Hexbox status bar with current cursor location
private void RequestPosition_Changed(object sender, EventArgs e)
{
if (hexBoxRequest.ByteProvider != null)
{
labelHexRequestStatus.Text = String.Format("Ln {0} Col {1} bytes {2}",
hexBoxRequest.CurrentLine, hexBoxRequest.CurrentPositionInLine, hexBoxRequest.ByteProvider.Length);
buttonSaveRequestHex.Visible = (hexBoxRequest.ByteProvider.Length > 0);
}
buttonSaveRequestHex.Visible = (hexBoxRequest.ByteProvider != null && hexBoxRequest.ByteProvider.Length > 0);
}
// Update Response Hexbox status bar with current cursor location
void ReplyPosition_Changed(object sender, EventArgs e)
{
if (hexBoxResponse.ByteProvider != null)
{
labelHexBoxResponseStatus.Text = String.Format("Ln {0} Col {1} bytes {2}",
hexBoxResponse.CurrentLine, hexBoxResponse.CurrentPositionInLine, hexBoxResponse.ByteProvider.Length);
}
buttonExportRawHex.Visible = (hexBoxResponse.ByteProvider != null && hexBoxResponse.ByteProvider.Length > 0);
}
// select all specified sessions by packet name
private void sessionSelectAllPacketType_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewSessions.Items)
{
if (item.SubItems[3].Text.Equals(toolStripMenuItemSelectPacketName.Tag) && !item.Selected)
item.Selected = true;
}
}
// stop capturing selected filters
private void filterDisableByPacketName_CheckedChanged(object sender, EventArgs e)
{
if (enableDisableFilterByNameToolStripMenuItem.Tag != null)
{
ListViewItem found = FindListViewItem(listViewMessageFilters, enableDisableFilterByNameToolStripMenuItem.Tag.ToString(), false);
if (found != null)
{
listViewMessageFilters.Items[found.Index].Checked = enableDisableFilterByNameToolStripMenuItem.Checked;
}
else
{
found = FindListViewItem(listViewPacketFilters, enableDisableFilterByNameToolStripMenuItem.Tag.ToString(), false);
if (found != null)
listViewPacketFilters.Items[found.Index].Checked = enableDisableFilterByNameToolStripMenuItem.Checked;
}
}
}
/// <summary>
/// Setup the context menu prior to it being displayed with specific entries for filtering packets/messages
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void contextMenuStripSessions_Opening(object sender, CancelEventArgs e)
{
if (listViewSessions.SelectedItems.Count == 1)
{
ListViewItem item = listViewSessions.SelectedItems[0];
string strPacketOrMessage = (item.SubItems[2].Text.Equals(PROTO_PACKETSTRING)) ? "Packets" : "Messages";
enableDisableFilterByNameToolStripMenuItem.Text = String.Format("Capture {0} {1}", item.SubItems[3].Text, strPacketOrMessage);
toolStripMenuItemSelectPacketName.Tag = enableDisableFilterByNameToolStripMenuItem.Tag = item.SubItems[3].Text;
toolStripMenuItemSelectPacketName.Text = String.Format("All {0} {1}", item.SubItems[3].Text, strPacketOrMessage);
enableDisableFilterByNameToolStripMenuItem.Visible =
toolStripSeparatorSelectPacketProto.Visible =
toolStripSeparatorFilterPacketByName.Visible =
toolStripMenuItemSelectPacketName.Visible = true;
// find checkstate of selected menuitem in packets or messages filters checkedListBoxes
bool ctxChecked = false;
if (strPacketOrMessage.Equals("Packets"))
{
ListViewItem found = FindListViewItem(listViewPacketFilters, toolStripMenuItemSelectPacketName.Tag.ToString(), false);
if (found != null)
ctxChecked = found.Checked;
}
else if (strPacketOrMessage.Equals("Messages"))
{
ListViewItem found = FindListViewItem(listViewMessageFilters, toolStripMenuItemSelectPacketName.Tag.ToString(), false);
if (found != null)
ctxChecked = found.Checked;
}
enableDisableFilterByNameToolStripMenuItem.Checked = ctxChecked;
}
else
{
// Hide specific selection options on context menu
enableDisableFilterByNameToolStripMenuItem.Visible =
toolStripSeparatorSelectPacketProto.Visible =
toolStripSeparatorFilterPacketByName.Visible =
toolStripMenuItemSelectPacketName.Visible = false;
}
if (listViewSessions.Items.Count > 0)
{
markToolStripMenuItem2.Enabled =
findToolStripMenuItem1.Enabled =
toolStripMenuSessionsRemove.Enabled =
selectToolStripMenuItem2.Enabled = true;
}
else
{
markToolStripMenuItem2.Enabled =
findToolStripMenuItem1.Enabled =
toolStripMenuSessionsRemove.Enabled =
selectToolStripMenuItem2.Enabled = false;
}
}
private void findSessions_Click(object sender, EventArgs e)
{
FilterOptions opts = new FilterOptions((listViewSessions.SelectedItems.Count > 0));
FormSessionSearch search = new FormSessionSearch(ref opts);
search.ShowDialog();
if (!String.IsNullOrEmpty(opts.SearchText))
{
Thread sThread = new Thread(delegate()
{
SearchSessions(opts);
});
sThread.Name = "Search";
sThread.Start();
}
}
// Enable Inject button if box contains text
private void richTextBoxInject_TextChanged(object sender, EventArgs e)
{
buttonInjectPacket.Enabled = (richTextBoxInject.TextLength > 0);
}
private void buttonInjectPacket_Click(object sender, EventArgs e)
{
proxy.InjectPacket(richTextBoxInject.Text, true);
}
private void saveFilterSelectionsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (saveFileDialog2.ShowDialog() == DialogResult.OK)
{
SaveAllSettings(saveFileDialog2.FileName);
}
}
private void loadFilterSelectionsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (openFileDialog2.ShowDialog() == DialogResult.OK)
{
RestoreSavedSettings(openFileDialog2.FileName);
if (listViewSessions.Items.Count > 0)
{
if (MessageBox.Show("Would you like to apply these settings to the current session list?",
"Apply Filter", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
{
listViewSessions.BeginUpdate();
foreach (ListViewItem item in listViewSessions.Items)
{
ListViewItem found = FindListViewItem(listViewPacketFilters, item.SubItems[3].Text, false);
if (found == null)
found = FindListViewItem(listViewMessageFilters, item.SubItems[3].Text, false);
if (found != null && !found.Checked)
listViewSessions.Items.Remove(item);
}
listViewSessions.EndUpdate();
}
}
}
}
private void listViewMessageFilters_ItemChecked(object sender, ItemCheckedEventArgs e)
{
proxy.AddCapsDelegate(e.Item.Text, e.Item.Checked);
}
private void listViewPacketFilters_ItemChecked(object sender, ItemCheckedEventArgs e)
{
if (e.Item.Group.Name.Equals("Packets"))
proxy.AddUDPDelegate(PacketTypeFromName(e.Item.Text), e.Item.Checked);
}
private void checkBoxCheckallCaps_CheckedChanged(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewMessageFilters.Items)
{
item.Checked = checkBoxCheckAllMessages.Checked;
}
}
/// <summary>
/// Start/Stop the statistics gathering timer
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void enableStatisticsToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
{
if (timer1.Enabled && !enableStatisticsToolStripMenuItem.Checked)
timer1.Enabled = false;
if (!timer1.Enabled && enableStatisticsToolStripMenuItem.Checked)
timer1.Enabled = true;
}
private void saveSessionArchiveToolStripMenuItem_Click(object sender, EventArgs e)
{
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
OSDMap map = new OSDMap(1);
OSDArray sessionArray = new OSDArray();
foreach (ListViewItem item in listViewSessions.Items)
{
if (item.Tag is Session)
{
Session data = null;
if (item.Tag is SessionCaps)
{
data = (SessionCaps)item.Tag;
}
else if (item.Tag is SessionEvent)
{
data = (SessionEvent)item.Tag;
}
else if (item.Tag is SessionLogin)
{
data = (SessionLogin)item.Tag;
}
else if (item.Tag is SessionPacket)
{
data = (SessionPacket)item.Tag;
}
else
{
Console.WriteLine("Not a valid session type?");
continue;
}
//Type t = item.Tag.GetType();
//Session data = (SessionCaps)item.Tag;
OSDMap session = new OSDMap();
//session["name"] = OSD.FromString(item.Name);
//session["image_index"] = OSD.FromInteger(item.ImageIndex);
session["id"] = OSD.FromString(item.SubItems[0].Text);
//session["protocol"] = OSD.FromString(item.SubItems[1].Text);
//session["packet"] = OSD.FromString(item.SubItems[2].Text);
//session["size"] = OSD.FromString(item.SubItems[3].Text);
//session["host"] = OSD.FromString(item.SubItems[4].Text);
session["type"] = OSD.FromString(data.GetType().ToString());
session["tag"] = OSD.FromBinary(data.Serialize());
sessionArray.Add(session);
}
}
map["sessions"] = sessionArray;
try
{
File.WriteAllText(saveFileDialog1.FileName, map.ToString());
}
catch (Exception ex)
{
MessageBox.Show("Exception occurred trying to save session archive: " + ex);
}
}
}
private void loadSessionArchiveToolStripMenuItem_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
OSDMap map = (OSDMap)OSDParser.DeserializeLLSDNotation(File.ReadAllText(openFileDialog1.FileName));
OSDArray sessionsArray = (OSDArray)map["sessions"];
listViewSessions.Items.Clear();
listViewSessions.BeginUpdate();
for (int i = 0; i < sessionsArray.Count; i++)
{
OSDMap session = (OSDMap)sessionsArray[i];
Session importedSession = (Session)m_CurrentAssembly.CreateInstance(session["type"].AsString());
importedSession.Deserialize(session["tag"].AsBinary());
ListViewItem addedItem = new ListViewItem(new string[] {
session["id"].AsString(),
importedSession.TimeStamp.ToString("HH:mm:ss.fff"),
importedSession.Protocol,
importedSession.Name,
importedSession.Length.ToString(),
importedSession.Host,
importedSession.ContentType});
AddSession(addedItem);
//addedItem.ImageIndex = session["image_index"].AsInteger();
addedItem.ImageIndex = (int)importedSession.Direction;
addedItem.BackColor = Color.GhostWhite; // give imported items a different color
addedItem.Tag = importedSession;
}
listViewSessions.EndUpdate();
}
}
//Generic ListView sort event used by filter listviews only
private void listViewFilterSorter_ColumnClick(object sender, ColumnClickEventArgs e)
{
ListView lv = (ListView)sender;
ListViewItemComparer columnSorter = new ListViewItemComparer();
columnSorter.column = e.Column;
if ((columnSorter.bAscending = (lv.Sorting == SortOrder.Ascending)))
lv.Sorting = SortOrder.Descending;
else
lv.Sorting = SortOrder.Ascending;
lv.ListViewItemSorter = columnSorter as IComparer;
}
private void exitToolStripMenuItem1_Click(object sender, EventArgs e)
{
// TODO: warn if client is connected!
this.Close();
}
#endregion GUI Event Handlers
#region Helpers
private void SaveAllSettings(string fileName)
{
Store.MessageSessions.Clear();
Store.PacketSessions.Clear();
foreach (ListViewItem item in listViewPacketFilters.Items)
{
FilterEntryOptions entry = new FilterEntryOptions();
entry.Checked = item.Checked;
entry.Type = item.SubItems[1].Text;
entry.Group = item.Group.Name;
if (!Store.PacketSessions.ContainsKey(item.Text))
Store.PacketSessions.Add(item.Text, entry);
}
foreach (ListViewItem item in listViewMessageFilters.Items)
{
FilterEntryOptions entry = new FilterEntryOptions();
entry.Checked = item.Checked;
entry.Type = item.SubItems[1].Text;
entry.Group = item.Group.Name;
if (!Store.MessageSessions.ContainsKey(item.Text))
Store.MessageSessions.Add(item.Text, entry);
}
Store.StatisticsEnabled = enableStatisticsToolStripMenuItem.Checked;
Store.SaveSessionOnExit = saveOptionsOnExitToolStripMenuItem.Checked;
Store.AutoCheckNewCaps = autoAddNewDiscoveredMessagesToolStripMenuItem.Checked;
Store.SerializeToFile(fileName);
}
private void RestoreSavedSettings(string fileName)
{
// load saved settings from OSD Formatted file
if (Store.DeserializeFromFile(fileName))
{
enableStatisticsToolStripMenuItem.Checked = Store.StatisticsEnabled;
saveOptionsOnExitToolStripMenuItem.Checked = Store.SaveSessionOnExit;
autoAddNewDiscoveredMessagesToolStripMenuItem.Checked = Store.AutoCheckNewCaps;
// Update message filter listview
listViewMessageFilters.BeginUpdate();
foreach (KeyValuePair<string, FilterEntryOptions> kvp in Store.MessageSessions)
{
ListViewItem foundMessage = FindListViewItem(listViewPacketFilters, kvp.Key, false);
if (foundMessage == null)
{
ListViewItem addedItem = listViewMessageFilters.Items.Add(
new ListViewItem(kvp.Key, listViewMessageFilters.Groups[kvp.Value.Group]));
addedItem.Name = kvp.Key;
addedItem.Checked = kvp.Value.Checked;
addedItem.SubItems.Add(kvp.Value.Type);
//addedItem.Group = listViewMessageFilters.Groups[kvp.Value.Group];
addedItem.BackColor = (kvp.Value.Type.Equals(PROTO_CAPABILITIES)) ? Color_Cap : Color_Event;
}
else
{
foundMessage.Checked = kvp.Value.Checked;
}
if (kvp.Value.Type.Equals(PROTO_CAPABILITIES))
{
proxy.AddCapsDelegate(kvp.Key, kvp.Value.Checked);
}
}
listViewMessageFilters.EndUpdate();
// updateTreeView packet filter listview
listViewPacketFilters.BeginUpdate();
foreach (KeyValuePair<string, FilterEntryOptions> kvp in Store.PacketSessions)
{
ListViewItem foundPacket = FindListViewItem(listViewPacketFilters, kvp.Key, false);
if (foundPacket == null)
{
ListViewItem addedItem = listViewPacketFilters.Items.Add(
new ListViewItem(kvp.Key, listViewPacketFilters.Groups[kvp.Value.Group]));
addedItem.Name = kvp.Key;
addedItem.Checked = kvp.Value.Checked;
addedItem.SubItems.Add(kvp.Value.Type);
addedItem.BackColor = (kvp.Value.Type.Equals(PROTO_AUTHENTICATE)) ? Color_Login : Color_Packet;
}
else
{
foundPacket.Checked = kvp.Value.Checked;
}
if (kvp.Value.Type.Equals(PROTO_PACKETSTRING))
{
proxy.AddUDPDelegate(PacketTypeFromName(kvp.Key), kvp.Value.Checked);
}
}
listViewPacketFilters.EndUpdate();
}
}
private void InitProxyFilters()
{
RestoreSavedSettings("settings.osd");
listViewPacketFilters.BeginUpdate();
foreach (string name in Enum.GetNames(typeof(PacketType)))
{
ListViewItem found = FindListViewItem(listViewPacketFilters, name, false);
if (!String.IsNullOrEmpty(name) && found == null)
{
ListViewItem addedItem = listViewPacketFilters.Items.Add(new ListViewItem(name, listViewPacketFilters.Groups["Packets"]));
addedItem.Name = name;
addedItem.SubItems.Add(PROTO_PACKETSTRING);
}
}
ListViewItem tmp;
if (!listViewPacketFilters.Items.ContainsKey("Login Request"))
{
tmp = listViewPacketFilters.Items.Add(new ListViewItem("Login Request", listViewPacketFilters.Groups["Login"]));
tmp.Name = "Login Request";
tmp.BackColor = Color_Login;
tmp.SubItems.Add("Login");
}
if (!listViewPacketFilters.Items.ContainsKey("Login Response"))
{
tmp = listViewPacketFilters.Items.Add(new ListViewItem("Login Response", listViewPacketFilters.Groups["Login"]));
tmp.Name = "Login Response";
tmp.BackColor = Color_Login;
tmp.SubItems.Add("Login");
}
listViewPacketFilters.EndUpdate();
}
private static PacketType PacketTypeFromName(string name)
{
Type packetTypeType = typeof(PacketType);
System.Reflection.FieldInfo f = packetTypeType.GetField(name);
if (f == null)
{//throw new ArgumentException("Bad packet type");
return PacketType.Error;
}
return (PacketType)Enum.ToObject(packetTypeType, (int)f.GetValue(packetTypeType));
}
private void SearchSessions(FilterOptions opts)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(() => SearchSessions(opts)));
}
else
{
int resultCount = 0;
foreach (ListViewItem item in listViewSessions.Items)
{
if (opts.UnMarkPrevious)
item.BackColor = Color.White;
if (opts.SearchSelected && !item.Selected)
{
continue;
}
if (
(opts.MatchCase
&& (item.SubItems[3].Text.Contains(opts.SearchText)
/*|| TagToString(item.Tag, item.SubItems[2].Text).Contains(opts.SearchText)*/)
) // no case matching
|| ((item.SubItems[3].Text.ToLower().Contains(opts.SearchText.ToLower())
/*|| TagToString(item.Tag, item.SubItems[2].Text).ToLower().Contains(opts.SearchText.ToLower())*/
))
)
{
resultCount++;
if (opts.MarkMatches)
item.BackColor = opts.HighlightMatchColor;
if (opts.SelectResults)
item.Selected = true;
else
item.Selected = false;
}
}
//toolStripMainLabel.Text = String.Format("Search found {0} Matches", resultCount);
}
}
#endregion
#region XML Tree
private void updateTreeView(string xml, TreeView treeView)
{
try
{
treeView.Nodes.Clear();
XmlDocument tmpxmldoc = new XmlDocument();
tmpxmldoc.LoadXml(xml);
FillTree(tmpxmldoc.DocumentElement, treeView.Nodes);
treeView.ExpandAll();
}
catch (Exception ex)
{
Console.WriteLine("Error during xml conversion:" + ex.Message);
}
}
private void FillTree(XmlNode node, TreeNodeCollection parentnode)
{
// End recursion if the node is a text type
if (node == null || node.NodeType == XmlNodeType.Text || node.NodeType == XmlNodeType.CDATA)
return;
TreeNodeCollection tmptreenodecollection = AddNodeToTree(node, parentnode);
// Add all the children of the current node to the treeview
foreach (XmlNode tmpchildnode in node.ChildNodes)
{
FillTree(tmpchildnode, tmptreenodecollection);
}
}
private TreeNodeCollection AddNodeToTree(XmlNode node, TreeNodeCollection parentnode)
{
TreeNode newchildnode = CreateTreeNodeFromXmlNode(node);
// if nothing to add, return the parent item
if (newchildnode == null) return parentnode;
// add the newly created tree node to its parent
if (parentnode != null) parentnode.Add(newchildnode);
return newchildnode.Nodes;
}
private TreeNode CreateTreeNodeFromXmlNode(XmlNode node)
{
TreeNode tmptreenode = new TreeNode();
if ((node.HasChildNodes) && (node.FirstChild.Value != null))
{
tmptreenode = new TreeNode(node.Name);
TreeNode tmptreenode2 = new TreeNode(node.FirstChild.Value);
tmptreenode.Nodes.Add(tmptreenode2);
}
else if (node.NodeType != XmlNodeType.CDATA)
{
tmptreenode = new TreeNode(node.Name);
}
return tmptreenode;
}
#endregion
#region Timers
private void timer1_Tick(object sender, EventArgs e)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(() => timer1_Tick(sender, e)));
}
else
{
label1PacketsOut.Text = String.Format("{0} ({1} bytes)", PacketsOutCounter, PacketsOutBytes);
labelPacketsIn.Text = String.Format("{0} ({1} bytes)", PacketsInCounter, PacketsInBytes);
labelPacketsTotal.Text = String.Format("{0} ({1} bytes)", PacketsOutCounter + PacketsInCounter, PacketsOutBytes + PacketsInBytes);
labelCapsIn.Text = String.Format("{0} ({1} bytes)", CapsInCounter, CapsInBytes);
labelCapsOut.Text = String.Format("{0} ({1} bytes)", CapsOutCounter, CapsOutBytes);
labelCapsTotal.Text = String.Format("{0} ({1} bytes)", CapsInCounter + CapsOutCounter, CapsOutBytes + CapsInBytes);
}
}
private void timerSessionQueue_Tick(object sender, EventArgs e)
{
lock (QueuedSessions)
{
if (QueuedSessions.Count > 0)
{
listViewSessions.BeginUpdate();
listViewSessions.Items.AddRange(QueuedSessions.ToArray());
if (listViewSessions.Items.Count > 0 && autoscrollToolStripMenuItem.Checked)
{
listViewSessions.Items[listViewSessions.Items.Count - 1].EnsureVisible();
}
listViewSessions.EndUpdate();
QueuedSessions.Clear();
}
}
}
#endregion
private void EditToolStripButton_DropDownOpening(object sender, EventArgs e)
{
if (listViewSessions.Items.Count > 0)
{
toolStripMenuSessionsRemove.Enabled =
removeToolStripMenuItem2.Enabled =
selectToolStripMenuItem1.Enabled =
saveSessionArchiveToolStripMenuItem.Enabled =
toolStripMenuItemRemoveAll.Enabled = true;
if (listViewSessions.SelectedItems.Count < listViewSessions.Items.Count)
{
toolStripMenuItemRemoveUnselected.Enabled = true;
}
else
{
toolStripMenuItemRemoveUnselected.Enabled = false;
}
if (listViewSessions.SelectedItems.Count > 0)
{
markToolStripMenuItem1.Enabled =
toolStripSeparatorSelectPacketProto.Visible =
toolStripMenuItemSelectPacketName.Visible =
noneToolStripMenuItem2.Enabled =
copyToolStripMenuItem1.Enabled =
toolStripMenuItemRemoveSelected.Enabled = true;
}
else
{
markToolStripMenuItem1.Enabled =
toolStripSeparatorSelectPacketProto.Visible =
toolStripMenuItemSelectPacketName.Visible =
noneToolStripMenuItem2.Enabled =
noneToolStripMenuItem2.Enabled =
copyToolStripMenuItem1.Enabled =
toolStripMenuItemRemoveSelected.Enabled = false;
}
if (listViewSessions.SelectedItems.Count > 0
&& listViewSessions.SelectedItems.Count != listViewSessions.Items.Count)
{
toolStripMenuItemRemoveUnselected.Enabled =
invertToolStripMenuItem1.Enabled =
noneToolStripMenuItem2.Enabled = true;
}
else
{
toolStripMenuItemRemoveUnselected.Enabled =
invertToolStripMenuItem1.Enabled =
noneToolStripMenuItem2.Enabled = false;
}
}
else
{
toolStripMenuSessionsRemove.Enabled =
toolStripSeparatorSelectPacketProto.Visible =
// toolStripMenuItemSelectProtocol.Visible =
toolStripMenuItemSelectPacketName.Visible =
findToolStripMenuItem.Enabled =
selectToolStripMenuItem1.Enabled =
removeToolStripMenuItem2.Enabled =
toolStripMenuItemRemoveUnselected.Enabled =
copyToolStripMenuItem1.Enabled =
markToolStripMenuItem1.Enabled =
saveSessionArchiveToolStripMenuItem.Enabled =
toolStripMenuItemRemoveAll.Enabled = false;
}
if (listViewPacketFilters.Items.Count + listViewSessions.Items.Count > 0)
{
saveFilterSelectionsToolStripMenuItem.Enabled = true;
}
else
{
saveFilterSelectionsToolStripMenuItem.Enabled = false;
}
}
private void autoColorizeToolStripMenuItem_Click(object sender, EventArgs e)
{
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
//listview.BackColor = colorDialog1.Color;
}
}
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
if (pluginManager == null)
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(() => 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;
// don't colorize xml!
if (m_rtb.Lines.Length <= 0 || m_rtb.Lines[0].StartsWith("<?xml"))
return;
Regex typesRegex = new Regex(@"\[(?<Type>\w+|\w+\[\])\]|\((?<Enum>.*)\)|\s-- (?<Header>\w+|\w+ \[\]) --\s|(?<BlockSep>\s\*\*\*\s)|(?<Tag>\s<\w+>\s|\s<\/\w+>\s)|(?<BlockCounter>\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.FromArgb(43, 145, 175);
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;
}
}
private void AddSession(ListViewItem item)
{
lock (QueuedSessions)
{
QueuedSessions.Add(item);
}
}
private void asDecodedTextToolStripMenuItem_Click(object sender, EventArgs e)
{
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
StringBuilder outString = new StringBuilder();
foreach (ListViewItem item in listViewSessions.Items)
{
if (item.Tag is Packet)
{
//outString.AppendLine(DecodePacket.PacketToString((Packet)item.Tag));
outString.AppendLine(PacketDecoder.PacketToString((Packet)item.Tag));
}
if (item.Tag is IMessage)
{
IMessage msg = (IMessage)item.Tag;
outString.AppendLine(msg.Serialize().ToString());
}
try
{
File.WriteAllText(saveFileDialog1.FileName, outString.ToString());
}
catch (Exception ex)
{
MessageBox.Show("Exception occurred trying to save session archive: " + ex);
}
}
}
}
private void richTextBoxDecodedRequest_LinkClicked(object sender, LinkClickedEventArgs e)
{
System.Diagnostics.Process.Start(e.LinkText);
}
private void saveSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
SaveAllSettings("settings.osd");
}
// Column sorter
private void listViewSessions_ColumnClick(object sender, ColumnClickEventArgs e)
{
ListView listView1 = (ListView)sender;
ListViewSorter Sorter = new ListViewSorter();
listView1.ListViewItemSorter = Sorter;
if (!(listView1.ListViewItemSorter is ListViewSorter))
return;
Sorter = (ListViewSorter)listView1.ListViewItemSorter;
if (Sorter.LastSort == e.Column)
{
if (listView1.Sorting == SortOrder.Ascending)
listView1.Sorting = SortOrder.Descending;
else
listView1.Sorting = SortOrder.Ascending;
}
else
{
listView1.Sorting = SortOrder.Descending;
}
Sorter.ByColumn = e.Column;
listView1.Sort();
listView1.Columns[e.Column].Width = -2;// = listView1.Columns[e.Column].Text + " " + '\u23BC';
}
private void buttonSaveRequestHex_Click(object sender, EventArgs e)
{
if (hexBoxRequest.ByteProvider != null && hexBoxRequest.ByteProvider.Length > 0)
{
saveFileDialog3.FileName = listViewSessions.SelectedItems[0].Name;
if (saveFileDialog3.ShowDialog() == DialogResult.OK)
{
byte[] bytes = new byte[hexBoxRequest.ByteProvider.Length];
for (int i = 0; i < hexBoxRequest.ByteProvider.Length; i++)
{
bytes[i] = hexBoxRequest.ByteProvider.ReadByte(i);
}
File.WriteAllBytes(saveFileDialog3.FileName, bytes);
}
}
}
private void buttonExportRawHex_Click(object sender, EventArgs e)
{
if (hexBoxResponse.ByteProvider != null && hexBoxResponse.ByteProvider.Length > 0)
{
saveFileDialog3.FileName = listViewSessions.SelectedItems[0].Name;
if (saveFileDialog3.ShowDialog() == DialogResult.OK)
{
byte[] bytes = new byte[hexBoxResponse.ByteProvider.Length];
for (int i = 0; i < hexBoxResponse.ByteProvider.Length; i++)
{
bytes[i] = hexBoxResponse.ByteProvider.ReadByte(i);
}
File.WriteAllBytes(saveFileDialog3.FileName, bytes);
}
}
else
{
// no bytes to read!
}
}
}
public class ListViewSorter : System.Collections.IComparer
{
public int Compare(object o1, object o2)
{
if (!(o1 is ListViewItem))
return 0;
if (!(o2 is ListViewItem))
return 0;
int result;
ListViewItem lvi1 = (ListViewItem)o2;
ListViewItem lvi2 = (ListViewItem)o1;
if (lvi1.ListView.Columns[ByColumn].Tag == null
|| lvi1.ListView.Columns[ByColumn].Tag == null)
{
return 0;
}
if (lvi1.ListView.Columns[ByColumn].Tag.ToString().ToLower().Equals("number"))
{
float fl1 = float.Parse(lvi1.SubItems[ByColumn].Text);
float fl2 = float.Parse(lvi2.SubItems[ByColumn].Text);
if (lvi1.ListView.Sorting == SortOrder.Ascending)
result = fl1.CompareTo(fl2);
else
result = fl2.CompareTo(fl1);
}
else if (lvi1.ListView.Columns[ByColumn].Tag.ToString().ToLower().Equals("string"))
{
string str1 = lvi1.SubItems[ByColumn].Text;
string str2 = lvi2.SubItems[ByColumn].Text;
if (lvi1.ListView.Sorting == SortOrder.Ascending)
result = String.Compare(str1, str2);
else
result = String.Compare(str2, str1);
}
else
{
return 0;
}
LastSort = ByColumn;
return (result);
}
public int ByColumn
{
get { return Column; }
set { Column = value; }
}
int Column = 0;
public int LastSort
{
get { return LastColumn; }
set { LastColumn = value; }
}
int LastColumn = 0;
}
}