Пример #1
0
        private void Write(Headers header, HeaderFields field)
        {
            var bytes = header[field];

            _writer.Write((byte)field);
            _writer.Write((short)bytes.Length);
            _writer.Write(bytes, 0, bytes.Length);
        }
Пример #2
0
        ///<summary>Returns text information about this HttpClient object.</summary>
        ///<returns>A string representing this HttpClient object.</returns>
        ///<param name="WithUrl">Specifies whether or not to include information about the requested URL.</param>
        public string ToString(bool WithUrl)
        {
            string Ret;

            try {
                if (DestinationSocket == null || DestinationSocket.RemoteEndPoint == null)
                {
                    Ret = "Incoming HTTP connection from " + ((IPEndPoint)ClientSocket.RemoteEndPoint).Address.ToString();
                }
                else
                {
                    Ret = "HTTP connection from " + ((IPEndPoint)ClientSocket.RemoteEndPoint).Address.ToString() + " to " + ((IPEndPoint)DestinationSocket.RemoteEndPoint).Address.ToString() + " on port " + ((IPEndPoint)DestinationSocket.RemoteEndPoint).Port.ToString();
                }
                if (HeaderFields != null && HeaderFields.ContainsKey("Host") && RequestedPath != null)
                {
                    Ret += "\r\n" + " requested URL: http://" + HeaderFields["Host"] + RequestedPath;
                }
            } catch {
                Ret = "HTTP Connection";
            }
            return(Ret);
        }
Пример #3
0
        public void AddHeaderField(string name, string value)
        {
            string key = name.ToLower();

            if (HeaderFields[key] == null || key.Equals("received"))
            {
                HeaderFields.Add(key, value);
            }
            else
            {
                HeaderFields[key] = value;
            }

            if (HeaderFieldNames[key] == null || key.Equals("received"))
            {
                HeaderFieldNames.Add(key, name);
            }
            else
            {
                HeaderFieldNames[key] = name;
            }
        }
Пример #4
0
        private void ProcessQuery(string Query)
        {
            HeaderFields = ParseQuery(Query);
            if (HeaderFields == null || !HeaderFields.ContainsKey("Host"))
            {
                SendBadRequest();
                return;
            }
            int    Port;
            string Host;
            int    Ret;

            if (HttpRequestType.ToUpper().Equals("CONNECT"))       //HTTPS
            {
                Ret = RequestedPath.IndexOf(":");
                if (Ret >= 0)
                {
                    Host = RequestedPath.Substring(0, Ret);
                    if (RequestedPath.Length > Ret + 1)
                    {
                        Port = int.Parse(RequestedPath.Substring(Ret + 1));
                    }
                    else
                    {
                        Port = 443;
                    }
                }
                else
                {
                    Host = RequestedPath;
                    Port = 443;
                }
            }
            else         //Normal HTTP
            {
                Ret = ((string)HeaderFields["Host"]).IndexOf(":");
                if (Ret > 0)
                {
                    Host = ((string)HeaderFields["Host"]).Substring(0, Ret);
                    Port = int.Parse(((string)HeaderFields["Host"]).Substring(Ret + 1));
                }
                else
                {
                    Host = (string)HeaderFields["Host"];
                    Port = 80;
                }
                if (HttpRequestType.ToUpper().Equals("POST"))
                {
                    int index = Query.IndexOf("\r\n\r\n");
                    m_HttpPost = Query.Substring(index + 4);
                }
            }
            try {
                IPEndPoint DestinationEndPoint = new IPEndPoint(Dns.Resolve(Host).AddressList[0], Port);
                DestinationSocket = new Socket(DestinationEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                if (HeaderFields.ContainsKey("Proxy-Connection") && HeaderFields["Proxy-Connection"].ToLower().Equals("keep-alive"))
                {
                    DestinationSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
                }
                DestinationSocket.BeginConnect(DestinationEndPoint, new AsyncCallback(this.OnConnected), DestinationSocket);
            } catch {
                SendBadRequest();
                return;
            }
        }
Пример #5
0
 public void AddHeaderField(Field field)
 {
     HeaderFields.Add(field);
 }
Пример #6
0
        ///<summary>Processes a specified query and connects to the requested HTTP web server.</summary>
        ///<param name="Query">A string containing the query to process.</param>
        ///<remarks>If there's an error while processing the HTTP request or when connecting to the remote server, the Proxy sends a "400 - Bad Request" error to the client.</remarks>
        private void ProcessQuery(string Query)
        {
            HeaderFields = ParseQuery(Query);
            if (HeaderFields == null || !HeaderFields.HasKeys() || !DoHeadersContainKey(HeaderFields, "Host"))
            {
                SendBadRequest();
                return;
            }

            if (OnProcessQueryEnd != null)
            {
                OnProcessQueryEnd.Invoke(DestinationSocket, this);
            }
            if (Cancel)
            {
                SendCancelledResponse();
                return;
            }

            int    Port;
            string Host;
            int    Ret;

            if (HttpRequestType.ToUpper().Equals("CONNECT"))
            {
                //HTTPS
                Ret = RequestedPath.IndexOf(":");
                if (Ret >= 0)
                {
                    Host = RequestedPath.Substring(0, Ret);
                    if (RequestedPath.Length > Ret + 1)
                    {
                        Port = int.Parse(RequestedPath.Substring(Ret + 1));
                    }
                    else
                    {
                        Port = 443;
                    }
                }
                else
                {
                    Host = RequestedPath;
                    Port = 443;
                }
            }
            else
            {
                //Normal HTTP
                Ret = (HeaderFields["Host"]).IndexOf(":");
                if (Ret > 0)
                {
                    Host = (HeaderFields["Host"]).Substring(0, Ret);
                    Port = int.Parse((HeaderFields["Host"]).Substring(Ret + 1));
                }
                else
                {
                    Host = HeaderFields["Host"];
                    Port = 80;
                }
                if (HttpRequestType.ToUpper().Equals("POST"))
                {
                    int index = Query.IndexOf("\r\n\r\n");
                    m_HttpPost = Query.Substring(index + 4);
                }
            }
            try
            {
                IPEndPoint DestinationEndPoint = new IPEndPoint(Dns.Resolve(Host).AddressList[0], Port);
                DestinationSocket = new Socket(DestinationEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                if (DoHeadersContainKey(HeaderFields, "Proxy-Connection") && HeaderFields["Proxy-Connection"].ToLower().Equals("keep-alive"))
                {
                    //DestinationSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
                }
                DestinationSocket.BeginConnect(DestinationEndPoint, OnConnected, DestinationSocket);
            }
            catch
            {
                SendBadRequest();
                return;
            }
        }
 private unsafe UInt32 GetHeaderField(Byte[] source, UInt32 start, HeaderFields field)
 {
     UInt32 val = 0;
     fixed (Byte* src = source) if (MemCompare(src + start, "QCLZ")) val = ((UInt32*)(src + start))[(Int32)field];
     return val;
 }
Пример #8
0
        private void ProcessQuery(string Query)
        {
            HeaderFields = ParseQuery(Query);
            if (HeaderFields == null || !HeaderFields.ContainsKey("Host"))
            {
                SendBadRequest();
                return;
            }

            if (UserValidator != null)
            {
                var authValid = true;

                try
                {
                    if (HeaderFields.ContainsKey("Proxy-Authorization") == false)
                    {
                        authValid = false;
                    }
                    else
                    {
                        var authHeader = HeaderFields["Proxy-Authorization"];
                        if (authHeader.IndexOf("Basic") > -1)
                        {
                            var base64String = authHeader.Replace("Basic", "").Trim();
                            var strUserPass  = Encoding.UTF8.GetString(Convert.FromBase64String(base64String));
                            var authParam    = strUserPass.Split(':');
                            var username     = authParam[0];
                            var password     = authParam[1];

                            authValid = UserValidator.IsValid(username, password);
                        }
                        else
                        {
                            authValid = false;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Write(MethodInfo.GetCurrentMethod(), ex);
                    authValid = false;
                }

                if (authValid == false)
                {
                    SendAuthenticationFailed();
                    return;
                }
            }


            int    Port;
            string Host;
            int    Ret;

            if (HttpRequestType.ToUpper().Equals("CONNECT"))
            { //HTTPS
                Ret = RequestedPath.IndexOf(":");
                if (Ret >= 0)
                {
                    Host = RequestedPath.Substring(0, Ret);
                    if (RequestedPath.Length > Ret + 1)
                    {
                        Port = int.Parse(RequestedPath.Substring(Ret + 1));
                    }
                    else
                    {
                        Port = 443;
                    }
                }
                else
                {
                    Host = RequestedPath;
                    Port = 443;
                }
            }
            else
            { //Normal HTTP
                Ret = ((string)HeaderFields["Host"]).IndexOf(":");
                if (Ret > 0)
                {
                    Host = ((string)HeaderFields["Host"]).Substring(0, Ret);
                    Port = int.Parse(((string)HeaderFields["Host"]).Substring(Ret + 1));
                }
                else
                {
                    Host = (string)HeaderFields["Host"];
                    Port = 80;
                }
                if (HttpRequestType.ToUpper().Equals("POST"))
                {
                    int index = Query.IndexOf("\r\n\r\n");
                    m_HttpPost = Query.Substring(index + 4);
                }
            }

            try
            {
                IPEndPoint DestinationEndPoint = new IPEndPoint(Dns.GetHostEntry(Host).AddressList[0], Port);
                DestinationSocket = new Socket(DestinationEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                if (HeaderFields.ContainsKey("Proxy-Connection") && HeaderFields["Proxy-Connection"].ToLower().Equals("keep-alive"))
                {
                    DestinationSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
                }
                DestinationSocket.BeginConnect(DestinationEndPoint, new AsyncCallback(this.OnConnected), DestinationSocket);
            }
            catch
            {
                SendBadRequest();
                return;
            }
        }
Пример #9
0
        protected override void ProcessQuery(string Query)
        {
            HeaderFields = ParseQuery(Query);
            if (HeaderFields == null || !HeaderFields.ContainsKey("Host"))
            {
                SendBadRequest();
                return;
            }
            int    Port;
            string Host;
            int    Ret;

            if (HttpRequestType.ToUpper().Equals("CONNECT"))
            { //HTTPS
                Ret = RequestedPath.IndexOf(":");
                if (Ret >= 0)
                {
                    Host = RequestedPath.Substring(0, Ret);
                    if (RequestedPath.Length > Ret + 1)
                    {
                        Port = int.Parse(RequestedPath.Substring(Ret + 1));
                    }
                    else
                    {
                        Port = 443;
                    }
                }
                else
                {
                    Host = RequestedPath;
                    Port = 443;
                }
            }
            else
            { //Normal HTTP
                Ret = ((string)HeaderFields["Host"]).IndexOf(":");
                if (Ret > 0)
                {
                    Host = ((string)HeaderFields["Host"]).Substring(0, Ret);
                    Port = int.Parse(((string)HeaderFields["Host"]).Substring(Ret + 1));
                }
                else
                {
                    Host = (string)HeaderFields["Host"];
                    Port = 80;
                }
                if (HttpRequestType.ToUpper().Equals("POST"))
                {
                    int index = Query.IndexOf("\r\n\r\n");
                    m_HttpPost = Query.Substring(index + 4);
                }
            }
            try
            {
                DestinationSocket = new ProxySocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                ((ProxySocket)DestinationSocket).ProxyEndPoint = new IPEndPoint(Config.SocksAddress, Config.SocksPort);
                ((ProxySocket)DestinationSocket).ProxyUser     = Config.Username;
                ((ProxySocket)DestinationSocket).ProxyPass     = Config.Password;
                ((ProxySocket)DestinationSocket).ProxyType     = Config.ProxyType;

                if (HeaderFields.ContainsKey("Proxy-Connection") && HeaderFields["Proxy-Connection"].ToLower().Equals("keep-alive"))
                {
                    ((ProxySocket)DestinationSocket).SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
                }
                ((ProxySocket)DestinationSocket).BeginConnect(Host, Port, new AsyncCallback(this.OnProxyConnected), DestinationSocket);
            }
            catch
            {
                SendBadRequest();
                return;
            }
        }
Пример #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Header" /> class.
 /// </summary>
 public Header() : base(CLASS_NAME)
 {
     mFields = new HeaderFields(this);
 }
Пример #11
0
        private void QueryHandle(string query)
        {
            HeaderFields = ParseQuery(query);
            if ((HeaderFields == null) || !HeaderFields.ContainsKey("Host"))
            {
                SendBadRequest();
            }
            else
            {
                int    num;
                string requestedPath;
                int    index;
                if (HttpRequestType.ToUpper().Equals("CONNECT"))
                {
                    index = RequestedPath.IndexOf(":");
                    if (index >= 0)
                    {
                        requestedPath = RequestedPath.Substring(0, index);
                        num           = RequestedPath.Length > (index + 1) ? int.Parse(RequestedPath.Substring(index + 1)) : 443;
                    }
                    else
                    {
                        requestedPath = RequestedPath;
                        num           = 80;
                    }
                }
                else
                {
                    index = HeaderFields["Host"].IndexOf(":");
                    if (index > 0)
                    {
                        requestedPath = HeaderFields["Host"].Substring(0, index);
                        num           = int.Parse(HeaderFields["Host"].Substring(index + 1));
                    }
                    else
                    {
                        requestedPath = HeaderFields["Host"];
                        num           = 80;
                    }
                    if (HttpRequestType.ToUpper().Equals("POST"))
                    {
                        int tempnum = query.IndexOf("\r\n\r\n");
                        _mHttpPost = query.Substring(tempnum + 4);
                    }
                }

                var localFile = String.Empty;
                if (MonitorLog.RegexUrl(RequestedUrl))
                {
                    localFile = UrlOperate.MatchFile(RequestedUrl);
                }

                _uinfo.PsnUrl = string.IsNullOrEmpty(_uinfo.PsnUrl) ? RequestedUrl : _uinfo.PsnUrl;
                if (!HttpRequestType.ToUpper().Equals("CONNECT") && localFile != string.Empty && File.Exists(localFile))
                {
                    _uinfo.ReplacePath = localFile;
                    _updataUrlLog(_uinfo);
                    SendLocalFile(localFile, HeaderFields.ContainsKey("Range") ? HeaderFields["Range"] : null, HeaderFields.ContainsKey("Proxy-Connection") ? HeaderFields["Proxy-Connection"] : null);
                }
                else
                {
                    try
                    {
                        bool      iscdn;
                        IPAddress hostIp   = CdnOperate.GetCdnAddress(requestedPath, out iscdn);
                        var       remoteEp = new IPEndPoint(hostIp, num);
                        DestinationSocket = new Socket(remoteEp.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                        if (HeaderFields.ContainsKey("Proxy-Connection") &&
                            HeaderFields["Proxy-Connection"].ToLower().Equals("keep-alive"))
                        {
                            DestinationSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
                        }
                        DestinationSocket.BeginConnect(remoteEp, OnConnected, DestinationSocket);

                        _uinfo.Host        = hostIp.ToString();
                        _uinfo.IsCdn       = iscdn;
                        _uinfo.ReplacePath = string.Empty;
                        _updataUrlLog(_uinfo);
                    }
                    catch
                    {
                        SendBadRequest();
                    }
                }
            }
        }
Пример #12
0
 public cMessageCacheItems Missing(cMessageCacheItems pItems) => new cMessageCacheItems(~mAttributes & pItems.Attributes, HeaderFields.Missing(pItems.Names));
Пример #13
0
 public bool ContainsNone(cMessageCacheItems pItems) => (~mAttributes & pItems.Attributes) == pItems.Attributes && HeaderFields.ContainsNone(pItems.Names);
Пример #14
0
        /// <summary>
        /// The MIME representation of the header.
        /// </summary>
        /// <param name="removeBlindCopies">if set to <c>true</c> remove blind copies (BCC).</param>
        /// <param name="forceBase64Encoding">if set to <c>true</c> forces inner elements to be base64 encoded</param>
        /// <returns></returns>
        public string ToHeaderString(bool removeBlindCopies, bool forceBase64Encoding = false)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();

            /*foreach (TraceInfo trace in this.Trace) sb.AppendLine("Received: " + trace.ToString());
             * if (!this.From.Email.Equals(string.Empty)) sb.AppendLine("From: " + this.From.Merged);
             * if (!this.Sender.Email.Equals(string.Empty)) sb.AppendLine("Sender: " + this.Sender.Merged);
             * if (this.To.Count > 0) sb.AppendLine("To: " + this.To.Merged);
             * if (this.Cc.Count > 0) sb.AppendLine("Cc: " + this.Cc.Merged);
             * if (this.Bcc.Count > 0) sb.AppendLine("Bcc: " + this.Bcc.Merged);
             * if (!this.ReplyTo.Email.Equals(string.Empty)) sb.AppendLine("Reply-to: " + this.ReplyTo.Merged);*/

            foreach (TraceInfo trace in Trace)
            {
                AddHeaderField("Received", trace.ToString());
            }
            if (!From.Email.Equals(string.Empty))
            {
                AddHeaderField("From", From.Merged);
            }
            if (!Sender.Email.Equals(string.Empty))
            {
                AddHeaderField("Sender", Sender.Merged);
            }
            if (To.Count > 0)
            {
                AddHeaderField("To", To.Merged);
            }
            if (Cc.Count > 0)
            {
                AddHeaderField("Cc", Cc.Merged);
            }
            if (Bcc.Count > 0 && !removeBlindCopies)
            {
                AddHeaderField("Bcc", Bcc.Merged);
            }
            if (!ReplyTo.Email.Equals(string.Empty))
            {
                AddHeaderField("Reply-To", ReplyTo.Merged);
            }

            if (Date.Equals(DateTime.MinValue))
            {
                Date = DateTime.Now;
            }

            if (string.IsNullOrEmpty(MessageId))
            {
                MessageId = "<AU" + Codec.GetUniqueString() + "@" + System.Net.Dns.GetHostName() + ">";
            }

            if (ContentType.MimeType.Length > 0)
            {
                string contentType = ContentType.ToString();
                contentType = contentType.Substring(contentType.IndexOf(":") + 1).TrimStart(' ');
                AddHeaderField("Content-Type", contentType);
            }

            if (ContentDisposition.Disposition.Length > 0)
            {
                string contentDisposition = ContentDisposition.ToString();
                contentDisposition = contentDisposition.Substring(contentDisposition.IndexOf(":") + 1).TrimStart(' ');
                AddHeaderField("Content-Disposition", contentDisposition);
            }

            if (forceBase64Encoding)
            {
                AddHeaderField("Content-Transfer-Encoding", "base64");
            }
            else if (ContentType.Type.Equals("text"))
            {
                AddHeaderField("Content-Transfer-Encoding", "quoted-printable");
            }

            System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
            Version v = asm.GetName().Version;

            AddHeaderField("X-Mailer", "ActiveUp.MailSystem " + v.Major + "." + v.Minor + "." + v.Build + " www.activeup.com");

            foreach (string key in HeaderFields.AllKeys)
            {
                for (int i = 0; i < HeaderFields.GetValues(key).Length; i++)
                {
                    sb.Append(HeaderFieldNames.GetValues(key)[i] + ": " + HeaderFields.GetValues(key)[i] + "\r\n");
                }
            }
            return(sb.ToString().TrimEnd('\r', '\n'));
        }
Пример #15
0
 ///<summary>Processes a specified query and connects to the requested HTTP web server.</summary>
 ///<param name="Query">A string containing the query to process.</param>
 ///<remarks>If there's an error while processing the HTTP request or when connecting to the remote server, the Proxy sends a "400 - Bad Request" error to the client.</remarks>
 private void ProcessQuery(string Query)
 {
     HeaderFields = ParseQuery(Query);
     if (HeaderFields == null || !HeaderFields.ContainsKey("Host"))
     {
         SendBadRequest();
         return;
     }
     #region Parse destination address and port
     int    Port;
     string Host;
     int    Ret;
     if (HttpRequestType.ToUpper().Equals("CONNECT"))               //HTTPS
     {
         isThisSSL            = true;
         this.isPayloadSecure = true;
         Ret = RequestedPath.IndexOf(":");
         if (Ret >= 0)
         {
             Host = RequestedPath.Substring(0, Ret);
             if (RequestedPath.Length > Ret + 1)
             {
                 Port             = int.Parse(RequestedPath.Substring(Ret + 1));
                 CurrentHTTPSport = Port;
             }
             else
             {
                 Port             = 443;
                 CurrentHTTPSport = 443;
             }
         }
         else
         {
             Host             = RequestedPath;
             Port             = 443;
             CurrentHTTPSport = 443;
         }
     }
     else
     {
         isThisSSL = false;
         Ret       = ((string)HeaderFields["Host"]).IndexOf(":");
         if (Ret > 0)
         {
             Host             = ((string)HeaderFields["Host"]).Substring(0, Ret);
             Port             = int.Parse(((string)HeaderFields["Host"]).Substring(Ret + 1));
             CurrentHTTPSport = Port;
         }
         else
         {
             Host             = (string)HeaderFields["Host"];
             Port             = 80;
             CurrentHTTPSport = 80;
         }
         if (HttpRequestType.ToUpper().Equals("GET") == false)
         {
             int index = Query.IndexOf("\r\n\r\n");
             m_HttpPost = Query.Substring(index + 4);
         }
     }
     #endregion
     #region Create destination socket
     try {
         IPEndPoint DestinationEndPoint = new IPEndPoint(Dns.Resolve(Host).AddressList[0], Port);
         if (this.isPayloadSecure)
         {
             SecurityOptions options = new SecurityOptions(
                 SecureProtocol.Ssl3 | SecureProtocol.Tls1,                              // use SSL3 or TLS1
                 null,                                                                   // not required for SSL client
                 ConnectionEnd.Client,                                                   // this is the client side
                 CredentialVerification.None,                                            // do not check the certificate -- this should not be used in a real-life application :-)
                 null,                                                                   // not used with automatic certificate verification
                 "www.bogus.com",                                                        // this is the common name of the Microsoft web server
                 SecurityFlags.Default,                                                  // use the default security flags
                 SslAlgorithms.SECURE_CIPHERS,                                           // only use secure ciphers
                 null);                                                                  // do not process certificate requests.
             // This line for intercept proxy
             DestinationSocket = new SecureSocket(DestinationEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp, options);
             // This line for pass-through proxy
             //DestinationSocket	= new SecureSocket(DestinationEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
         }
         else
         {
             DestinationSocket = new SecureSocket(DestinationEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
         }
         if (HeaderFields.ContainsKey("Proxy-Connection") && HeaderFields["Proxy-Connection"].ToLower().Equals("keep-alive"))
         {
             DestinationSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
         }
         DestinationSocket.BeginConnect(DestinationEndPoint, new AsyncCallback(this.OnConnected), DestinationSocket);
     } catch {
         SendBadRequest();
         return;
     }
     #endregion
 }
        /// <summary>
        /// Launch the RDF export wizard and save resulting RDF file to disk.
        /// </summary>
        public void ExportRDF()
        {
            // Generate candidate list of namespaces to map, for the export dialog to consume
            candidateNamespacesToMap = new HashSet <Uri>();
            foreach (Worksheet worksheet in Globals.ThisAddIn.Application.Worksheets)
            {
                int    lastUsedColumnIndex = worksheet.UsedRange.Columns.Count;
                string lastUsedColumnName  = Helper.GetExcelColumnName(lastUsedColumnIndex);
                Range  headerRange         = worksheet.get_Range(String.Format("A1:{0}1", lastUsedColumnName));
                candidateNamespacesToMap.UnionWith(Helper.getNamespaceUrisFromComments(headerRange));
            }

            ExportOptionsForm exportOptionsForm = new ExportOptionsForm();

            if (exportOptionsForm.ShowDialog() == DialogResult.OK)
            {
                // Set up save file UI
                SaveFileDialog saveRdfFileDialog = new SaveFileDialog();
                saveRdfFileDialog.Filter = "RDF/XML (*.rdf)|*.rdf|Turtle (*.ttl)|*.ttl|NTriples (*.nt)|*.nt";
                saveRdfFileDialog.Title  = "Save RDF file";
                if (saveRdfFileDialog.ShowDialog() == DialogResult.OK)
                {
                    // Initiate DotNetRdf Graph and shared IRI:s
                    IGraph   g       = new Graph();
                    IUriNode rdfType = g.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfType));

                    // Assign namespace mappings from export dialog
                    foreach (KeyValuePair <string, Uri> entry in exportPrefixMappings)
                    {
                        g.NamespaceMap.AddNamespace(entry.Key, entry.Value);
                    }

                    // Used to trim URI:s
                    Char[] trimUrisChars = new Char[] { '<', '>' };

                    // Iterate over all worksheets
                    foreach (Worksheet worksheet in Globals.ThisAddIn.Application.Worksheets)
                    {
                        // Which bits of the sheet are being used
                        Range usedRange      = worksheet.UsedRange;
                        int   lastUsedRow    = usedRange.Row + usedRange.Rows.Count - 1;
                        int   lastUsedColumn = usedRange.Column + usedRange.Columns.Count - 1;

                        // Identifier column metadata
                        int identifierColumn = 0;

                        // Class name is tentatively in the data namespace until the identifier column is found
                        Uri className = new Uri(exportNamespace.ToString() + worksheet.Name);

                        // Set up lookup table. Note that we use 1-indexing to simplify mapping to/from Excel
                        // ranges. The 0:th column will thus be empty and should not be adressed, as will the
                        // identifier column.
                        HeaderFields[] headerLookupTable = new HeaderFields[lastUsedColumn + 1];

                        // Parse the header row.
                        string lastUsedColumnName = Helper.GetExcelColumnName(lastUsedColumn);
                        Range  headerRange        = worksheet.get_Range(String.Format("A1:{0}1", lastUsedColumnName));
                        foreach (Range headerCell in headerRange.Cells)
                        {
                            int column = headerCell.Column;

                            // If there is an embedded note, proceed
                            if (headerCell.Comment != null)
                            {
                                string   noteText           = headerCell.Comment.Text(Type.Missing, Type.Missing, Type.Missing);
                                string[] noteTextComponents = noteText.Split('\n');

                                string iriComponent = noteTextComponents[0];
                                if (iriComponent.Equals("<IRI>") && noteTextComponents.Count() == 2)
                                {
                                    // This is the identifier column; update worksheet metadata accordingly
                                    identifierColumn = headerCell.Column;
                                    string classComponent        = noteTextComponents[1];
                                    string classComponentTrimmed = classComponent.Trim(trimUrisChars);
                                    className = new Uri(classComponentTrimmed);
                                }
                                else if (noteTextComponents.Count() == 3)
                                {
                                    HeaderFields hf = new HeaderFields();
                                    hf.propertyIri = g.CreateUriNode(UriFactory.Create(iriComponent.Trim(trimUrisChars)));

                                    string propertyTypeComponent = noteTextComponents[1];
                                    hf.propertyType = new Uri(propertyTypeComponent.Trim(trimUrisChars));

                                    string propertyRangeComponent = noteTextComponents[2];
                                    hf.propertyRange = new Uri(propertyRangeComponent.Trim(trimUrisChars));

                                    headerLookupTable[column] = hf;
                                }
                                else if (noteTextComponents.Count() == 6)
                                {
                                    HeaderFields hf = new HeaderFields();
                                    hf.propertyIri = g.CreateUriNode(UriFactory.Create(iriComponent.Trim(trimUrisChars)));

                                    string propertyTypeComponent = noteTextComponents[1];
                                    hf.propertyType = new Uri(propertyTypeComponent.Trim(trimUrisChars));

                                    string propertyRangeComponent = noteTextComponents[2];
                                    hf.propertyRange = new Uri(propertyRangeComponent.Trim(trimUrisChars));

                                    string nestedIriComponent = noteTextComponents[3];
                                    hf.nestedIri = g.CreateUriNode(UriFactory.Create(nestedIriComponent.Trim(trimUrisChars)));

                                    string nestedTypeComponent = noteTextComponents[4];
                                    hf.nestedType = new Uri(nestedTypeComponent.Trim(trimUrisChars));

                                    string nestedRangeComponent = noteTextComponents[5].Trim(trimUrisChars);
                                    if (nestedRangeComponent.Length > 0)
                                    {
                                        hf.nestedRange = new Uri(nestedRangeComponent);
                                    }

                                    headerLookupTable[column] = hf;
                                }
                            }
                        }

                        // Now, assuming an identifier column has been found, we can finally start parsing the rows
                        if (identifierColumn != 0)
                        {
                            // All entities will have the same class
                            IUriNode worksheetClass = g.CreateUriNode(className);

                            // For every row in the spreadsheet..
                            for (int rowIndex = 2; rowIndex <= lastUsedRow; rowIndex++)
                            {
                                string rowRangeIdentifier = String.Format("{0}{1}:{2}{3}", Helper.GetExcelColumnName(1), rowIndex, Helper.GetExcelColumnName(lastUsedColumn), rowIndex);
                                Range  row = worksheet.get_Range(rowRangeIdentifier);

                                // Set subject node ID.
                                string identifierCellIdentifier = String.Format("{0}{1}", Helper.GetExcelColumnName(identifierColumn), rowIndex);
                                Range  identifierCell           = worksheet.get_Range(identifierCellIdentifier);

                                // Used to store the references to any intermediate (nested) blank nodes for the row
                                Dictionary <IUriNode, IBlankNode> intermediateNodes = new Dictionary <IUriNode, IBlankNode>();

                                // Only parse rows that have an identifier
                                if (identifierCell.Text != "")
                                {
                                    Uri      subjectUri  = new Uri(exportNamespace.ToString() + identifierCell.Text);
                                    IUriNode subjectNode = g.CreateUriNode(subjectUri);
                                    g.Assert(new Triple(subjectNode, rdfType, worksheetClass));

                                    // Iterate over remaining columns, i.e., property instances, skipping the identifier column if it reappears
                                    foreach (Range dataCell in row.Cells)
                                    {
                                        if (dataCell.Column == identifierColumn)
                                        {
                                            continue;
                                        }

                                        // Get header fields
                                        HeaderFields hf = headerLookupTable[dataCell.Column];

                                        // Check that there actually are header fields for the cell under consideration; otherwise, ignore cell
                                        // This is not a simple null check since HeaderFields is a struct, e.g., value type, which cannot be null
                                        if (hf.Equals(default(HeaderFields)))
                                        {
                                            continue;
                                        }

                                        if (hf.nestedIri != null)
                                        {
                                            // This is a nested anonymous individual

                                            // Assert the intermediate (nested) individual
                                            IUriNode   predicateNode = hf.propertyIri;
                                            IBlankNode intermediateBlank;
                                            if (intermediateNodes.ContainsKey(predicateNode))
                                            {
                                                intermediateBlank = intermediateNodes[predicateNode];
                                            }
                                            else
                                            {
                                                intermediateBlank = g.CreateBlankNode();
                                                intermediateNodes.Add(predicateNode, intermediateBlank);
                                            }
                                            IUriNode intermediateType = g.CreateUriNode(hf.propertyRange);
                                            g.Assert(new Triple(subjectNode, predicateNode, intermediateBlank));
                                            g.Assert(new Triple(intermediateBlank, rdfType, intermediateType));

                                            IUriNode nestedPredicateNode = hf.nestedIri;

                                            // Get out and parse object.
                                            // "Raw" cell value, will need treatment (TODO!)
                                            INode  objectNode;
                                            string cellValue = dataCell.Text;

                                            // Check so cell isn't empty
                                            if (!cellValue.Equals(""))
                                            {
                                                switch (hf.nestedType.ToString())
                                                {
                                                case OntologyHelper.OwlDatatypeProperty:
                                                    objectNode = g.CreateLiteralNode(cellValue, hf.nestedRange);
                                                    break;

                                                case OntologyHelper.OwlObjectProperty:
                                                    // If there is a valid URI in the cell, use that as-is, otherwise generate one frame the export namespace
                                                    if (Uri.TryCreate(cellValue, UriKind.Absolute, out Uri tempObjectPropertyValue) == true)
                                                    {
                                                        objectNode = g.CreateUriNode(tempObjectPropertyValue);
                                                    }
                                                    else
                                                    {
                                                        objectNode = g.CreateUriNode(new Uri(exportNamespace.ToString() + cellValue));
                                                    }
                                                    break;

                                                case OntologyHelper.OwlAnnotationProperty:
                                                    // For annotation properties we use literal object nodes if property range is in XSD namespace
                                                    // and uri nodes otherwise.
                                                    if (hf.nestedRange.ToString().Contains(XmlSpecsHelper.NamespaceXmlSchema))
                                                    {
                                                        objectNode = g.CreateLiteralNode(cellValue, hf.nestedRange);
                                                    }
                                                    else
                                                    {
                                                        // If there is a valid URI in the cell, use that as-is, otherwise generate one frame the export namespace
                                                        if (Uri.TryCreate(cellValue, UriKind.Absolute, out Uri tempAnnotationPropertyValue) == true)
                                                        {
                                                            objectNode = g.CreateUriNode(tempAnnotationPropertyValue);
                                                        }
                                                        else
                                                        {
                                                            objectNode = g.CreateUriNode(new Uri(exportNamespace.ToString() + cellValue));
                                                        }
                                                    }
                                                    break;

                                                default:
                                                    continue;
                                                }

                                                g.Assert(new Triple(intermediateBlank, nestedPredicateNode, objectNode));
                                            }
                                        }
                                        else
                                        {
                                            IUriNode predicateNode = hf.propertyIri;

                                            // Get out and parse object.
                                            // "Raw" cell value, will need treatment (TODO!)
                                            INode  objectNode;
                                            string cellValue = dataCell.Text;

                                            // Check so cell isn't empty
                                            if (!cellValue.Equals(""))
                                            {
                                                switch (hf.propertyType.ToString())
                                                {
                                                case OntologyHelper.OwlDatatypeProperty:
                                                    objectNode = g.CreateLiteralNode(cellValue, hf.propertyRange);
                                                    break;

                                                case OntologyHelper.OwlObjectProperty:
                                                    // If there is a valid URI in the cell, use that as-is, otherwise generate one frame the export namespace
                                                    if (Uri.TryCreate(cellValue, UriKind.Absolute, out Uri tempObjectPropertyValue) == true)
                                                    {
                                                        objectNode = g.CreateUriNode(tempObjectPropertyValue);
                                                    }
                                                    else
                                                    {
                                                        objectNode = g.CreateUriNode(new Uri(exportNamespace.ToString() + cellValue));
                                                    }
                                                    break;

                                                case OntologyHelper.OwlAnnotationProperty:
                                                    // For annotation properties we use literal object nodes if property range is in XSD namespace
                                                    // and uri nodes otherwise.
                                                    if (hf.propertyRange.ToString().Contains(XmlSpecsHelper.NamespaceXmlSchema))
                                                    {
                                                        objectNode = g.CreateLiteralNode(cellValue, hf.propertyRange);
                                                    }
                                                    else
                                                    {
                                                        // If there is a valid URI in the cell, use that as-is, otherwise generate one frame the export namespace
                                                        if (Uri.TryCreate(cellValue, UriKind.Absolute, out Uri tempAnnotationPropertyValue) == true)
                                                        {
                                                            objectNode = g.CreateUriNode(tempAnnotationPropertyValue);
                                                        }
                                                        else
                                                        {
                                                            objectNode = g.CreateUriNode(new Uri(exportNamespace.ToString() + cellValue));
                                                        }
                                                    }
                                                    break;

                                                default:
                                                    continue;
                                                }

                                                g.Assert(new Triple(subjectNode, predicateNode, objectNode));
                                            }
                                        }
                                    }
                                }
                            }
                            String     saveFileExtension = Path.GetExtension(saveRdfFileDialog.FileName);
                            IRdfWriter writer            = MimeTypesHelper.GetWriterByFileExtension(saveFileExtension);
                            writer.Save(g, saveRdfFileDialog.FileName);
                        }
                    }
                }
            }
        }