using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices;
using System.Collections;
using System.Xml;
using System.Xml.XPath;
using System.Net;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace EmailManager
{
    public partial class ThisAddIn
    {

        Timer MyTimer = new Timer();

        private void ClearCalendarAudits()
        {
            try
            {
                Outlook.Folder calFolder = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) as Outlook.Folder;
                DateTime start = DateTime.Now.AddDays(-7);
                DateTime end = DateTime.Now;
                Outlook.Items rangeAppts = GetAppointmentsInRange(calFolder, start, end);
                if (rangeAppts != null)
                {
                    foreach (Outlook.AppointmentItem appt in rangeAppts)
                    {
                        //Debug.WriteLine(DateTime.Now.ToString() + " - " +"Subject: " + appt.Subject + " Start: " + appt.Start.ToString("g"));
                        if (appt.Subject.StartsWith(" IS-"))
                        {
                            System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +appt.Start + " - " + appt.Subject + " Found !");
                            appt.Delete();
                        }
                    }
                }
            }
            catch
            {

            }
        }


        private void JiraToCalendar(string LogItemsCount)
        {
            Log[] ActivityLog = GetJiraActivity("EID", LogItemsCount);
            if (ActivityLog == null)
            {
                return;
            }
            foreach (var MyLog in ActivityLog)
            {
                //Debug.WriteLine(DateTime.Now.ToString() + " - " +DateTime.Parse(MyLog.Published, System.Globalization.CultureInfo.InvariantCulture) + " - " + MyLog.Summary + " - " + MyLog.Ticket);
                if (!AddAppointment(" " + MyLog.Ticket + " - " + MyLog.Summary, DateTime.Parse(MyLog.Published, System.Globalization.CultureInfo.InvariantCulture).AddMinutes(-15))) //Adjust the 15s to show work in the past
                {
                    //break;
                }
            }
        }

        private void TimerCount_Tick(System.Object sender, System.EventArgs e)
        {
            JiraToCalendar("10");
        }

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            ServicePointManager.ServerCertificateValidationCallback = AcceptAllCertifications;
            ServicePointManager.Expect100Continue = true;
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            MarkEmailsAsHuman();
            MyTimer.Interval = 60000 * 3;
            MyTimer.Tick += TimerCount_Tick;
            MyTimer.Start();

            //ClearCalendarAudits();

            JiraToCalendar("30");

            //this.Application.NewMail += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_NewMailEventHandler(_NewMail);
            this.Application.NewMailEx += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_NewMailExEventHandler(Application_NewMailEx);

            ListenForRawData();
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
            // Note: Outlook no longer raises this event. If you have code that 
            //    must run when Outlook shuts down, see https://go.microsoft.com/fwlink/?LinkId=506785
        }

        private bool AddAppointment(string subject, DateTime StartDate)
        {
            try
            {
                Outlook.Folder calFolder = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) as Outlook.Folder;
                DateTime start = StartDate.AddMinutes(-10); //Cloup updates together between 
                DateTime end = start.AddMinutes(45);
                Outlook.Items rangeAppts = GetAppointmentsInRange(calFolder, start, end);
                if (rangeAppts != null)
                {
                    foreach (Outlook.AppointmentItem appt in rangeAppts)
                    {
                        //Debug.WriteLine(DateTime.Now.ToString() + " - " +"Subject: " + appt.Subject + " Start: " + appt.Start.ToString("g"));
                        if (appt.Subject == subject)
                        {
                            System.Diagnostics.Debug.WriteLine("\t" + DateTime.Now.ToString() + " - " +appt.Subject + " Already exist!");
                            return false; //Cant tell the difference between a duped and clumped work. need to add a UID
                        }
                    }
                }
            }
            catch
            {

            }
            try
            {
                Outlook.AppointmentItem newAppointment = (Outlook.AppointmentItem)this.Application.CreateItem(Outlook.OlItemType.olAppointmentItem);
                newAppointment.Start = StartDate;
                newAppointment.End = StartDate.AddMinutes(15);
                newAppointment.Location = "N/A";
                newAppointment.Body = "";
                newAppointment.AllDayEvent = false;
                newAppointment.Subject = subject;
                newAppointment.ReminderSet = false;
                newAppointment.Categories = "Jira";
                newAppointment.Sensitivity = Outlook.OlSensitivity.olPrivate;
                /*
                newAppointment.Recipients.Add("Roger Harui");
                 * Outlook.Recipients sentTo = newAppointment.Recipients;
                Outlook.Recipient sentInvite = null;
                sentInvite = sentTo.Add("Holly Holt");
                sentInvite.Type = (int)Outlook.OlMeetingRecipientType
                    .olRequired;
                sentInvite = sentTo.Add("David Junca ");
                sentInvite.Type = (int)Outlook.OlMeetingRecipientType
                    .olOptional;
                sentTo.ResolveAll();
                */
                newAppointment.Save();
                //newAppointment.Display(true);
            }
            catch (Exception ex)
            {
                MessageBox.Show("The following error occurred: " + ex.Message);
            }
            return true;
        }

        private bool AddCallLog(string subject, double seconds)
        {
            DateTime start = DateTime.Now.AddSeconds(-seconds); //Watch this, it seems to be multiplying and not adding
            DateTime end = DateTime.Now;

            try
            {
                Outlook.Folder calFolder = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) as Outlook.Folder;
                Outlook.Items rangeAppts = GetAppointmentsInRange(calFolder, start, end);
                if (rangeAppts != null)
                {
                    foreach (Outlook.AppointmentItem appt in rangeAppts)
                    {
                        //Debug.WriteLine(DateTime.Now.ToString() + " - " +"Subject: " + appt.Subject + " Start: " + appt.Start.ToString("g"));
                        if (appt.Subject == subject)
                        {
                            System.Diagnostics.Debug.WriteLine("\t" + DateTime.Now.ToString() + " - " +appt.Subject + " Already exist!");
                            return false; //Cant tell the difference between a duped and clumped work. need to add a UID
                        }
                    }
                }
            }
            catch
            {

            }
            try
            {
                Outlook.AppointmentItem newAppointment = (Outlook.AppointmentItem)this.Application.CreateItem(Outlook.OlItemType.olAppointmentItem);
                newAppointment.Start = start;
                newAppointment.End = end;
                newAppointment.Location = "N/A";
                newAppointment.Body = "";
                newAppointment.AllDayEvent = false;
                newAppointment.Subject = subject;
                newAppointment.ReminderSet = false;
                newAppointment.Categories = "PhoneCall";
                newAppointment.Sensitivity = Outlook.OlSensitivity.olPrivate;

                newAppointment.Save();
                //newAppointment.Display(true);
            }
            catch (Exception ex)
            {
                MessageBox.Show("The following error occurred: " + ex.Message);
            }
            return true;
        }
        private Outlook.Items GetAppointmentsInRange(Outlook.Folder folder, DateTime startTime, DateTime endTime)
        {
            string filter = "[Start] >= '"
                + startTime.ToString("g")
                + "' AND [End] <= '"
                + endTime.ToString("g") + "'";
            Debug.WriteLine(DateTime.Now.ToString() + " - " +filter);
            try
            {
                Outlook.Items calItems = folder.Items;
                calItems.IncludeRecurrences = true;
                calItems.Sort("[Start]", Type.Missing);
                Outlook.Items restrictItems = calItems.Restrict(filter);
                if (restrictItems.Count > 0)
                {
                    return restrictItems;
                }
                else
                {
                    return null;
                }
            }
            catch { return null; }
        }

        ArrayList Humans = new ArrayList();
        ArrayList NonHumans = new ArrayList();
        object Item = null;
        Outlook._MailItem moveMail = null;
        Outlook.Items resultItems = null;

        private void Application_NewMailEx(string EntryIDCollection)
        {
            /*string senderEmailid = string.Empty;
            Outlook.NameSpace outlookNameSpace = this.Application.GetNamespace("MAPI");
            Outlook.Application myApp = new Outlook.Application();
            Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
            Outlook.MAPIFolder myInbox = mapiNameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
            Outlook.Attachments attachments;
            int test = myInbox.Items.Count;
            */
                object Item = Application.Session.GetItemFromID(EntryIDCollection, Type.Missing) as Outlook.MailItem;
            if (Item is Outlook._MailItem)
            {
                ProcessMailItem(Item as Outlook.MailItem);
            }
        }

        private void MarkEmailsAsHuman()
        {
            Outlook.MAPIFolder inBox = (Outlook.MAPIFolder) this.Application.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);

            Outlook.Items inboxitems = (Outlook.Items)inBox.Items;


            //sFilter = "[LastModificationTime] > '" & Format("1/15/99 3:30pm", "ddddd h:nn AMPM") & "'"
            //items.Restrict("[UnRead] = true");
            //Outlook.MAPIFolder destFolder = inBox.Folders ["Inbox"];
            //Outlook.MAPIFolder destFolder = this.Application.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
            string Restricting = "([LastModificationTime] > '" + DateTime.Now.AddDays(-2).ToString("yyyy-MM-dd HH:mm") + "' or [ReceivedTime] > '" + DateTime.Now.AddDays(-2).ToString("yyyy-MM-dd HH:mm") + "')";
            //string Restricting = "[UnRead] = true and ([LastModificationTime] > '" + DateTime.Now.AddDays(-2).ToString("yyyy-MM-dd HH:mm") + "' or [ReceivedTime] > '" + DateTime.Now.AddDays(-2).ToString("yyyy-MM-dd HH:mm") + "')";
            //string Restricting = "[UnRead] = true";
            resultItems = inboxitems.Restrict(Restricting);
            //Dictionary<string, string> SenderToAD = new Dictionary<string, string>();

            Item = resultItems.GetFirst();
            while (Item != null)
            {
                if (Item is Outlook._MailItem)
                {
                    ProcessMailItem(Item as Outlook.MailItem);
                }

                Marshal.ReleaseComObject(Item);
                Item = resultItems.GetNext();
            }
            /*
            foreach (object eMail in resultItems)
            {
                moveMail = eMail as Outlook.MailItem;
                try
                {
                    if (!(moveMail is null))
                    {
                        System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +moveMail.UnRead + " " + moveMail.ReceivedTime + " / " + moveMail.LastModificationTime + " - " + (string)moveMail.SenderEmailAddress + " " +  (string)moveMail.Subject);
                        //if (!(moveMail.ReceivedTime is null))
                        //{
                        if (moveMail.ReceivedTime > (DateTime.Now.AddDays(-2)))
                        {
                            if (!(moveMail.Subject is null))
                            {
                                if (moveMail.SenderEmailAddress.StartsWith("/O=EISENHOWER MEDICAL CENTER", StringComparison.OrdinalIgnoreCase))
                                {
                                    if (!(moveMail.Categories is null))
                                    {
                                        System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +moveMail.Categories);
                                    }
                                    if (moveMail.Categories != "Human")
                                    {
                                        moveMail.Categories = "Human";
                                        moveMail.Save();
                                    }
                                    //string titleSubject = (string)moveMail.Subject;
                                }
                            }
                        }
                        else
                        {
                            //return;
                        }
                        //}
                    }
                }
                catch (Exception ex)
                {
                    return;
                    MessageBox.Show(ex.Message);
                    if (ex.Message.StartsWith("Out of memory or system resources", StringComparison.OrdinalIgnoreCase))
                    {
                        Application.Quit();
                    }
                }
            }
            */
        }


        private void ProcessMailItem(Outlook.MailItem Item)
        {
            if (Item is Outlook._MailItem)
            {
                moveMail = Item as Outlook.MailItem;
                if (Humans.Contains(moveMail.SenderEmailAddress))
                {
                    if (moveMail.Categories != "Human")
                    {
                        moveMail.Categories = "Human";
                        moveMail.Save();
                    }
                    return;
                }

                if (NonHumans.Contains(moveMail.SenderEmailAddress))
                {
                    return;
                }

                Outlook.Recipient recipient = moveMail.Application.Session.CreateRecipient(moveMail.SenderEmailAddress);

                System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +moveMail.SenderEmailAddress + " " + (string) moveMail.Subject);
                if (recipient != null && recipient.Resolve() && recipient.AddressEntry != null)
                {
                    Outlook.ExchangeUser exUser = recipient.AddressEntry.GetExchangeUser();
                    if (exUser != null && !string.IsNullOrEmpty(exUser.Alias))
                    {
                        using (PrincipalContext pc = new PrincipalContext(ContextType.Domain))
                        {
                            /*System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +exUser.Alias + " - " + exUser.Address);
                            if (exUser.Alias == "ssharpe")
                            {
                                System.Diagnostics.Debugger.Break();
                            }
                            */
                            UserPrincipal up = UserPrincipal.FindByIdentity(pc, exUser.Alias);
                            if (up != null)
                            {
                                DirectoryEntry directoryEntry = up.GetUnderlyingObject() as DirectoryEntry;
            System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +directoryEntry.Path);
                                if (directoryEntry.Properties.Contains("wWWHomePage"))
                                {
                                    //deliveryOffice = directoryEntry.Properties["wWWHomePage"].Value.ToString();
                                    //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +moveMail.UnRead + " " + moveMail.ReceivedTime + " / " + moveMail.LastModificationTime + " - " + (string)moveMail.SenderEmailAddress + " " + (string)moveMail.Subject);
                                    if (moveMail.ReceivedTime > (DateTime.Now.AddDays(-2)))
                                    {
                                        if (!(moveMail.Subject is null))
                                        {
                                            if (moveMail.SenderEmailAddress.StartsWith("/O=EISENHOWER MEDICAL CENTER", StringComparison.OrdinalIgnoreCase))
                                            {
                                                Humans.Add(moveMail.SenderEmailAddress);

                                                if (moveMail.Categories != "Human")
                                                {
                                                    if (!(moveMail.Categories is null))
                                                    {
                                                        System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +moveMail.Categories);
                                                    }
                                                    moveMail.Categories = "Human";
                                                    moveMail.Save();
                                                }
                                                //string titleSubject = (string)moveMail.Subject;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    NonHumans.Add(moveMail.SenderEmailAddress);
                                    moveMail.Categories = "";
                                    moveMail.Save();
                                    System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +"1");
                                }
                            }
                            else
                            {
                                NonHumans.Add(moveMail.SenderEmailAddress);
                                moveMail.Categories = "";
                                moveMail.Save();
                                System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +"2");
                            }
                        }
                    }
                    else
                    {
                        NonHumans.Add(moveMail.SenderEmailAddress);
                        System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +moveMail.Subject);
                        moveMail.Categories = "";
                        moveMail.Save();
                        System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +"3");
                    }
                }
                else
                {
                    NonHumans.Add(moveMail.SenderEmailAddress);
                    moveMail.Categories = "";
                    moveMail.Save();
                    System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " - " +"4");
                }
            }
        }







        //https://jira.FQDN.org/plugins/servlet/gadgets/ifr?container=atlassian&mid=1&country=US&lang=en&view=default&view-params=%7B%22writable%22%3A%22false%22%7D&st=atlassian%3ACHEhujCuDk7wVctYMBFtIB6EC%2FsWWjT0NvqsMcRrrEjOTyApQg5A%2Bx%2FF6RMyK3KngdA2uz0YCRp66uc18ivqE0uu%2B8qzlP6%2F2bEudWu5oAcCkP8LVpCd7vERN1liX8wsnQ%2F8ARYrcH%2F82pOewKgs52752hgU8%2FoVLVgbin%2BpIMbCZGR8%2FG6IsPfPfci6%2Bt4HtjXsYZObGEC%2BnzjFs0j8OJmsxZSPI%2FZ8NCky1Ikty%2B85LF3vWK%2F4cVz8BaeTwyiRtL9HWkOHzBvVEAZeG5XttSA%2FiRk%3D&up_isConfigured=true&up_isReallyConfigured=false&up_title=Activity+Stream&up_titleRequired=false&up_numofentries=10&up_refresh=false&up_maxProviderLabelCharacters=50&up_rules=&up_renderingContext=&up_keys=&up_itemKeys=&up_username=EID&url=https%3A%2F%2Fjira.FQDN.org%2Frest%2Fgadgets%2F1.0%2Fg%2Fcom.atlassian.streams.streams-jira-plugin%2Fgadgets%2Factivitystream-gadget.xml&libs=auth-refresh#rpctoken=988677668

        const string JiraURL = "https://jira.FQDN.org/activity?maxResults=10&streams=user+IS+EID&os_authType=basic&title=mytitle";

        private struct Log
        {
            public string Ticket;
            public string Published;
            public string Summary;
        }

        private Log[] GetJiraActivity(string UserEID, string MaxResults)
        {
            Log[] MyLogsToReturn = new Log[Convert.ToInt32(MaxResults)];
            int I = -1;
            // Create a WebRequest to the remote site
            System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create("https://jira.FQDN.org/activity?maxResults=" + MaxResults + "&streams=user+IS+" + UserEID + "&os_authType=basic&title=mytitle");
            // NB! Use the following line ONLY if the website is protected
            request.UseDefaultCredentials = true;
            request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
            request.Credentials = CredentialCache.DefaultNetworkCredentials;

            request.Credentials = new System.Net.NetworkCredential("EID", "Password");

            System.Net.HttpWebResponse response = null;
            // Call the remote site, and parse the data in a response object
            try
            {
                response = (HttpWebResponse)request.GetResponse();
            }
            catch
            {
                return null;
            }

            // Check if the response is OK (status code 200)
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                // Parse the contents from the response to a stream object
                System.IO.Stream stream = response.GetResponseStream();
                // Create a reader for the stream object
                System.IO.StreamReader reader = new System.IO.StreamReader(stream);
                // Read from the stream object using the reader, put the contents in a string
                string contents = reader.ReadToEnd();
                // Create a new, empty XML document
                System.Xml.XmlDocument document = new System.Xml.XmlDocument();
                // Load the contents into the XML document
                document.LoadXml(contents);
                // 
                // 
                XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
                nsmgr.AddNamespace("http://www.w3.org/2005/Atom", document.DocumentElement.NamespaceURI);
                // Now you have a XmlDocument object that contains the XML from the remote site, you can
                // use the objects and methods in the System.Xml namespace to read the document
                XmlNodeList rssNodes = document.SelectNodes("//feed/entry");
                StringBuilder rssContent = new StringBuilder();

                foreach (XmlNode MyNode in document.ChildNodes)
                {
                }

                XPathDocument xpathDoc;
                XPathNavigator xmlNav;
                XPathNodeIterator xmlNI;
                XmlReader XmlReader = new XmlNodeReader(document);
                xpathDoc = new XPathDocument(XmlReader);
                xmlNav = xpathDoc.CreateNavigator();
                xmlNI = xmlNav.Select("/");

                xmlNI.MoveNext();
                xmlNI.Current.MoveToFirstChild();
                if (!(xmlNI.Current.IsEmptyElement))
                {
                }

                if ((xmlNI.Current.HasChildren))
                {
                    while ((xmlNI.Current.Name != "feed"))
                        xmlNI.MoveNext();

                    xmlNI.Current.MoveToFirstChild();

                    while ((xmlNI.Current.Name != "entry"))
                        xmlNI.Current.MoveToNext();

                    xmlNI.Current.MoveToFirstChild();

                    bool RestartWhile = false;

                    while (true)
                    {
                        if ((!RestartWhile))
                        {
                            I += 1;
                            while ((xmlNI.Current.Name != "published"))
                            {
                                if ((!xmlNI.Current.MoveToNext()))
                                    return null;
                                if ((xmlNI.Current.Name == "published"))
                                {
                                    MyLogsToReturn[I].Published = xmlNI.Current.Value;
                                    // Debug.WriteLine(DateTime.Now.ToString() + " - " +xmlNI.Current.Name + " : " + xmlNI.Current.Value)
                                    break;
                                }
                            }
                        }

                        RestartWhile = false;

                        while ((xmlNI.Current.Name != "activity:target" & xmlNI.Current.Name != "activity:object"))
                        {
                            if ((!xmlNI.Current.MoveToNext()))
                                return null;
                        }

                        xmlNI.Current.MoveToFirstChild();

                        while ((xmlNI.Current.Name != "title"))
                        {
                            if ((!xmlNI.Current.MoveToNext()))
                            {
                                xmlNI.Current.MoveToParent();
                                xmlNI.Current.MoveToNext();
                                RestartWhile = true;
                                break;
                            }
                            if ((xmlNI.Current.Value.Contains("IS-")))
                                MyLogsToReturn[I].Ticket = xmlNI.Current.Value;
                        }

                        if (RestartWhile)
                            continue;

                        while ((xmlNI.Current.Name != "summary"))
                        {
                            if ((!xmlNI.Current.MoveToNext()))
                            {
                                xmlNI.Current.MoveToParent();
                                xmlNI.Current.MoveToNext();
                                RestartWhile = true;
                                break;
                            }
                            if ((xmlNI.Current.Name == "summary"))
                                MyLogsToReturn[I].Summary = xmlNI.Current.Value;
                        }

                        if (RestartWhile)
                            continue;

                        xmlNI.Current.MoveToParent();
                        xmlNI.Current.MoveToParent();
                        if ((!xmlNI.Current.MoveToNext()))
                            break;
                        xmlNI.Current.MoveToFirstChild();
                    }

                    return MyLogsToReturn;
                }
            }
            else
            {
                // If the call to the remote site fails, you'll have to handle this. There can be many reasons, ie. the 
                // remote site does not respond (code 404) or your username and password were incorrect (code 401)
                // 
                // See the codes in the System.Net.HttpStatusCode enumerator 
                throw new Exception("Could not retrieve document from the URL, response code: " + response.StatusCode);
            }
            return null;
        }

        public bool AcceptAllCertifications(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certification, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }


        ArrayList ByeServerList = new ArrayList();
        ArrayList ByeSipList = new ArrayList();
        ArrayList PhonePickedUpList = new ArrayList();

        private System.Net.Sockets.Socket RAWSocket;
        private const int IOC_VENDOR = 0x18000000;
        private const int IOC_IN = -2147483648;
        private const int SIO_RCVALL = IOC_IN | IOC_VENDOR | 1;
        private const int SECURITY_BUILTIN_DOMAIN_RID = 0x20;
        private const int DOMAIN_ALIAS_RID_ADMINS = 0x220;
        private string MyIPAddr = "";
        private StateObject MyStateObject;
        public class StateObject
        {
            public System.Net.Sockets.Socket workSocket = null;
            public const int BUFFER_SIZE = 65535;
            public byte[] buffer = new byte[65536];
            public System.Text.StringBuilder sb = new System.Text.StringBuilder();
        } // StateObject

        private void ListenForRawData()
        {
            // To get local address
            string sHostName;
            sHostName = System.Net.Dns.GetHostName();
            System.Net.IPHostEntry ipE = System.Net.Dns.GetHostByName(sHostName);
            System.Net.IPAddress[] IpA = ipE.AddressList;
            MyIPAddr = IpA[0].ToString();

            MyStateObject = new StateObject();
            RAWSocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Raw, System.Net.Sockets.ProtocolType.IP);
            byte[] OptionIn = BitConverter.GetBytes(1);
            byte[] OptionOut = null;

            byte[] InByte = new byte[] { 1, 0, 0, 0 };
            byte[] outByte = new byte[5];

            // RAWSocket.Bind(New System.Net.IPEndPoint(Net.IPAddress.Any, 0))
            RAWSocket.Bind(new System.Net.IPEndPoint(System.Net.IPAddress.Parse(MyIPAddr), 0)); // must be bound to a IP
                                                                                                // 
            RAWSocket.IOControl(SIO_RCVALL, InByte, outByte);
            RAWSocket.BeginReceive(MyStateObject.buffer, 0, StateObject.BUFFER_SIZE, System.Net.Sockets.SocketFlags.Peek, new AsyncCallback(SockCallBack), null);
            Debug.WriteLine(DateTime.Now.ToString() + " - " +"Listening On: " + MyIPAddr);
        }

        private void SockCallBack(System.IAsyncResult ar)
        {
            var BytesReturned = RAWSocket.EndReceive(ar);

            string ListboxData = null;
            switch (MyStateObject.buffer[9])
            {
                case 0x1 // Protocol ICMP
               :
                    {
                        break;
                    }

                case 0x2:
                    {
                        break;
                    }

                case 0x6 // TCP
       :
                    {
                        break;
                    }

                case 0x11 // UDP
       :
                    {
                        break;
                    }

                default:
                    {
                        break;
                    }
            }

            // For i = 0 To BytesReturned - 1
            // Debug.Write(Hex$(MyStateObject.buffer(i)) & " ")
            // If i = 9 Or i = 19 Or i = 29 Or i = 39 Or i = 49 Then Debug.WriteLine(DateTime.Now.ToString() + " - " +"")
            // Next
            // Debug.WriteLine(DateTime.Now.ToString() + " - " +"")
            // Debug.WriteLine(DateTime.Now.ToString() + " - " +"")
            // 

            switch (MyStateObject.buffer[9])
            {
                case 0x1:
                    {
                        string FROMIP = MyStateObject.buffer[12] + "." + MyStateObject.buffer[13] + "." + MyStateObject.buffer[14] + "." + MyStateObject.buffer[15];
                        string DESTIP = MyStateObject.buffer[16] + "." + MyStateObject.buffer[17] + "." + MyStateObject.buffer[18] + "." + MyStateObject.buffer[19];

                        if (FROMIP == MyIPAddr)
                        {
                            if (MyStateObject.buffer[20] == 0)
                                Debug.WriteLine(DateTime.Now.ToString() + " - " +"You sent a Ping Reply to: " + DESTIP);
                            else
                                Debug.WriteLine(DateTime.Now.ToString() + " - " +"You sent a Ping Request to: " + DESTIP);
                            RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null);
                            return;
                        }

                        if (MyStateObject.buffer[20] == 0)
                        {
                            Debug.WriteLine(DateTime.Now.ToString() + " - " +"Ping Reply: " + FROMIP);
                            RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null);
                            return;
                        }

                        Debug.WriteLine(DateTime.Now.ToString() + " - " +"Ping Request From - " + FROMIP + " | Bytes: " + (BytesReturned - 28) + " | TTL=" + MyStateObject.buffer[8]); // -28 shows the ping payload
                        break;
                    }

                case 0x2:
                    {
                        break;
                    }

                case 0x6:
                    {
                        //Debug.WriteLine(DateTime.Now.ToString() + " - " +"TCP ");
                        uint DestPort = MyStateObject.buffer[22];
                        DestPort <<= 8;
                        DestPort += MyStateObject.buffer[23];

                        uint SrcPort = MyStateObject.buffer[20];
                        SrcPort <<= 8;
                        SrcPort += MyStateObject.buffer[21];

                        string FROMIP = MyStateObject.buffer[12] + "." + MyStateObject.buffer[13] + "." + MyStateObject.buffer[14] + "." + MyStateObject.buffer[15];

                        string Data = null; // = System.Text.ASCIIEncoding.ASCII.GetString(MyStateObject.buffer)

                        if (DestPort != 5060 && SrcPort != 5060)
                        {
                            RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null);
                            return; 
                        }

                        foreach (byte MyByte in MyStateObject.buffer)
                        {
                            if ((MyByte >= 32 && MyByte <= 126) || MyByte == 0x0d || MyByte == 0x0a)
                                Data += System.Text.ASCIIEncoding.ASCII.GetString(new[] { MyByte });
                        }
                        Debug.WriteLine("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
                        //Debug.WriteLine(DateTime.Now.ToString() + " - " + "Data: " + SrcPort + " -> " + DestPort + " | " + Data);

                        string myTo = null;
                        string myFrom = null;
                        string myDuration = null;

                        MatchCollection matches = Regex.Matches(Data, @"(To|From):.*?<sip:[%|\d]{1,14}@.*?>");
                        // Loop over matches.
                        foreach (Match m in matches)
                        {
                            // Loop over captures.
                            foreach (Capture c in m.Captures)
                            {
                                // Display.
                                // Console.WriteLine("Index={0}, Value={1}", c.Index, c.Value)
                                if (c.Value.Contains("From:"))
                                    myFrom = c.Value;
                                if (c.Value.Contains("To:"))
                                    myTo = c.Value;
                            }


                        }

                        if (myTo == null || myFrom == null)
                        {
                            // System.Diagnostics.Debugger.Break();
                            RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null);
                            Debug.WriteLine("No to and from, Skipping...");
                            if (Data.Contains("BYE") && Data.Contains("RTP-TxStat:"))
                            {
                                //System.Diagnostics.Debugger.Break();
                            }
                            return;
                        }

                        if (Data.Contains("INVITE sip"))
                            Debug.WriteLine(DateTime.Now.ToString() + " - " +"Incomming call: " + myFrom + " -> " + myTo);

                        if (Data.Contains("Request Cancelled"))
                            Debug.WriteLine(DateTime.Now.ToString() + " - " +"Request Canceled: " + myFrom + " -> " + myTo);

                        //PhonePickedUpList
                        if (Data.Contains("ACK sip:"))
                        {
                            MatchCollection matches3 = Regex.Matches(Data, @"Session-ID: [[0-9a-fA-F]+;");
                            // Loop over matches.
                            foreach (Match m in matches3)
                            {
                                if (PhonePickedUpList.Contains(m.Value))
                                {
                                    //Debug.WriteLine(DateTime.Now.ToString() + " - " +"Call Concluded");
                                    RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null);
                                    return;
                                }
                                PhonePickedUpList.Add(m.Value);
                            }
                            Debug.WriteLine(DateTime.Now.ToString() + " - " + "Callee Picked up the phone: " + myFrom + " -> " + myTo);
                        }


                        if (Data.Contains("SIP/2.0 180 Ringing"))
                            Debug.WriteLine(DateTime.Now.ToString() + " - " +"Ringing Phone: " + myFrom + " -> " + myTo);

                        if (Data.Contains("UPDATE sip"))
                            Debug.WriteLine(DateTime.Now.ToString() + " - " + "UPDATE sip: " + myFrom + " -> " + myTo);

                        if (Data.Contains("CANCEL sip")) // Call missed
                            Debug.WriteLine(DateTime.Now.ToString() + " - " +"CANCEL sip: " + myFrom + " -> " + myTo);

                        if (Data.Contains("UPDATE sip"))
                            Debug.WriteLine(DateTime.Now.ToString() + " - " +"UPDATE sip: " + myFrom + " -> " + myTo);

                        if (Data.Contains("BYE sip"))
                        {
                            MatchCollection matches3 = Regex.Matches(Data, @"Session-ID: [[0-9a-fA-F]+;");
                            // Loop over matches.
                            foreach (Match m in matches3)
                            {
                                if (ByeSipList.Contains(m.Value))
                                {
                                    //Debug.WriteLine(DateTime.Now.ToString() + " - " +"Call Concluded");
                                    RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null);
                                    return;
                                }
                                ByeSipList.Add(m.Value);
                            }

                            Debug.WriteLine(DateTime.Now.ToString() + " - " +"Call ending: " + myFrom + " -> " + myTo);

                            MatchCollection matches2 = Regex.Matches(Data, @"RTP-RxStat: Dur=[\d]+,");
                            // Loop over matches.
                            foreach (Match m in matches2)
                            {
                                myDuration = m.Value.ToString().Replace("RTP-RxStat: Dur=", "").Replace(",", "");
                                Debug.WriteLine(DateTime.Now.ToString() + " - " +"BYE sip: Duration of call in seconds: " + myDuration);
                            }

                            if (myDuration != null)
                            {
                                Int32 ISeconds = Convert.ToInt32(myDuration) + 60;
                                Double DSeconds = Convert.ToDouble(ISeconds);
                                if (!AddCallLog(" " + myFrom + " -> " + myTo, DSeconds)) //Add a minute to each call. Each call takes at least a minute of our day right?
                                {
                                    Debug.WriteLine(DateTime.Now.ToString() + " - " +"Failed to write calllog");
                                    //break;
                                }
                            }  
                        }



                        if (Data.Contains("BYE\r\nServer: Cisco-CSF") && Data.Contains("RTP-TxStat:")) //OKVia: SIP
                        {
                            MatchCollection matches3 = Regex.Matches(Data, @"Session-ID: [[0-9a-fA-F]+;");
                            // Loop over matches.
                            foreach (Match m in matches3)
                            {
                                if (ByeServerList.Contains(m.Value))
                                {
                                    //Debug.WriteLine(DateTime.Now.ToString() + " - " +"Call Concluded");
                                    RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null);
                                    return;
                                }
                                ByeServerList.Add(m.Value);
                            }

                            Debug.WriteLine(DateTime.Now.ToString() + " - " +"Call ending from Callee: " + myFrom + " -> " + myTo);

                            MatchCollection matches2 = Regex.Matches(Data, @"RTP-RxStat: Dur=[\d]+,");
                            // Loop over matches.
                            foreach (Match m in matches2)
                            {
                                myDuration = m.Value.ToString().Replace("RTP-RxStat: Dur=", "").Replace(",", "");
                                Debug.WriteLine(DateTime.Now.ToString() + " - " + "BYEServer: Duration of call in seconds: " + myDuration);
                            }

                            if (myDuration != null)
                            {
                                Int32 ISeconds = Convert.ToInt32(myDuration) + 60;
                                Double DSeconds = Convert.ToDouble(ISeconds);
                                if (!AddCallLog(" " + myFrom + " -> " + myTo, DSeconds)) //Add a minute to each call. Each call takes at least a minute of our day right?
                                {
                                    Debug.WriteLine(DateTime.Now.ToString() + " - " +"Failed to write calllog");
                                    //break;
                                }
                            }
                        }


                        if (Data.Contains("Accepted"))
                            Debug.WriteLine(DateTime.Now.ToString() + " - " +"Accepted: " + myFrom + " -> " + myTo);

                        switch (MyStateObject.buffer[33])
                        {
                            case 0x2:
                                {
                                    break;
                                }

                            case 0x10:
                                {
                                    break;
                                }

                            case 0x11:
                                {
                                    break;
                                }

                            case 0x12:
                                {
                                    break;
                                }

                            case 0x14:
                                {
                                    break;
                                }

                            case 0x18:
                                {
                                    //Debug.Write("[PSH, ACK] - ");
                                    break;
                                }

                            default:
                                {
                                    break;
                                }
                        }

                        break;
                    }

                case 0x11:
                    {
                        break;
                    }

                default:
                    {
                        break;
                    }
            }

            // For i = 0 To BytesReturned - 1
            // Debug.Write(Hex$(MyStateObject.buffer(i)) & " ")
            // If i = 9 Or i = 19 Or i = 29 Or i = 39 Or i = 49 Then Debug.WriteLine(DateTime.Now.ToString() + " - " +"")
            // Next
            // Debug.WriteLine(DateTime.Now.ToString() + " - " +"")
            // Debug.WriteLine(DateTime.Now.ToString() + " - " +"")
            // 
            RAWSocket.BeginReceive(MyStateObject.buffer, 0, 65535, System.Net.Sockets.SocketFlags.None, new AsyncCallback(SockCallBack), null);
        }



        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }

        #endregion
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax