/// <summary> Helper method retrieves HTML web content </summary>
        /// <param name="BasicInfo"> Basic information from the database for this endpoint, including the URL segments </param>
        /// <param name="Tracer"></param>
        /// <param name="ErrorType"> Any error enocuntered during the process </param>
        /// <returns> Built HTML content object, or NULL </returns>
        private static HTML_Based_Content read_source_file(WebContent_Basic_Info BasicInfo, Custom_Tracer Tracer, out WebContentEndpointErrorEnum ErrorType)
        {
            // Set a default error message first
            ErrorType = WebContentEndpointErrorEnum.NONE;

            // Build the directory to look for the static content
            StringBuilder possibleInfoModeBuilder = new StringBuilder(BasicInfo.Level1);
            if (!String.IsNullOrEmpty(BasicInfo.Level2))
            {
                possibleInfoModeBuilder.Append(Path.DirectorySeparatorChar + BasicInfo.Level2);
                if (!String.IsNullOrEmpty(BasicInfo.Level3))
                {
                    possibleInfoModeBuilder.Append(Path.DirectorySeparatorChar + BasicInfo.Level3);
                    if (!String.IsNullOrEmpty(BasicInfo.Level4))
                    {
                        possibleInfoModeBuilder.Append(Path.DirectorySeparatorChar + BasicInfo.Level4);
                        if (!String.IsNullOrEmpty(BasicInfo.Level5))
                        {
                            possibleInfoModeBuilder.Append(Path.DirectorySeparatorChar + BasicInfo.Level5);
                            if (!String.IsNullOrEmpty(BasicInfo.Level6))
                            {
                                possibleInfoModeBuilder.Append(Path.DirectorySeparatorChar + BasicInfo.Level6);
                                if (!String.IsNullOrEmpty(BasicInfo.Level7))
                                {
                                    possibleInfoModeBuilder.Append(Path.DirectorySeparatorChar + BasicInfo.Level7);
                                    if (!String.IsNullOrEmpty(BasicInfo.Level8))
                                    {
                                        possibleInfoModeBuilder.Append(Path.DirectorySeparatorChar + BasicInfo.Level8);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            string possible_info_mode = possibleInfoModeBuilder.ToString().Replace("'", "").Replace("\"", "");
            string filename = possible_info_mode;
            string base_source = Engine_ApplicationCache_Gateway.Settings.Servers.Base_Directory + "design\\webcontent";
            string source = base_source;
            string found_source = null;

            if ((possible_info_mode.IndexOf("\\") > 0) || (possible_info_mode.IndexOf("/") > 0))
            {
                source = source + "\\" + possible_info_mode.Replace("/", "\\");
                string[] split = source.Split("\\".ToCharArray());
                filename = split[split.Length - 1];
                source = source.Substring(0, source.Length - filename.Length);
            }

            // If the designated source exists, look for the files
            if (Directory.Exists(source))
            {
                // This may point to the default html in the parent directory
                if ((Directory.Exists(source + "\\" + filename)) && (File.Exists(source + "\\" + filename + "\\default.html")))
                {
                    found_source = Path.Combine(source, filename, "default.html");
                    Tracer.Add_Trace("WebContentServices.get_html_content", "Found source file: " + found_source);
                }

                // If this was found, build it and return it
                if (!String.IsNullOrEmpty(found_source))
                {
                    HTML_Based_Content simpleWebContent = HTML_Based_Content_Reader.Read_HTML_File(found_source, true, Tracer);

                    if ((simpleWebContent == null) || (simpleWebContent.Content.Length == 0))
                    {
                        ErrorType = WebContentEndpointErrorEnum.Error_Reading_File;
                        Tracer.Add_Trace("WebContentServices.get_html_content", "Error reading source file");
                        return null;
                    }

                    // Copy over the primary key and URL segments for this web content
                    simpleWebContent.WebContentID = BasicInfo.WebContentID;
                    simpleWebContent.Level1 = BasicInfo.Level1;
                    simpleWebContent.Level2 = BasicInfo.Level2;
                    simpleWebContent.Level3 = BasicInfo.Level3;
                    simpleWebContent.Level4 = BasicInfo.Level4;
                    simpleWebContent.Level5 = BasicInfo.Level5;
                    simpleWebContent.Level6 = BasicInfo.Level6;
                    simpleWebContent.Level7 = BasicInfo.Level7;
                    simpleWebContent.Level8 = BasicInfo.Level8;
                    if ((BasicInfo.Locked.HasValue) && (BasicInfo.Locked.Value)) simpleWebContent.Locked = true;

                    // Now, check for any "server-side include" directorives in the source text
                    int include_index = simpleWebContent.Content.IndexOf("<%INCLUDE");
                    while ((include_index > 0) && (simpleWebContent.Content.IndexOf("%>", include_index, StringComparison.Ordinal) > 0))
                    {
                        int include_finish_index = simpleWebContent.Content.IndexOf("%>", include_index, StringComparison.Ordinal) + 2;
                        string include_statement = simpleWebContent.Content.Substring(include_index, include_finish_index - include_index);
                        string include_statement_upper = include_statement.ToUpper();
                        int file_index = include_statement_upper.IndexOf("FILE");
                        string filename_to_include = String.Empty;
                        if (file_index > 0)
                        {
                            // Pull out the possible file name
                            string possible_file_name = include_statement.Substring(file_index + 4);
                            int file_start = -1;
                            int file_end = -1;
                            int char_index = 0;

                            // Find the start of the file information
                            while ((file_start < 0) && (char_index < possible_file_name.Length))
                            {
                                if ((possible_file_name[char_index] != '"') && (possible_file_name[char_index] != '=') && (possible_file_name[char_index] != ' '))
                                {
                                    file_start = char_index;
                                }
                                else
                                {
                                    char_index++;
                                }
                            }

                            // Find the end of the file information
                            if (file_start >= 0)
                            {
                                char_index++;
                                while ((file_end < 0) && (char_index < possible_file_name.Length))
                                {
                                    if ((possible_file_name[char_index] == '"') || (possible_file_name[char_index] == ' ') || (possible_file_name[char_index] == '%'))
                                    {
                                        file_end = char_index;
                                    }
                                    else
                                    {
                                        char_index++;
                                    }
                                }
                            }

                            // Get the filename
                            if ((file_start > 0) && (file_end > 0))
                            {
                                filename_to_include = possible_file_name.Substring(file_start, file_end - file_start);
                            }
                        }

                        // Remove the include and either place in the text from the indicated file,
                        // or just remove
                        if ((filename_to_include.Length > 0) && (File.Exists(Engine_ApplicationCache_Gateway.Settings.Servers.Base_Directory + "design\\webcontent\\" + filename_to_include)))
                        {
                            // Define the value for the include text
                            string include_text;

                            // Look in the cache for this
                            object returnValue = HttpContext.Current.Cache.Get("INCLUDE_" + filename_to_include);
                            if (returnValue != null)
                            {
                                include_text = returnValue.ToString();
                            }
                            else
                            {
                                try
                                {
                                    // Pull from the file
                                    StreamReader reader = new StreamReader(Engine_ApplicationCache_Gateway.Settings.Servers.Base_Directory + "design\\webcontent\\" + filename_to_include);
                                    include_text = reader.ReadToEnd();
                                    reader.Close();

                                    // Store on the cache for two minutes, if no indication not to
                                    if (include_statement_upper.IndexOf("NOCACHE") < 0)
                                        HttpContext.Current.Cache.Insert("INCLUDE_" + filename_to_include, include_text, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(2));
                                }
                                catch (Exception)
                                {
                                    include_text = "Unable to read the soruce file ( " + filename_to_include + " )";
                                }
                            }

                            // Replace the text with the include file
                            simpleWebContent.Content = simpleWebContent.Content.Replace(include_statement, include_text);
                            include_index = simpleWebContent.Content.IndexOf("<%INCLUDE", include_index + include_text.Length - 1, StringComparison.Ordinal);
                        }
                        else
                        {
                            // No suitable name was found, or it doesn't exist so just remove the INCLUDE completely
                            simpleWebContent.Content = simpleWebContent.Content.Replace(include_statement, "");
                            include_index = simpleWebContent.Content.IndexOf("<%INCLUDE", include_index, StringComparison.Ordinal);
                        }
                    }

                    // Now, return the web content object, with the text
                    return simpleWebContent;
                }
            }

            // Was never found
            Tracer.Add_Trace("WebContentServices.get_html_content", "No source file found");
            ErrorType = WebContentEndpointErrorEnum.No_File_Found;
            return null;
        }
        private WebContent_Basic_Info datarow_to_basic_info(DataRow ChangeRow)
        {
            // Start to buid the object to report this work
            WebContent_Basic_Info recentChange = new WebContent_Basic_Info
            {
                WebContentID = Int32.Parse(ChangeRow[0].ToString()),
                Level1 = ChangeRow[1].ToString()
            };

            // Grab the values out and assign them
            if ((ChangeRow[2] != DBNull.Value) && (!String.IsNullOrEmpty(ChangeRow[2].ToString())))
            {
                recentChange.Level2 = ChangeRow[2].ToString();
                if ((ChangeRow[3] != DBNull.Value) && (!String.IsNullOrEmpty(ChangeRow[3].ToString())))
                {
                    recentChange.Level3 = ChangeRow[3].ToString();
                    if ((ChangeRow[4] != DBNull.Value) && (!String.IsNullOrEmpty(ChangeRow[4].ToString())))
                    {
                        recentChange.Level4 = ChangeRow[4].ToString();
                        if ((ChangeRow[5] != DBNull.Value) && (!String.IsNullOrEmpty(ChangeRow[5].ToString())))
                        {
                            recentChange.Level5 = ChangeRow[5].ToString();
                            if ((ChangeRow[6] != DBNull.Value) && (!String.IsNullOrEmpty(ChangeRow[6].ToString())))
                            {
                                recentChange.Level6 = ChangeRow[6].ToString();
                                if ((ChangeRow[7] != DBNull.Value) && (!String.IsNullOrEmpty(ChangeRow[7].ToString())))
                                {
                                    recentChange.Level7 = ChangeRow[7].ToString();
                                    if ((ChangeRow[8] != DBNull.Value) && (!String.IsNullOrEmpty(ChangeRow[8].ToString())))
                                    {
                                        recentChange.Level8 = ChangeRow[8].ToString();
                                    }
                                }
                            }
                        }
                    }
                }
            }

            recentChange.Title = ChangeRow[9].ToString();
            if (Boolean.Parse(ChangeRow[11].ToString()))
                recentChange.Deleted = true;
            if ((ChangeRow[12] != DBNull.Value) && (!String.IsNullOrEmpty(ChangeRow[12].ToString())))
                recentChange.Redirect = ChangeRow[12].ToString();
            return recentChange;
        }
        /// <summary> Gets the basic information about a web content page, by the URL segments </summary>
        /// <param name="Level1"> Level 1 of the URL for this web content page </param>
        /// <param name="Level2"> Level 2 of the URL for this web content page </param>
        /// <param name="Level3"> Level 3 of the URL for this web content page </param>
        /// <param name="Level4"> Level 4 of the URL for this web content page </param>
        /// <param name="Level5"> Level 5 of the URL for this web content page </param>
        /// <param name="Level6"> Level 6 of the URL for this web content page </param>
        /// <param name="Level7"> Level 7 of the URL for this web content page </param>
        /// <param name="Level8"> Level 8 of the URL for this web content page </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <returns> Built web content basic info object, or NULL if not found at all </returns>
        /// <remarks> This calls the 'SobekCM_WebContent_Get_Page' stored procedure </remarks> 
        public static WebContent_Basic_Info WebContent_Get_Page(string Level1, string Level2, string Level3, string Level4, string Level5, string Level6, string Level7, string Level8, Custom_Tracer Tracer)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("Engine_Database.WebContent_Get_Page", "");
            }

            try
            {
                EalDbParameter[] parameters = new EalDbParameter[8];
                parameters[0] = new EalDbParameter("@level1", Level1);
                parameters[1] = new EalDbParameter("@level2", Level2);
                parameters[2] = new EalDbParameter("@level3", Level3);
                parameters[3] = new EalDbParameter("@level4", Level4);
                parameters[4] = new EalDbParameter("@level5", Level5);
                parameters[5] = new EalDbParameter("@level6", Level6);
                parameters[6] = new EalDbParameter("@level7", Level7);
                parameters[7] = new EalDbParameter("@level8", Level8);

                // Define a temporary dataset
                DataSet value = EalDbAccess.ExecuteDataset(DatabaseType, Connection_String, CommandType.StoredProcedure, "SobekCM_WebContent_Get_Page", parameters);

                // If nothing was returned, return NULL
                if ((value.Tables.Count == 0) || (value.Tables[0].Rows.Count == 0))
                    return null;

                // Get the values from the returned object
                DataRow pageRow = value.Tables[0].Rows[0];
                int webid = Int32.Parse(pageRow["WebContentID"].ToString());
                string title = pageRow["Title"].ToString();
                string summary = pageRow["Summary"].ToString();
                bool deleted = bool.Parse(pageRow["Deleted"].ToString());
                string redirect = pageRow["Redirect"].ToString();

                // Build and return the basic info object
                WebContent_Basic_Info returnValue = new WebContent_Basic_Info(webid, title, summary, deleted, redirect);
                if (bool.Parse(pageRow["Locked"].ToString()))
                    returnValue.Locked = true;

                // Also, add the levels
                if ((pageRow["Level1"] != DBNull.Value) && (!String.IsNullOrEmpty(pageRow["Level1"].ToString())))
                {
                    returnValue.Level1 = pageRow["Level1"].ToString();
                    if ((pageRow["Level2"] != DBNull.Value) && (!String.IsNullOrEmpty(pageRow["Level2"].ToString())))
                    {
                        returnValue.Level2 = pageRow["Level2"].ToString();
                        if ((pageRow["Level3"] != DBNull.Value) && (!String.IsNullOrEmpty(pageRow["Level3"].ToString())))
                        {
                            returnValue.Level3 = pageRow["Level3"].ToString();
                            if ((pageRow["Level4"] != DBNull.Value) && (!String.IsNullOrEmpty(pageRow["Level4"].ToString())))
                            {
                                returnValue.Level4 = pageRow["Level4"].ToString();
                                if ((pageRow["Level5"] != DBNull.Value) && (!String.IsNullOrEmpty(pageRow["Level5"].ToString())))
                                {
                                    returnValue.Level5 = pageRow["Level5"].ToString();
                                    if ((pageRow["Level6"] != DBNull.Value) && (!String.IsNullOrEmpty(pageRow["Level6"].ToString())))
                                    {
                                        returnValue.Level6 = pageRow["Level6"].ToString();
                                        if ((pageRow["Level7"] != DBNull.Value) && (!String.IsNullOrEmpty(pageRow["Level7"].ToString())))
                                        {
                                            returnValue.Level7 = pageRow["Level7"].ToString();
                                            if ((pageRow["Level8"] != DBNull.Value) && (!String.IsNullOrEmpty(pageRow["Level8"].ToString())))
                                                returnValue.Level8 = pageRow["Level8"].ToString();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                return returnValue;

            }
            catch (Exception ee)
            {
                Last_Exception = ee;
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Engine_Database.WebContent_Get_Page", "Exception caught during database work", Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Engine_Database.WebContent_Get_Page", ee.Message, Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Engine_Database.WebContent_Get_Page", ee.StackTrace, Custom_Trace_Type_Enum.Error);
                }
                return null;
            }
        }