//////////////////////////////////////////////////////////////// // // Copyright (c) 2007-2010 MetaGeek, LLC // // 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. // //////////////////////////////////////////////////////////////// // =================================================================== // This code was originally written by: // Charles Putney // 18 Quinns Road // Shankill // Co. Dublin // IRELAND // // Charles released the code to CodeProject on June 22, 2007 // Norman Rasmussed updated the code to add Native Wi-Fi API support // (Charles had used the "netscan" command) on August 10, 2007 // // The code has since been heavily modified and specialized for Inssider // by Ryan Woodings at MetaGeek, LLC (ryan@metageek.net). Modifications // include adding the graph, and changing the data table from a ListView // to a DataGridView to allow better data manipulation (sorting, etc) // =================================================================== using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; using System.Diagnostics; using System.IO; using System.Drawing; using System.Text; using NativeWifi; using System.Timers; using System.Net.NetworkInformation; using Inssider.Properties; using Microsoft.Win32; using MetaGeek.IoctlNdis; using System.Globalization; using System.ComponentModel; using System.Collections; using System.Xml; using System.Reflection; namespace Inssider { public delegate void NetworkScanStateHandler(bool enabled); public partial class ScannerForm : Form { #region Constants private const int MIN_NON_GRID_VERTICAL = 262; private const int UPDATE_HIGHLIGHT_INTERVAL = 300; private const int UPDATE_LIST_INTERVAL = 2500; internal const int USES_BETWEEN_UPDATE_REMINDER = 5; private const int MAX_SCAN_FAIL_COUNT = 2; #endregion #region Private Variables // UI network data private List _networks = new List(); // network scanning thread private Thread _scanThread; // timestamp for the last scan private DateTime _lastScanTimeStamp = DateTime.MinValue; // timestamp for when the last data was updated on the UI private DateTime _lastDrawnTimeStamp = DateTime.MinValue; // timer for updating the UI private System.Timers.Timer _viewUpdateTimer; // flag for starting a new selection private bool _newSelection = false; private bool _ignoreSelection = false; // flag for automatically resizing grid private bool _autoResize = true; // application abort flag private bool _abort = false; // currently selected network interface private NetworkInterface _interface = null; // Scanner thread terminate event private AutoResetEvent _terminateNetworkScan = new AutoResetEvent(false); // flag for catching suspend/resume private bool _scanSuspended = false; ElapsedEventHandler updateViewHandler; ElapsedEventHandler updateListHandler; private int _scanFailedCounter = 0; // Checkbox for the "select all networks" private CheckBox selectAllNetworksCheckBox; //To delay set window location settings private bool _canSet = false; private delegate void updateTextCall(string input); // XML Log File private XmlDocument _dataLog = null; private string _logFilename; private string _xmlHeader = @""; private DateTime logTime = DateTime.Now; delegate void SetGPSCallback(); private Gps _gps = null; private Vendors _vendors = new Vendors(); #endregion #region Constructors /// /// Creates a new instance of the ScannerForm, which is the main application /// form. /// public ScannerForm() { String culture = String.Empty; //culture = "es-es"; //culture = "zh-TW"; //culture = "ja-JP"; //culture = "de-DE"; //culture = "sv-SE"; //culture = "ru-RU"; if ((culture != null) && (culture != String.Empty)) { CultureInfo ci = new CultureInfo(culture); // set culture for formatting Thread.CurrentThread.CurrentCulture = ci; // set culture for resources Thread.CurrentThread.CurrentUICulture = ci; } // // Check for the correct operating environment // CheckEnvironment(); // // Initialize components on the form. // InitializeComponent(); _gps = new Gps(); _gps.GpsTimeout += new EventHandler(GpsTimeout); _gps.GpsUpdated += new EventHandler(GpsUpdated); SelectStartImage(); #if CRASH crashToolStripMenuItem.Visible = true; crashToolStripMenuItem.Enabled = true; #endif UpdateNetworkScanState(false); SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged); channelGraph.Networks = _networks; // // Initialize the UI update thread // updateViewHandler = new ElapsedEventHandler(UpdateDataGrid); updateListHandler = new ElapsedEventHandler(updateInterfaceList); _viewUpdateTimer = new System.Timers.Timer(UPDATE_LIST_INTERVAL); _viewUpdateTimer.AutoReset = true; _viewUpdateTimer.SynchronizingObject = this; _viewUpdateTimer.Elapsed += updateListHandler; } #endregion #region Environment and NIC Selection Methods /// /// Checks for supported operating systems /// private void CheckEnvironment() { //int wordSize = IntPtr.Size; //if (wordSize > 4) { // ShowError(Localizer.GetString("x64Error")); // Application.Exit(); //} int major = System.Environment.OSVersion.Version.Major; int minor = System.Environment.OSVersion.Version.Minor; if (!((major == 5 && minor >= 1) || (major == 6))) { ShowError(Localizer.GetString("UnsupportedOsError")); Application.Exit(); } } /// /// Returns a wireless interface class that wraps the /// wlan query functionality. /// /// a WirelessInterface object private WirelessInterface GetInterface() { WirelessInterface wirelessInterface = null; try { wirelessInterface = WirelessInterface.Create(_interface); } catch (ApplicationException ex) { ShowError(Localizer.GetString("UnsupportedInterfaceError") + " {0}", ex.Message); } catch (Win32Exception ex) { ShowError(Localizer.GetString("UnsupportedInterfaceError") + " {0}", ex.Message); } return (wirelessInterface); } // End GetInterface() /// /// This method is a Timer event handler that updates the data /// grid with the current network information. /// /// not used /// not used private void updateInterfaceList(object source, ElapsedEventArgs e) { LoadInterfaceList(); } /// /// Presents the user with a dialog box that allows the user to download the /// Native wirless API. /// private void ShowDownloadDllMessage() { DialogResult status = MessageBox.Show(Localizer.GetString("DownloadWirelessLanApi"), Localizer.GetString("MissingDll"), MessageBoxButtons.YesNo, MessageBoxIcon.Error); if (status == DialogResult.Yes) { Process downloadProc = Process.Start("http://support.microsoft.com/kb/918997"); downloadProc.WaitForExit(); } } /// /// Presents the user with an error dialog box. /// /// format string /// format arguments private void ShowError(string format, params object[] args) { string messageText = String.Format(format, args); MessageBox.Show(messageText, Localizer.GetString("ApplicationError"), MessageBoxButtons.OK, MessageBoxIcon.Error); } /// /// Presents the user with a dialog box that includes the /// error information. /// /// Exception object private void ShowException(Exception ex) { MessageBox.Show(Localizer.GetString("ExceptionMessage") + ex.Message, Localizer.GetString("ApplicationError"), MessageBoxButtons.OK, MessageBoxIcon.Warning); } private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) { switch (e.Mode) { case PowerModes.Suspend: StopScanning(); break; } } private void LoadInterfaceList() { string selectedName = string.Empty; NetworkInterface[] interfaces = null; // // Get a list of wireless network interfaces. // #if !DEBUG try { #endif interfaces = NetworkInterface.GetAllNetworkInterfaces(); #if !DEBUG } catch { // hopefully it will work the next time } #endif #if DEBUG foreach (NetworkInterface netif in interfaces) { Console.WriteLine(netif); } #endif NetworkInterface selectedInterface = (NetworkInterface)interfaceList.SelectedItem; if (selectedInterface != null) { selectedName = selectedInterface.Name; } else { selectedName = Settings.Default.PreviousInterfaceName; } // // Populate the drop down list // interfaceList.DataSource = interfaces; interfaceList.DisplayMember = "Description"; foreach (NetworkInterface netInterface in interfaceList.Items) { if (netInterface.Name == selectedName) { interfaceList.SelectedItem = netInterface; break; } } } // End LoadInterfaceList() /// /// Checks for update and displays update dialog if there is an update available /// /// False to display dialog saying no update... private void CheckForUpdate(bool silentIfNoUpdate) { if (VersionInfo.CheckForAvailableUpdate(Localizer.GetString("VersionURL"), Settings.Default.IgnoreUpdateVersion)) { DialogResult result = VersionInfo.ShowUpdateDialog(); switch (result) { case DialogResult.OK: try { Process.Start(VersionInfo.DownloadUrl); this.Close(); } catch (Win32Exception) { } break; case DialogResult.Cancel: Settings.Default.NextUpdateCheck = DateTime.Now + VersionInfo.TimeBetweenReminders; break; case DialogResult.Ignore: Settings.Default.IgnoreUpdateVersion = VersionInfo.LatestVersion; break; } } else { Settings.Default.NextUpdateCheck = DateTime.Now + TimeSpan.FromDays(1); if (!silentIfNoUpdate) { MessageBox.Show(Localizer.GetString("LatestVersionAlreadyInstalled", VersionInfo.LatestVersion)); } } } #endregion #region Network Scanning Methods /// /// This method is the entry point for the network scanning thread. Its /// purpose is to periodically scan the wireless environment and collect /// network information. /// private void ScanNetworks() { // // Grab a wireless interface. // WirelessInterface wirelessInterface = GetInterface(); if (null == wirelessInterface) { return; } // // Begin the main network scanning loop. // do { try { // // Timestamp the last network scan, so we can keep track of // when networks come and go. // _lastScanTimeStamp = DateTime.Now; // // Get the network information from the interface. // if (_scanSuspended) { // grab the interface again... it is lost during suspend/resume wirelessInterface = GetInterface(); if (null == wirelessInterface) { MessageBox.Show(Localizer.GetString("WirelessCardRemoved")); } _scanSuspended = false; } List detailList = wirelessInterface.GetWirelessDetails(); // // Scan for available network information. // wirelessInterface.ScanNetworks(); // // Update the UI network data // UpdateNetworkList(detailList); // // Plot the RSSI values for each of the networks. // UpdateTimeGraph(); if (Settings.Default.DisplayChannelGraph) { channelGraph.Invalidate(); } //Writes an entry in the log. This is programmed the lazy/slow way by appending to InnerXml if (Settings.Default.isLogging) { writeLogEntry(detailList); } // If we finish the loop, reset the failed scan counter _scanFailedCounter = 0; } catch (Win32Exception ex) { ShowError("Unable to continue scanning with selected interface: {0}", ex.Message); StopScanning(false); break; } catch (ThreadAbortException) { break; } catch (Exception ex) { ExceptionForm.ShowException(ex); } } while (!_terminateNetworkScan.WaitOne(Settings.Default.NetworkScanRate, false)); } // End ScanNetworks() /// /// This method copies the data from the detail list returned by the adapter /// to the local UI network list. /// /// list of WirelessDetails objects read from the /// wireles adapter. private void UpdateNetworkList(List detailList) { bool visible = (selectAllNetworksCheckBox.CheckState == CheckState.Checked); foreach (WirelessDetails detailItem in detailList) { // // Attempt to find the current network in the cached UI data. If // a ScannerNetwork is not found, then a new object must be added // to the list, so its data will be presented on the UI. // ScannerNetwork network = FindScannerNetwork(detailItem.MacAddress); if (null == network) { string vendor = _vendors.GetVendor(detailItem.MacAddress); network = ScannerNetwork.Create(detailItem, vendor, _lastScanTimeStamp, visible); lock (_networks) { _networks.Add(network); } } else { // // A ScannerNetwork was found in the UI data, so // update its current signal value. Sometimes it has a rollover issue and // shows low signals as super strong... // if (detailItem.Rssi < 0) { network.Signal = detailItem.Rssi; } else { network.Signal = detailItem.Rssi - 256; } network.LastSeenTimeStamp = _lastScanTimeStamp; // update Channel too... it's possible that the AP changed channels... (although unlikely) network.Channel = detailItem.Channel; } } }// End UpdateNetworkList() /// /// Attempts to find a ScannerNetwork with the given MAC /// address string. /// /// MAC address of the network to find /// a ScannerNetwork object if found, null otherwise private ScannerNetwork FindScannerNetwork(MacAddress macAddress) { lock (_networks) { foreach (ScannerNetwork network in this._networks) { if (network.MacAddress.Equals(macAddress)) { return network; } } } return null; }// End FindScannerNetwork() /// /// Starts the network scanning thread /// private void StartScanning() { startImageLabel.Visible = false; hideStartImageLabel.Visible = false; bottomPanel.Dock = DockStyle.Fill; bottomPanel.Visible = true; _interface = (interfaceList.SelectedItem as NetworkInterface); if (null != _interface) { try { // TUT: check whether we can open the selected // interface before we start the scan thread WirelessInterface tmpIF = GetInterface(); if (null == tmpIF) { return; } } catch (System.DllNotFoundException) { ShowDownloadDllMessage(); return; } catch (FileNotFoundException) { ShowError(Localizer.GetString("MissingDLL")); return; } lock (_networks) { _networks.Clear(); } ResetData(); timeGraph.Start(); _terminateNetworkScan.Reset(); _scanThread = new Thread(ScanNetworks); _scanThread.IsBackground = true; _scanThread.Start(); _viewUpdateTimer.Elapsed -= updateListHandler; _viewUpdateTimer.Elapsed += updateViewHandler; _viewUpdateTimer.Interval = UPDATE_HIGHLIGHT_INTERVAL; UpdateNetworkScanState(true); Settings.Default.PreviousInterfaceName = _interface.Name; } } // End StartScanning() private void UpdateNetworkScanState(bool enabled) { if (this.InvokeRequired) { NetworkScanStateHandler handler = new NetworkScanStateHandler(UpdateNetworkScanState); this.Invoke(handler, new object[] { enabled }); } else { if (enabled) { scanButton.Text = Localizer.GetString("StopScanning"); } else { scanButton.Text = Localizer.GetString("StartScanning"); } scanButton.Refresh(); interfaceList.Enabled = !enabled; } } /// /// Stops scanning and kills the scan thread /// private void StopScanning() { StopScanning(true); } /// /// /// /// true to terminate the scanThread private void StopScanning(bool killThread) { if (timeGraph != null) { timeGraph.Stop(); } if (Settings.Default.isLogging && (null != _dataLog)) { SaveLogFile(); _dataLog = null; } if (_viewUpdateTimer != null) { _viewUpdateTimer.Elapsed -= updateViewHandler; _viewUpdateTimer.Elapsed += updateListHandler; _viewUpdateTimer.Interval = UPDATE_LIST_INTERVAL; } if (killThread && _scanThread != null) { _terminateNetworkScan.Set(); if (!_scanThread.Join(5000)) { _scanThread.Abort(); } } UpdateNetworkScanState(false); } // End StopScanning() private void CheckScanStatus() { if (_scanThread.ThreadState == System.Threading.ThreadState.Stopped) { StopScanning(); } } // End CheckScanStatus private ScannerNetwork getNetworkFromId(uint networkID) { for (int i = 0; i < _networks.Count; i++) { if (_networks[i].ID == networkID) { return _networks[i]; } } return null; } #endregion #region Data Grid Methods /// /// Attempts to find a row in the data grid with a matching /// MAC address string. /// /// MAC address to find in the data grid /// A DataGridViewRow if found, null otherwise. private DataGridViewRow FindDataRow(string macAddress) { DataGridViewRow foundRow = null; foreach (DataGridViewRow row in scannerGridView.Rows) { string cellMacAddress = (string)row.Cells["macColumn"].Value; if (null != cellMacAddress && cellMacAddress.Equals(macAddress)) { foundRow = row; break; } } return (foundRow); } // End FindDataCell /// /// This method is a Timer event handler that updates the data /// grid with the current network information. /// /// not used /// not used private void UpdateDataGrid(object source, ElapsedEventArgs e) { // // Make sure the scan thread is still running // CheckScanStatus(); if (!_abort && (_lastDrawnTimeStamp < _lastScanTimeStamp)) { _lastDrawnTimeStamp = DateTime.Now; ImageList imgLst; clearInactiveNetworks(); lock (_networks) { foreach (ScannerNetwork network in _networks) { if (!(network.Security == "None")) { imgLst = imageSignalLevelEnc; } else { imgLst = imageSignalLevel; } DataGridViewRow row = FindDataRow(network.MacAddress.ToString()); if (null != row) { row.Cells["channelColumn"].Value = network.Channel; row.Cells["securityColumn"].Value = network.Security; row.Cells["typeColumn"].Value = network.NetworkType; row.Cells["lastSeenColumn"].Value = network.LastSeenTimeStamp.ToLongTimeString(); row.Cells["speedColumn"].Value = network.Speed; row.Cells["speedColumn"].ToolTipText = network.SpeedString; //Update Strength indicator if (network.Signal > -60) { row.Cells["sigIndColumn"].Value = imgLst.Images[0]; } //Green else if (network.Signal <= -60 && network.Signal > -70) { row.Cells["sigIndColumn"].Value = imgLst.Images[1]; } //LtGreen else if (network.Signal <= -70 && network.Signal > -80) { row.Cells["sigIndColumn"].Value = imgLst.Images[2]; } //Yellow else if (network.Signal <= -80 && network.Signal > -90) { row.Cells["sigIndColumn"].Value = imgLst.Images[3]; } //Orange else if (network.Signal <= -90 && network.Signal > -99) { row.Cells["sigIndColumn"].Value = imgLst.Images[4]; } //Red else { row.Cells["sigIndColumn"].Value = imgLst.Images[5]; } //Gray // Check to see how much time has passed since the network was last seen TimeSpan duration = _lastScanTimeStamp - network.LastSeenTimeStamp; if (duration.Seconds <= 30) { row.Cells["signalColumn"].Value = network.Signal; } else { // After 30 seconds, set the RSSI value to unknown row.Cells["signalColumn"].Value = -100; } //Update GPS location if (network.Signal > (int)row.Cells["oldSigColumn"].Value && (bool)row.Cells["oldSig2Column"].Value == true) { //if (GPSloc.TypeOfFix != GPSTools.GPSInfo.FixType.Invalid) if (_gps.HasFix) { row.Cells["locationColumn"].Value = Math.Round(_gps.Latitude, 5).ToString(CultureInfo.InvariantCulture) + " , " + Math.Round(_gps.Longitude, 5).ToString(CultureInfo.InvariantCulture); // row.Cells["locationColumn"].Value = Math.Round(GPSloc.Latitude, 5).ToString() + " , " + Math.Round(GPSloc.Longitude, 5).ToString(); row.Cells["oldSig2Column"].Value = false; row.Cells["oldSigColumn"].Value = network.Signal; } } if (network.Signal > (int)row.Cells["oldSigColumn"].Value && (bool)row.Cells["oldSig2Column"].Value == false) { row.Cells["oldSig2Column"].Value = true; } } else { // add the new network to the data grid row = new DataGridViewRow(); row.CreateCells(scannerGridView, network.Data); // Ryan: The column names aren't working here... ugh@! row.Cells[1].Style.BackColor = network.LineColor; row.Cells[1].Style.SelectionBackColor = network.LineColor; scannerGridView.Rows.Add(row); // [4-11-09] The column names seem to work after the row is added. if (network.Signal > -60) { row.Cells["sigIndColumn"].Value = imgLst.Images[0]; } //Green else if (network.Signal <= -60 && network.Signal > -70) { row.Cells["sigIndColumn"].Value = imgLst.Images[1]; } //LtGreen else if (network.Signal <= -70 && network.Signal > -80) { row.Cells["sigIndColumn"].Value = imgLst.Images[2]; } //Yellow else if (network.Signal <= -80 && network.Signal > -90) { row.Cells["sigIndColumn"].Value = imgLst.Images[3]; } //Orange else if (network.Signal <= -90 && network.Signal > -99) { row.Cells["sigIndColumn"].Value = imgLst.Images[4]; } //Red else { row.Cells["sigIndColumn"].Value = imgLst.Images[5]; } //Gray try { //if (GPSloc.TypeOfFix != GPSTools.GPSInfo.FixType.Invalid) if (_gps.HasFix) { row.Cells["locationColumn"].Value = Math.Round(_gps.Latitude, 5).ToString(CultureInfo.InvariantCulture) + " , " + Math.Round(_gps.Longitude, 5).ToString(CultureInfo.InvariantCulture); // row.Cells["locationColumn"].Value = Math.Round(GPSloc.Latitude, 5).ToString() + " , " + Math.Round(GPSloc.Longitude, 5).ToString(); } else { row.Cells["locationColumn"].Value = "0.00000 , 0.00000"; } } catch (NullReferenceException) { //DoNothing(ex); //System.Diagnostics.Debugger.Break(); return; } row.Cells["oldSigColumn"].Value = network.Signal; row.Cells["oldSig2Column"].Value = false; updateVerticalHeights(); row.Selected = false; timeGraph.AddLine(network.ID, network.LineColor, network.DashedLine, network.StripedLine); timeGraph[network.ID].Visible = network.Visible; } txtAPstat.Text = scannerGridView.Rows.Count.ToString() + " AP(s)"; } } if (null != scannerGridView.SortedColumn) { // TUT: for some reason a row gets selected as a side effect of sorting if (0 == scannerGridView.SelectedRows.Count) { _ignoreSelection = true; } scannerGridView.Sort(scannerGridView.SortedColumn, (scannerGridView.SortOrder == SortOrder.Descending ? ListSortDirection.Descending : ListSortDirection.Ascending) ); } if (Settings.Default.DisplayTimeGraph) { timeGraph.Refresh(); } } } private void clearHighlights() { ScannerNetwork network; for (int counter = 0; counter < _networks.Count; counter++) { network = _networks[counter]; network.Selected = false; if (timeGraph[network.ID] != null) { timeGraph[network.ID].Selected = false; } } channelGraph.Invalidate(); } private void copyGridToClipboard() { StringBuilder text = new StringBuilder(); text.Append(scannerGridView.Columns["macColumn"].HeaderText + "\t"); text.Append(scannerGridView.Columns["vendorColumn"].HeaderText + "\t"); text.Append(scannerGridView.Columns["ssidColumn"].HeaderText + "\t"); text.Append(scannerGridView.Columns["channelColumn"].HeaderText + "\t"); text.Append(scannerGridView.Columns["signalColumn"].HeaderText + "\t"); text.Append(scannerGridView.Columns["securityColumn"].HeaderText + "\t"); text.Append(scannerGridView.Columns["typeColumn"].HeaderText + "\t"); text.Append(scannerGridView.Columns["speedColumn"].HeaderText + "\t"); text.Append(scannerGridView.Columns["firstSeenColumn"].HeaderText + "\t"); text.Append(scannerGridView.Columns["lastSeenColumn"].HeaderText + "\t"); text.Append(scannerGridView.Columns["locationColumn"].HeaderText + "\r\n"); for (int i = 0; i < scannerGridView.Rows.Count; i++) { text.Append(scannerGridView.Rows[i].Cells["macColumn"].Value + "\t"); text.Append(scannerGridView.Rows[i].Cells["vendorColumn"].Value + "\t"); text.Append(scannerGridView.Rows[i].Cells["ssidColumn"].Value + "\t"); text.Append(scannerGridView.Rows[i].Cells["channelColumn"].Value + "\t"); text.Append(scannerGridView.Rows[i].Cells["signalColumn"].Value + "\t"); text.Append(scannerGridView.Rows[i].Cells["securityColumn"].Value + "\t"); text.Append(scannerGridView.Rows[i].Cells["typeColumn"].Value + "\t"); text.Append(scannerGridView.Rows[i].Cells["speedColumn"].Value + "\t"); text.Append(scannerGridView.Rows[i].Cells["firstSeenColumn"].Value + "\t"); text.Append(scannerGridView.Rows[i].Cells["lastSeenColumn"].Value + "\t"); text.Append(scannerGridView.Rows[i].Cells["locationColumn"].Value + "\r\n"); } try { Clipboard.SetDataObject(text.ToString(), true); } catch (ExternalException) { MessageBox.Show(Localizer.GetString("FailedToCopyClipboard"), Localizer.GetString("ClipboardError"), MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void clearInactiveNetworks() { if (Settings.Default.InactiveNetworkTimeout == TimeSpan.Zero) { return; } DateTime oldestAllowedTime = DateTime.Now - Settings.Default.InactiveNetworkTimeout; for (int i = 0; i < _networks.Count; i++) { // delete old networks if (_networks[i].LastSeenTimeStamp < oldestAllowedTime) { // remove from graph first.. timeGraph.RemoveLine(_networks[i].ID); // remove from table for (int j = 0; j < scannerGridView.Rows.Count; j++) { if ((uint)scannerGridView.Rows[j].Cells["idColumn"].Value == _networks[i].ID) { scannerGridView.Rows.RemoveAt(j); updateVerticalHeights(); break; } } lock (_networks) { _networks.RemoveAt(i); } } } } private void scannerGridView_SortCompare(object sender, DataGridViewSortCompareEventArgs e) { if (e.Column == scannerGridView.Columns["signalColumn"] || e.Column == scannerGridView.Columns["channelColumn"]) { if (Convert.ToInt32(e.CellValue1) > Convert.ToInt32(e.CellValue2)) { e.SortResult = 1; } else if (Convert.ToInt32(e.CellValue1) < Convert.ToInt32(e.CellValue2)) { e.SortResult = -1; } else { e.SortResult = 0; } e.Handled = true; } } private void scannerGridView_UpdateHeaderCheckBoxPos() { if (scannerGridView != null && selectAllNetworksCheckBox != null) { Rectangle rect = scannerGridView.GetColumnDisplayRectangle(scannerGridView.Columns["checkColumn"].Index, true); selectAllNetworksCheckBox.Size = new Size(13,13); rect.X += 6; rect.Y += 5; //Change the location of the CheckBox to make it stay on the header selectAllNetworksCheckBox.Location = rect.Location; selectAllNetworksCheckBox.Invalidate(); } } #endregion #region UI Methods /// /// Resets the graph and data grids /// private void ResetData() { scannerGridView.Rows.Clear(); timeGraph.Clear(); // Start the network IDs over again ScannerNetwork.ResetNextId(); } /// /// Adjust the UI to match the saved preferences /// private void PrefsToWindow() { try { WindowState = Settings.Default.WindowState; Rectangle windowArea = new Rectangle(Settings.Default.WindowLocation, Settings.Default.WindowSize); Rectangle desktopArea = Screen.GetWorkingArea(windowArea); if (!desktopArea.Contains(windowArea)) { if (windowArea.Height > desktopArea.Height) { windowArea.Height = desktopArea.Height; } if (windowArea.Width > desktopArea.Width) { windowArea.Width = desktopArea.Width; } if (windowArea.Left < desktopArea.Left || windowArea.Right > desktopArea.Right) { windowArea.X = desktopArea.Left + ((desktopArea.Width - windowArea.Width) / 2); } if (windowArea.Top < desktopArea.Top || windowArea.Bottom > desktopArea.Bottom) { windowArea.Y = desktopArea.Top + ((desktopArea.Height - windowArea.Height) / 2); } } this.DesktopBounds = windowArea; scannerGridView.Columns["idColumn"].DisplayIndex = Settings.Default.IndexIdColumn; scannerGridView.Columns["checkColumn"].DisplayIndex = Settings.Default.IndexCheckColumn; scannerGridView.Columns["sigIndColumn"].DisplayIndex = Settings.Default.IndexSigIndColumn; scannerGridView.Columns["macColumn"].DisplayIndex = Settings.Default.IndexMacColumn; scannerGridView.Columns["vendorColumn"].DisplayIndex = Settings.Default.IndexVendorColumn; scannerGridView.Columns["ssidColumn"].DisplayIndex = Settings.Default.IndexSsidColumn; scannerGridView.Columns["channelColumn"].DisplayIndex = Settings.Default.IndexChannelColumn; scannerGridView.Columns["signalColumn"].DisplayIndex = Settings.Default.IndexSignalColumn; scannerGridView.Columns["securityColumn"].DisplayIndex = Settings.Default.IndexSecurityColumn; scannerGridView.Columns["speedColumn"].DisplayIndex = Settings.Default.IndexSpeedColumn; scannerGridView.Columns["typeColumn"].DisplayIndex = Settings.Default.IndexTypeColumn; scannerGridView.Columns["firstSeenColumn"].DisplayIndex = Settings.Default.IndexFirstSeenColumn; scannerGridView.Columns["lastSeenColumn"].DisplayIndex = Settings.Default.IndexLastSeenColumn; scannerGridView.Columns["locationColumn"].DisplayIndex = Settings.Default.IndexLocationColumn; // Set column visibility scannerGridView.Columns["macColumn"].Visible = Settings.Default.DisplayMacColumn; scannerGridView.Columns["vendorColumn"].Visible = Settings.Default.DisplayVendorColumn; scannerGridView.Columns["ssidColumn"].Visible = Settings.Default.DisplaySsidColumn; scannerGridView.Columns["channelColumn"].Visible = Settings.Default.DisplayChannelColumn; scannerGridView.Columns["signalColumn"].Visible = Settings.Default.DisplaySignalColumn; scannerGridView.Columns["securityColumn"].Visible = Settings.Default.DisplaySecurityColumn; scannerGridView.Columns["speedColumn"].Visible = Settings.Default.DisplaySpeedColumn; scannerGridView.Columns["typeColumn"].Visible = Settings.Default.DisplayTypeColumn; scannerGridView.Columns["firstSeenColumn"].Visible = Settings.Default.DisplayFirstSeenColumn; scannerGridView.Columns["lastSeenColumn"].Visible = Settings.Default.DisplayLastSeenColumn; scannerGridView.Columns["locationColumn"].Visible = Settings.Default.DisplayLocationColumn; macToolStripMenuItem.Checked = Settings.Default.DisplayMacColumn; vendorToolStripMenuItem.Checked = Settings.Default.DisplayVendorColumn; ssidToolStripMenuItem.Checked = Settings.Default.DisplaySsidColumn; channelToolStripMenuItem.Checked = Settings.Default.DisplayChannelColumn; signalToolStripMenuItem.Checked = Settings.Default.DisplaySignalColumn; securityToolStripMenuItem.Checked = Settings.Default.DisplaySecurityColumn; speedToolStripMenuItem.Checked = Settings.Default.DisplaySpeedColumn; typeToolStripMenuItem.Checked = Settings.Default.DisplayTypeColumn; firstSeenToolStripMenuItem.Checked = Settings.Default.DisplayFirstSeenColumn; lastSeenToolStripMenuItem.Checked = Settings.Default.DisplayLastSeenColumn; locationToolStripMenuItem.Checked = Settings.Default.DisplayLocationColumn; GraphSplitContainer.SplitterDistance = Settings.Default.graphSplitterDistance; displayTimeGraphToolStripMenuItem.Checked = Settings.Default.DisplayTimeGraph; displayChannelGraphToolStripMenuItem.Checked = Settings.Default.DisplayChannelGraph; ; if (Settings.Default.ChannelView24) { channelGraph.Band = ChannelView.BandType.Band2400MHz; band2400Button.Checked = true; } else { channelGraph.Band = ChannelView.BandType.Band5000MHz; band5000Button.Checked = true; } _logFilename = Settings.Default.LogFolder; } catch { // This is causing a crash due to a corrupt config file... Settings.Default.Reset(); } // will update the views based on the above settings UpdateGraphsInView(); } /// /// Randomly picks the start image. Since this is not essential to app functionality /// we catch ALL exceptions that may be thrown in this function. /// private void SelectStartImage() { try { if (Application.ProductVersion.Length > 0 && Settings.Default.HideStartImageVersion.Length > 0 && VersionInfo.CompareVersions(Application.ProductVersion, Settings.Default.HideStartImageVersion)) { int numImages = int.Parse(Localizer.GetString("NumStartImages")); Random random = new Random(); int imageIndex = random.Next(numImages); Bitmap image = Localizer.GetBitmap("start" + imageIndex); startImageLabel.Image = image; startImageLabel.Name = imageIndex.ToString(); int pageNum = random.Next(numImages); } else { startImageLabel.Visible = false; hideStartImageLabel.Visible = false; } } catch (Exception) { } } /// /// /// /// /// private void hideStartImageLabel_Click(object sender, EventArgs e) { try { Settings.Default.HideStartImageVersion = Application.ProductVersion; Settings.Default.Save(); startImageLabel.Visible = false; hideStartImageLabel.Visible = false; } catch (Exception) { } } private void UpdateSize() { if (WindowState == FormWindowState.Normal) { try { Settings.Default.WindowSize = Size; } catch (SystemException) { // couldn't update prefs, that's OK } } if (startImageLabel.Visible) { startImageLabel.Left = (adPanel.Width - startImageLabel.Width) / 2; startImageLabel.Top = (adPanel.Height - startImageLabel.Height) / 2; hideStartImageLabel.Left = (adPanel.Width - hideStartImageLabel.Width) / 2; hideStartImageLabel.Top = startImageLabel.Bottom; } else { updateVerticalHeights(); } } public delegate void SetStringToClipboard(); /// /// Used to copy the error info on a crash to teh clipboard /// /// public void StringToClipboard(string data) { if (this.InvokeRequired) { this.Invoke( new SetStringToClipboard(delegate() { Clipboard.SetDataObject(data); } )); } else { Clipboard.SetDataObject(data); } } private void updateVerticalHeights() { if (_autoResize) { scannerGridView.Height = Math.Min((this.Height - MIN_NON_GRID_VERTICAL), (scannerGridView.PreferredSize.Height - (scannerGridView.Height > scannerGridView.DisplayRectangle.Height ? 16 : 33))); } } /// /// Updates which graphs are in view. If no graphs in view the entire graphs panel is hidden /// private void UpdateGraphsInView() { GraphSplitContainer.Visible = (displayTimeGraphToolStripMenuItem.Checked || displayChannelGraphToolStripMenuItem.Checked); // When the app starts, the GraphSplitContainer is not visible, because the entire bottomPanel is not visible // so this needs to be based on the menu itmes, not on GraphSplitContainer.Visible if (displayTimeGraphToolStripMenuItem.Checked || displayChannelGraphToolStripMenuItem.Checked) { GraphSplitContainer.Panel1Collapsed = !displayTimeGraphToolStripMenuItem.Checked; GraphSplitContainer.Panel2Collapsed = !displayChannelGraphToolStripMenuItem.Checked; } channelGraphPrefsPanel.Enabled = displayChannelGraphToolStripMenuItem.Checked; } /// /// Plots the RSSI values of the available wireless networks. /// private void UpdateTimeGraph() { lock (_networks) { foreach (ScannerNetwork network in _networks) { TimeGraph.Line line = timeGraph[network.ID]; if (null != line && network.LastSeenTimeStamp > line.MaxMeasuredTimeStamp) { line.AddPoint(network.Signal, _lastScanTimeStamp, true); } } } }// End UpdateSignalGraph() #endregion #region UI Interaction Methods private void scannerGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) { // clicked on row selector.. if (e.RowIndex == -1) { _ignoreSelection = true; return; } switch (e.ColumnIndex) { // Checkbox column case 1: ScannerNetwork network = getNetworkFromId((uint)scannerGridView.Rows[e.RowIndex].Cells["idColumn"].Value); if (e.Button == MouseButtons.Left) { if (network != null) { network.Visible = !network.Visible; scannerGridView.Rows[e.RowIndex].Cells["checkColumn"].Value = network.Visible; if (timeGraph[network.ID] != null) { timeGraph[network.ID].Visible = network.Visible; channelGraph.Invalidate(); } } } break; default: if (e.Button == MouseButtons.Right) { if (scannerGridView.SelectedRows.Count > 0) { if (scannerGridView.SelectedRows.Count == 1) { hideToolStripMenuItem.Text = Localizer.GetString("HideNetwork", scannerGridView.SelectedRows[0].Cells["ssidColumn"].Value); } else { hideToolStripMenuItem.Text = Localizer.GetString("HideSelectedNetworks"); } rowContextMenuStrip.Show(Cursor.Position); } } else if ((scannerGridView.Rows[e.RowIndex].Selected) && !_newSelection) { scannerGridView.Rows[e.RowIndex].Selected = false; } break; } // check for indeterminate state of the selectAllCheckBox int numVisible = 0; int numInvisible = 0; lock (_networks) { foreach (ScannerNetwork network in _networks) { if (network.Visible) numVisible++; else numInvisible++; } } if (numVisible == 0) { selectAllNetworksCheckBox.CheckState = CheckState.Unchecked; } else if (numInvisible == 0) { selectAllNetworksCheckBox.CheckState = CheckState.Checked; } else { selectAllNetworksCheckBox.CheckState = CheckState.Indeterminate; } _newSelection = false; } /// /// Manually positions the selectAllNetworksCheckBox. This is kind of a hack, /// but there isn't a standard way of putting a checkbox into the DataGridView /// header /// /// /// private void scannerGridView_VisibleChanged(object sender, EventArgs e) { if (scannerGridView.Visible) { if (selectAllNetworksCheckBox == null) { selectAllNetworksCheckBox = new CheckBox(); selectAllNetworksCheckBox.ThreeState = true; selectAllNetworksCheckBox.CheckState = CheckState.Checked; selectAllNetworksCheckBox.CheckedChanged += new EventHandler(selectAllNetworksCheckBox_CheckedChanged); //Add the CheckBox into the DataGridView this.scannerGridView.Controls.Add(selectAllNetworksCheckBox); } // TUT: this little hack causes the column indices to get updated on XP scannerGridView.Columns["idColumn"].Visible = true; scannerGridView.Columns["idColumn"].Visible = false; scannerGridView_UpdateHeaderCheckBoxPos(); } } /// /// Toggles the Wi-Fi overlays for ALL Wi-Fi networks in the Wi-Fi sidebar /// /// /// private void selectAllNetworksCheckBox_CheckedChanged(object source, System.EventArgs e) { if (selectAllNetworksCheckBox.CheckState == CheckState.Indeterminate) { return; } foreach (DataGridViewRow row in scannerGridView.Rows) { if (row.Visible) { row.Cells["checkColumn"].Value = selectAllNetworksCheckBox.Checked; ScannerNetwork network = getNetworkFromId((uint)row.Cells["idColumn"].Value); if (network != null) { network.Visible = selectAllNetworksCheckBox.Checked; if (timeGraph[network.ID] != null) { timeGraph[network.ID].Visible = network.Visible; } } } } if (Settings.Default.DisplayChannelGraph) { channelGraph.Invalidate(); } } private void scannerGridView_SelectionChanged(object sender, EventArgs e) { clearHighlights(); if (_ignoreSelection) { foreach (DataGridViewRow row in scannerGridView.Rows) { if (null != row) { row.Selected = false; } } _ignoreSelection = false; } else { for (int row = 0; row < scannerGridView.SelectedRows.Count; row++) { uint networkID = (uint)scannerGridView.SelectedRows[row].Cells["idColumn"].Value; if (timeGraph[networkID] != null) { timeGraph[networkID].Selected = true; } ScannerNetwork network = getNetworkFromId(networkID); if (network != null) { network.Selected = true; } } _newSelection = true; if (Settings.Default.DisplayChannelGraph) { channelGraph.Invalidate(); } } } private void copyDataToolStripMenuItem_Click(object sender, EventArgs e) { copyGridToClipboard(); } private void macToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["macColumn"].Visible = macToolStripMenuItem.Checked; Settings.Default.DisplayMacColumn = macToolStripMenuItem.Checked; } private void vendorToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["vendorColumn"].Visible = vendorToolStripMenuItem.Checked; Settings.Default.DisplayVendorColumn = vendorToolStripMenuItem.Checked; } private void ssidToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["ssidColumn"].Visible = ssidToolStripMenuItem.Checked; Settings.Default.DisplaySsidColumn = ssidToolStripMenuItem.Checked; } private void channelToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["channelColumn"].Visible = channelToolStripMenuItem.Checked; Settings.Default.DisplayChannelColumn = channelToolStripMenuItem.Checked; } private void signalToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["signalColumn"].Visible = signalToolStripMenuItem.Checked; Settings.Default.DisplaySignalColumn = signalToolStripMenuItem.Checked; } private void securityToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["securityColumn"].Visible = securityToolStripMenuItem.Checked; Settings.Default.DisplaySecurityColumn = securityToolStripMenuItem.Checked; } private void networkToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["typeColumn"].Visible = typeToolStripMenuItem.Checked; Settings.Default.DisplayTypeColumn = typeToolStripMenuItem.Checked; } private void speedToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["speedColumn"].Visible = speedToolStripMenuItem.Checked; Settings.Default.DisplaySpeedColumn = speedToolStripMenuItem.Checked; } private void firstSeenToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["firstSeenColumn"].Visible = firstSeenToolStripMenuItem.Checked; Settings.Default.DisplayFirstSeenColumn = firstSeenToolStripMenuItem.Checked; } private void lastTimeToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["lastSeenColumn"].Visible = lastSeenToolStripMenuItem.Checked; Settings.Default.DisplayLastSeenColumn = lastSeenToolStripMenuItem.Checked; } private void locationToolStripMenuItem_Click(object sender, EventArgs e) { scannerGridView.Columns["locationColumn"].Visible = locationToolStripMenuItem.Checked; Settings.Default.DisplayLocationColumn = locationToolStripMenuItem.Checked; } private void ScannerForm_SizeChanged(object sender, EventArgs e) { UpdateSize(); } private void ScannerForm_FormClosing(object sender, FormClosingEventArgs args) { try { if (Settings.Default.isLogging && (null != _dataLog)) { SaveLogFile(); } } catch (SystemException) { // couldn't acccess settings to see if logging, save if there is a log file if (null != _dataLog) { SaveLogFile(); } } Settings.Default.WindowState = WindowState; if (WindowState == FormWindowState.Normal) { Settings.Default.WindowLocation = Location; Settings.Default.WindowSize = Size; } // Save column order //Settings.Default.DataGridColumns = new System.Collections.Specialized.StringDictionary(); //foreach (DataGridViewColumn col in scannerGridView.Columns) //{ // Settings.Default.DataGridColumns.Add(col.Name, col.DisplayIndex.ToString()); //} Settings.Default.IndexIdColumn = scannerGridView.Columns["idColumn"].DisplayIndex; Settings.Default.IndexCheckColumn = scannerGridView.Columns["checkColumn"].DisplayIndex; Settings.Default.IndexSigIndColumn = scannerGridView.Columns["sigIndColumn"].DisplayIndex; Settings.Default.IndexMacColumn = scannerGridView.Columns["macColumn"].DisplayIndex; Settings.Default.IndexVendorColumn = scannerGridView.Columns["vendorColumn"].DisplayIndex; Settings.Default.IndexSsidColumn = scannerGridView.Columns["ssidColumn"].DisplayIndex; Settings.Default.IndexChannelColumn = scannerGridView.Columns["channelColumn"].DisplayIndex; Settings.Default.IndexSignalColumn = scannerGridView.Columns["signalColumn"].DisplayIndex; Settings.Default.IndexSecurityColumn = scannerGridView.Columns["securityColumn"].DisplayIndex; Settings.Default.IndexSpeedColumn = scannerGridView.Columns["speedColumn"].DisplayIndex; Settings.Default.IndexTypeColumn = scannerGridView.Columns["typeColumn"].DisplayIndex; Settings.Default.IndexFirstSeenColumn = scannerGridView.Columns["firstSeenColumn"].DisplayIndex; Settings.Default.IndexLastSeenColumn = scannerGridView.Columns["lastSeenColumn"].DisplayIndex; Settings.Default.IndexLocationColumn = scannerGridView.Columns["locationColumn"].DisplayIndex; Settings.Default.Save(); _abort = true; if (null != _gps) { _gps.TerminateThread(); } StopScanning(); } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { this.Close(); } private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { using (AboutForm about = new AboutForm()) { about.ShowDialog(); } } private void communityForumToolStripMenuItem_Click(object sender, EventArgs e) { try { Process.Start("http://www.metageek.net/forum?utm_campaign=Software&utm_medium=Inssider." + Application.ProductVersion + "&utm_source=HelpMenuForum"); } catch (System.ComponentModel.Win32Exception) { // // Ignore exception. // // This exception will be thrown when Firefox unexpectedly // shuts down, and asks the user to restore the session when it is started by // Inssider. Apparently, Windoz doesn't like this, because it tosses a // file not found exception. Weird! // // Anyway, the lesser evil right now is to silently ignore // this exception. // } } private void ScannerForm_LocationChanged(object sender, EventArgs e) { if (WindowState == FormWindowState.Normal) { if (_canSet) { Settings.Default.WindowLocation = Location; } } } private void scannerGridView_ColumnHeadersHeightChanged(object sender, EventArgs e) { updateVerticalHeights(); } private void copyTimeGraphToolStripMenuItem_Click(object sender, EventArgs e) { Clipboard.SetDataObject(timeGraph.GraphBitMap, true); } private void copyChannelGraphToolStripMenuItem_Click(object sender, EventArgs e) { Clipboard.SetDataObject(channelGraph.GraphBitmap, true); } private void preferencesToolStripMenuItem_Click(object sender, EventArgs e) { using (PreferencesForm prefs = new PreferencesForm()) { if (prefs.ShowDialog() == DialogResult.OK) { clearInactiveNetworks(); _gps.Enabled = Settings.Default.gpsEnabled; if (_gps.Enabled) { if (Settings.Default.GPSPort != _gps.PortName || !_gps.Connected) { _gps.InitializeThread(); } } GpsUpdated(this, e); } } } private void helpToolStripMenuItem_Click(object sender, EventArgs e) { try { string pathName = Directory.GetParent(Path.GetDirectoryName(Application.ExecutablePath)).ToString() + "\\docs\\inssider.chm"; Process.Start(pathName); } catch (Exception) { MessageBox.Show(Localizer.GetString("HelpErrorMessage"), Localizer.GetString("HelpError")); } } private void scannerGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { if (e.Button == MouseButtons.Right) { columnsContextMenuStrip.Show(Cursor.Position); } else { // data sort just changed.... int lastRow = scannerGridView.Rows.Count - 1; for (int i = 0; i <= lastRow; i++) { uint networkID = (uint)scannerGridView.Rows[i].Cells["idColumn"].Value; if (timeGraph[networkID] != null) { timeGraph[networkID].drawOrder = lastRow - i; } } timeGraph.Refresh(); } } private void CreateVendorLookup() { string fileName = Path.GetDirectoryName( Application.ExecutablePath) + "\\oui.txt"; if (null == _vendors) { _vendors = new Vendors(); } try { _vendors.LoadFromOui(); } catch { string message = String.Format("File \"{0}\" could not be loaded", fileName); MessageBox.Show(message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } private void ScannerForm_Load(object sender, EventArgs e) { try { if (Settings.Default.NextUpdateCheck < DateTime.Now) { CheckForUpdate(true); } } catch (SystemException) { // Couldn't access setting to see if due for an update check // go ahead and check CheckForUpdate(true); } PrefsToWindow(); UpdateSize(); try { _gps.Enabled = Settings.Default.gpsEnabled; } catch (SystemException) { _gps.Enabled = false; } _canSet = true; bottomPanel.Visible = false; // load the vendor information from the oui file. CreateVendorLookup(); LoadInterfaceList(); _viewUpdateTimer.Start(); gridSplitter.SplitPosition = 55; this.GraphSplitContainer.SplitterMoved += new System.Windows.Forms.SplitterEventHandler(this.GraphSplitContainer_SplitterMoved); this.GraphSplitContainer.Panel1MinSize = 250; this.GraphSplitContainer.Panel2MinSize = 250; //Init the GPS if (_gps.Enabled) { _gps.InitializeThread(); } GpsUpdated(this, e); } private void scanButton_Click(object sender, EventArgs e) { if (scanButton.Text.Equals(Localizer.GetString("StartScanning"))) { StartScanning(); } else { StopScanning(); } } private void checkToolStripMenuItem_Click(object sender, EventArgs e) { CheckForUpdate(false); } private void automaticallyResizeToolStripMenuItem_Click(object sender, EventArgs e) { _autoResize = !_autoResize; automaticallyResizeToolStripMenuItem.Checked = _autoResize; if (_autoResize) { updateVerticalHeights(); } } private void graphSplitter_SplitterMoving(object sender, SplitterEventArgs e) { // TUT: once the user moves the splitter up, we don't want to autosize it anymore if (e.Y > e.SplitY) { _autoResize = false; } } private void hideToolStripMenuItem_Click(object sender, EventArgs e) { foreach(DataGridViewRow row in scannerGridView.SelectedRows) { row.Cells["checkColumn"].Value = false; uint networkID = (uint)row.Cells["idColumn"].Value; if (timeGraph[networkID] != null) { timeGraph[networkID].Visible = false; } ScannerNetwork network = getNetworkFromId(networkID); if (network != null) { network.Visible = false; } row.Visible = false; } updateVerticalHeights(); if (Settings.Default.DisplayChannelGraph) { channelGraph.Invalidate(); } } /// /// Shows all networks in the table /// /// /// private void showAllNetworksToolStripMenuItem_Click(object sender, EventArgs e) { foreach (DataGridViewRow row in scannerGridView.Rows) { row.Visible = true; } updateVerticalHeights(); } /// /// Adjust horizontal size of the graphs /// /// /// private void GraphSplitContainer_SplitterMoved(object sender, SplitterEventArgs e) { Settings.Default.graphSplitterDistance = e.SplitX; } /// /// Go to website for the image ad /// /// /// private void startImageLabel_Click(object sender, EventArgs e) { string page = string.Empty; switch (startImageLabel.Name) { case "0": page = "products/wi-spy-24i"; break; case "1": page = "products/wirelessmon"; break; default: case "2": page = "products/wi-spy-dbx"; break; } try { Process.Start("http://www.metageek.net/" + page + "?utm_campaign=Software&utm_medium=Inssider." + Application.ProductVersion + "&utm_source=StartPage" + startImageLabel.Name); } catch (Win32Exception) { } } private void clickableControl_MouseEnter(object sender, EventArgs e) { this.Cursor = Cursors.Hand; } private void clickableControl_MouseLeave(object sender, EventArgs e) { this.Cursor = Cursors.Default; } private void ScannerForm_VisibleChanged(object sender, EventArgs e) { UpdateSize(); } #region GPS Methods /// /// Attempts to open the log file for GPS logging /// private void OpenLogFile() { logTime = DateTime.Now; try { _dataLog = new XmlDocument(); string dateString = logTime.Year + "-" + logTime.Month + "-" + logTime.Day + "_" + logTime.Hour + "-" + logTime.Minute + "-" + logTime.Second; _logFilename = Settings.Default.LogFolder + "\\" + dateString + ".gpx"; _dataLog.LoadXml(_xmlHeader); } catch (Exception) { _dataLog = null; } } private void SaveLogFile() { try { _dataLog.Save(_logFilename); } catch (XmlException e) { System.Diagnostics.Debug.WriteLine(e.Message); } catch (System.IO.IOException e) { System.Diagnostics.Debug.WriteLine(e.Message); MessageBox.Show(Localizer.GetString("GpxFileInUse"), Localizer.GetString("Error"), MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void writeLogEntry(List detailList) { if (null == _dataLog) { OpenLogFile(); } try { //WirelessDetails[] wirelessArray = detailList.ToArray(); //for (int i = 0; i < wirelessArray.Length; i++) foreach (WirelessDetails tempDetail in detailList) { //WirelessDetails tempDetail = wirelessArray[i]; uint ChannelID = tempDetail.Channel; string MAC = tempDetail.MacAddress.ToString(); int RSSI = tempDetail.Rssi; string infraMode = tempDetail.InfrastructureMode; string networkType = tempDetail.NetworkType; string privacy = tempDetail.Privacy; string rates = tempDetail.BuildRateString(); string signalQuality = tempDetail.SignalQuality + ""; string SSID = tempDetail.Ssid; SSID = XmlCleanUp.CleanUp(SSID); XmlElement dataPoint = _dataLog.CreateElement("wpt"); dataPoint.SetAttribute("lat", _gps.Latitude + ""); dataPoint.SetAttribute("lon", _gps.Longitude + ""); dataPoint.InnerXml = "" + _gps.Altitude + ""; dataPoint.InnerXml += ""; string CR = System.Environment.NewLine; if (!double.IsNaN(_gps.MagVar)) { dataPoint.InnerXml += "" + _gps.MagVar + ""; } dataPoint.InnerXml += "" + _gps.GeoidSeperation + ""; dataPoint.InnerXml += "" + SSID + " [" + MAC + "]"; //Currently this description is ignored when converted to a KML file. However you'll see it in Google Earth if you import the GPX directly. string desc = SSID + CR + "[" + MAC + "]" + CR + privacy + CR + "RSSI :" + RSSI + "dBm" + CR + "Quality " + signalQuality + "%" + CR + "Channel " + ChannelID + CR + "Speed (kph) " + _gps.Speed + CR + _gps.Time.ToString(); dataPoint.InnerXml += "" + _gps.Speed + ""; dataPoint.InnerXml += "" + desc + ""; dataPoint.InnerXml += "" + _gps.FixString + ""; dataPoint.InnerXml += "" + _gps.SatellitesUsed + ""; dataPoint.InnerXml += "" + _gps.HDOP + ""; dataPoint.InnerXml += "" + _gps.VDOP + ""; dataPoint.InnerXml += "" + _gps.PDOP + ""; double age = _gps.DGPSAge; if (age != 0) { dataPoint.InnerXml += "" + _gps.DGPSAge + ""; dataPoint.InnerXml += "" + _gps.DGPSID + ""; } string extensions = ""; extensions += ""; extensions += "" + MAC + ""; extensions += "" + SSID + ""; extensions += "" + RSSI + ""; extensions += "" + ChannelID + ""; extensions += "" + privacy + ""; extensions += "" + signalQuality + ""; extensions += "" + networkType + ""; extensions += "" + rates + ""; extensions += ""; dataPoint.InnerXml += extensions; //Ignore anything less than or equal to -100 dBm if (RSSI > -100) { _dataLog.GetElementsByTagName("gpx").Item(0).AppendChild(dataPoint); } } // Periodically auto save timestamped log if enabled TimeSpan dT = DateTime.Now - logTime; string rootFilename = Settings.Default.LogFolder; if (Settings.Default.isLogging && Settings.Default.isAutoSaving && ((int)(Math.Floor(dT.TotalSeconds))) > Settings.Default.autoSaveRate) { logTime = DateTime.Now; SaveLogFile(); } } catch (Exception) { } } private void GpsUpdated(object sender, EventArgs e) { string updateString = String.Empty; try { if (!_gps.Enabled) { updateString = "GPS: Disabled"; } else if (_gps.Connected) { if (!_gps.HasTalked) { updateString = "GPS: Waiting for data"; } else { if (!_gps.HasFix) { updateString = "FIX LOST! Last Values: "; } updateString += "GPS : " + Math.Round(_gps.Latitude, 5).ToString("F5") + "°," + Math.Round(_gps.Longitude, 5).ToString("F5") + "°," + _gps.Altitude.ToString("F1") + "m"; updateString += " SPEED : " + _gps.Speed.ToString("F1") + "km/h SAT COUNT : " + _gps.SatellitesUsed; } } else { updateString = "GPS: Not detected on " + _gps.PortName; } } catch (ObjectDisposedException) { } txtGPSstat.Text = updateString; } private void GpsTimeout(object sender, EventArgs e) { txtGPSstat.Text = "GPS: No GPS found on " + _gps.PortName; } private void exportAsNS1ToolStripMenuItem_Click(object sender, EventArgs e) { ExportNS1(); } /// /// Exports data in the Netstumbler file format /// private void ExportNS1() { NS1Format.ns1File exportFile = new NS1Format.ns1File(scannerGridView.Rows.Count); NS1Format.Type apType = NS1Format.Type.Other; string[] latlon; bool enc; try { for (int i = 0; i < scannerGridView.Rows.Count; i++) { latlon = scannerGridView.Rows[i].Cells["locationColumn"].Value.ToString().Split(','); apType = NS1Format.Type.Other; if (scannerGridView.Rows[i].Cells["typeColumn"].Value.ToString() == "Access Point") { apType = NS1Format.Type.AP; } else if (scannerGridView.Rows[i].Cells["typeColumn"].Value.ToString() == "Ad Hoc") { apType = NS1Format.Type.AdHoc; } if (scannerGridView.Rows[i].Cells["securityColumn"].Value.ToString() != "None") { enc = true; } else { enc = false; } exportFile.Add(scannerGridView.Rows[i].Cells["ssidColumn"].Value.ToString(), scannerGridView.Rows[i].Cells["macColumn"].Value.ToString(), Convert.ToInt32(scannerGridView.Rows[i].Cells["signalColumn"].Value), scannerGridView.Rows[i].Cells["firstSeenColumn"].Value.ToString(), scannerGridView.Rows[i].Cells["lastSeenColumn"].Value.ToString(), Convert.ToUInt32(scannerGridView.Rows[i].Cells["channelColumn"].Value), Convert.ToUInt32(scannerGridView.Rows[i].Cells["speedColumn"].Value), enc, Convert.ToDouble(latlon[0].Trim(), CultureInfo.InvariantCulture), Convert.ToDouble(latlon[1].Trim(), CultureInfo.InvariantCulture), apType); } sdlgExport.ShowDialog(this); if (sdlgExport.FileName == "") { return; } else { exportFile.WriteOut(sdlgExport.FileName); } } catch { MessageBox.Show("The data could not be exported", "NS1 Export Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void exportToKmlToolStripMenuItem_Click(object sender, EventArgs e) { using (KmlExporterForm logViewerForm = new KmlExporterForm()) { logViewerForm.ShowDialog(); } } #endregion private void band2400Button_CheckedChanged(object sender, EventArgs e) { channelGraph.Band = ChannelView.BandType.Band2400MHz; Settings.Default.ChannelView24 = true; channelGraph.Invalidate(); } private void band5000Button_CheckedChanged(object sender, EventArgs e) { channelGraph.Band = ChannelView.BandType.Band5000MHz; Settings.Default.ChannelView24 = false; channelGraph.Invalidate(); } /// /// Updates setting for displaying time graph and then calls UpdateGraphView /// /// /// private void displayTimeGraphToolStripMenuItem_Click(object sender, EventArgs e) { Settings.Default.DisplayTimeGraph = displayTimeGraphToolStripMenuItem.Checked; UpdateGraphsInView(); } /// /// Updates setting for displaying channel graph and then calls UpdateGraphView /// /// /// private void displayChannelGraphToolStripMenuItem_Click(object sender, EventArgs e) { Settings.Default.DisplayChannelGraph = displayChannelGraphToolStripMenuItem.Checked; UpdateGraphsInView(); channelGraph.Invalidate(); } #endregion private void scannerGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e) { scannerGridView_UpdateHeaderCheckBoxPos(); } } }