// License: BSD/LGPL // Copyright (C) 2011 Thomas d'Otreppe using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.IO; namespace WirelessPanda.Readers { public class Reader { public const string ACCESSPOINTS_DATATABLE = "Access Points"; public const string STATIONS_DATATABLE = "Stations"; #region Private members private DataSet _dataset = new DataSet(); private List _accessPoints = new List(); private List _stations = new List(); private string _filename = string.Empty; private bool _parseSuccess = false; #endregion #region Properties /// /// Returns true if the file exist /// public bool FileExist { get { return File.Exists(this._filename); } } /// /// DataSet containing 2 tables: "Access Points" and "Stations" /// public virtual DataSet Dataset { get { return this._dataset; } } /// /// Was the file parsed successfully? /// public bool ParseSuccess { get { return this._parseSuccess; } protected set { this._parseSuccess = value; } } /// /// Array of access points /// public virtual AccessPoint[] AccessPoints { get { return this._accessPoints.ToArray().Clone() as AccessPoint[]; } } /// /// Array of stations /// public virtual Station[] Stations { get { return this._stations.ToArray().Clone() as Station[]; } } /// /// Filename /// public string Filename { get { return this._filename; } } /// /// Reader type /// public virtual string ReaderType { get { return "Unknown"; } } /// /// Reader type /// protected virtual string DATE_FORMAT { get { return null; } } /// /// Reader type /// protected virtual string ALT_DATE_FORMAT { get { return null; } } #endregion /// /// Constructor /// /// Filename (doesn't need to exist now but MUST when using Read() ) public Reader(string filename) { if (string.IsNullOrEmpty(filename)) { throw new FileNotFoundException("Filename cannot be null or empty"); } this._filename = filename; } protected void Clear() { // Clear all the values and re-create datatables this._dataset.Tables.Clear(); this._accessPoints.Clear(); this._stations.Clear(); this._parseSuccess = false; } /// /// Open the file and returns its content /// /// /// File does not exist /// Fails to open file protected string[] getStrippedFileContent() { if (string.IsNullOrEmpty(this.Filename)) { throw new FileNotFoundException("Filename cannot be null or empty"); } FileInfo f = new FileInfo(this.Filename); if (!f.Exists) { throw new FileNotFoundException("File <" + this.Filename + "> does not exist"); } // Returns an array with one empty string if (f.Length == 0) { return new string[] { string.Empty }; } StreamReader sr = null; // Open the file try { sr = f.OpenText(); } catch (Exception e) { throw new Exception("Failed to open <" + this.Filename + ">", e); } List lines = new List(); // Read the file try { while (!sr.EndOfStream) { lines.Add(sr.ReadLine().Trim()); } } catch { /* Done or failure so stop */} // Close file try { sr.Close(); } catch { } return lines.ToArray(); } /// /// Read/Update the content of the file /// /// true if successful public virtual bool Read() { return this.ParseSuccess; } /// /// Generate the columns for the DataTable from the Hashtable (and in a specific order if needed) /// /// /// private DataColumn[] getColumnsFromHashtable(Hashtable ht, Hashtable order) { List columnList = new List(); if (ht != null) { if (order == null) { // No specific order but that's not going to happen foreach (string key in ht.Keys) { Type t = ht[key].GetType(); columnList.Add(new DataColumn(key, t)); } } else { for (int i = 0; i < order.Count; i++) { Type t = ht[(string)order[i]].GetType(); columnList.Add(new DataColumn((string)order[i], t)); } } } return columnList.ToArray(); } /// /// Add a station to the list /// /// Station /// protected bool addStation(Station s) { if (s == null) { return false; } // Create DataTable if needed if (!this._dataset.Tables.Contains(STATIONS_DATATABLE)) { // Create Stations DataTable DataTable dtStations = new DataTable(STATIONS_DATATABLE); dtStations.CaseSensitive = true; // Create columns dtStations.Columns.AddRange(this.getColumnsFromHashtable(s.FieldsDictionary, s.FieldsOrder)); // And add it to the dataset this._dataset.Tables.Add(dtStations); } // Add row DataRow dr = this._dataset.Tables[STATIONS_DATATABLE].NewRow(); // Set value for each field foreach (string key in s.FieldsDictionary.Keys) { dr[key] = s.FieldsDictionary[key]; } // Add row this._dataset.Tables[STATIONS_DATATABLE].Rows.Add(dr); // Add station to the list this._stations.Add(s); return true; } /// /// Link clients to their associated AP /// protected void LinkAPClients() { foreach (Station s in this._stations) { if (string.IsNullOrEmpty(s.BSSID)) { continue; } foreach (AccessPoint ap in this._accessPoints) { if (ap.BSSID == s.BSSID) { ap.addClient(s); break; } } } //this._dataset.Tables[ACCESSPOINTS_DATATABLE].ChildRelations.Add(new DataRelation("Cients", this._dataset.Tables[ACCESSPOINTS_DATATABLE].Columns["BSSID"], this._dataset.Tables[STATIONS_DATATABLE].Columns["BSSID"])); //this._dataset.Tables[STATIONS_DATATABLE].ParentRelations.Add(new DataRelation("Associated AP", this._dataset.Tables[ACCESSPOINTS_DATATABLE].Columns["BSSID"], this._dataset.Tables[STATIONS_DATATABLE].Columns["BSSID"])); } /// /// Add Access Point to the list /// /// Access Point /// protected bool addAccessPoint(AccessPoint ap) { if (ap == null) { return false; } // Create DataTable if needed if (!this._dataset.Tables.Contains(ACCESSPOINTS_DATATABLE)) { // Create Access Points DataTable DataTable dtAPs = new DataTable(ACCESSPOINTS_DATATABLE); dtAPs.CaseSensitive = true; // Create columns dtAPs.Columns.AddRange(this.getColumnsFromHashtable(ap.FieldsDictionary, ap.FieldsOrder)); this._dataset.Tables.Add(dtAPs); } // Add row DataRow dr = this._dataset.Tables[ACCESSPOINTS_DATATABLE].NewRow(); foreach (string key in ap.FieldsDictionary.Keys) { dr[key] = ap.FieldsDictionary[key]; } // Add row this._dataset.Tables[ACCESSPOINTS_DATATABLE].Rows.Add(dr); // Add the Access Point to the list this._accessPoints.Add(ap); return true; } /// /// Return the type of the file (and obviously, also the "name" of the reader to use /// /// Path to the file /// Null if type is unknown or a string with the type public static string getFileType(string path) { Reader r = new CsvReader(path); try { r.Read(); } catch { r = new KismetCsvReader(path); try { r.Read(); } catch { r = new NetXMLReader(path); try { r.Read(); } catch { } } } if (!r.ParseSuccess) { return null; } return r.ReaderType; } /// /// Parse a string containing the date and time /// /// Date string /// DateTime value /// Date/Time string cannot be null or empty /// Date Format is not set protected DateTime parseDateTime(string s) { if (string.IsNullOrEmpty(this.DATE_FORMAT)) { throw new FormatException("Date Format is not set"); } if (string.IsNullOrEmpty(s)) { throw new ArgumentNullException("Date/Time string cannot be null or empty"); } // Parse it DateTime ret = new DateTime(); try { ret = DateTime.ParseExact(s.Trim(), DATE_FORMAT, null); } catch { ret = DateTime.ParseExact(s.Trim(), ALT_DATE_FORMAT, null); } return ret; } } }