/// <summary> Constructor for a new instance of the Track_Item_MySobekViewer class </summary>
        /// <param name="User"> Authenticated user information </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        public Track_Item_MySobekViewer(User_Object User, SobekCM_Navigation_Object Current_Mode, Custom_Tracer Tracer)
            : base(User)
        {
            Tracer.Add_Trace("Track_Item_MySobekViewer.Constructor", String.Empty);

            currentMode = Current_Mode;

            //If there is no user, go back
            if (user == null)
            {
                currentMode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                HttpContext.Current.Response.Redirect(currentMode.Redirect_URL());
            }

            //Initialize variables
            tracking_users = new DataTable();
            user_list = new Dictionary<string, User_Object>();
            scanners_list = new List<string>();

            //Determine the page
            page = 1;

            if ((HttpContext.Current.Session["Selected_Tab"] != null) && !(String.IsNullOrEmpty(HttpContext.Current.Session["Selected_Tab"].ToString())) && HttpContext.Current.Session["Selected_Tab"] == "2")
                page = 2;

            string sub_page = HttpContext.Current.Request.Form["tracking_new_page"] ?? "";
            if (sub_page == "2")
            {
                page = 2;
                HttpContext.Current.Session["Selected_Tab"] = "2";
            }
            else if (sub_page == "1")
            {
                page = 1;
                HttpContext.Current.Session["Selected_Tab"] = "1";
            }

            //Get the list of users who are possible Scanning/Processing technicians from the DB
            tracking_users = Database.SobekCM_Database.Tracking_Get_Users_Scanning_Processing();

            foreach (DataRow row in tracking_users.Rows)
            {
                User_Object temp_user = new User_Object();
                temp_user.UserName = row["UserName"].ToString();
                temp_user.Given_Name = row["FirstName"].ToString();
                temp_user.Family_Name = row["LastName"].ToString();
                temp_user.Email = row["EmailAddress"].ToString();
                user_list.Add(temp_user.UserName, temp_user);
            }

            if (!user_list.ContainsKey(User.UserName))
                user_list.Add(User.UserName, User);

            //Get the list of scanning equipment
            DataTable scanners = new DataTable();
            scanners = Database.SobekCM_Database.Tracking_Get_Scanners_List();
            foreach (DataRow row in scanners.Rows)
            {
                scanners_list.Add(row["ScanningEquipment"].ToString());
            }

            //See if there were any hidden requests
            hidden_request = HttpContext.Current.Request.Form["Track_Item_behaviors_request"] ?? String.Empty;
            hidden_value = HttpContext.Current.Request.Form["Track_Item_hidden_value"] ?? String.Empty;

            //Get the equipment value
            //if (HttpContext.Current.Session["Equipment"] != null && !String.IsNullOrEmpty(HttpContext.Current.Session["Equipment"].ToString()))
            //    equipment = HttpContext.Current.Session["Equipment"].ToString();
            if (User.Get_Setting("Track_Item_MySobekViewer:Equipment") != null && !String.IsNullOrEmpty(User.Get_Setting("Track_Item_MySobekViewer:Equipment").ToString()))
                equipment = User.Get_Setting("Track_Item_MySobekViewer:Equipment").ToString();

            else
            {
                equipment = scanners_list[0];
                User.Add_Setting("Track_Item_MySobekViewer:Equipment", equipment);
                //  HttpContext.Current.Session["Equipment"] = equipment;
            }

            //Check the hidden value to see if equipment was previously changed
            if (!String.IsNullOrEmpty(HttpContext.Current.Request.Form["hidden_equipment"]))
            {
                equipment = HttpContext.Current.Request.Form["hidden_equipment"];
                //   HttpContext.Current.Session["equipment"] = equipment;
                User.Add_Setting("Track_Item_MySobekViewer:Equipment", equipment);
            }

            //Also get the currently selected user
            if (HttpContext.Current.Session["Selected_User"] != null)
                current_selected_user = (User_Object)HttpContext.Current.Session["Selected_User"];

            else
            {
                current_selected_user = User;
                HttpContext.Current.Session["Selected_User"] = current_selected_user;
            }

            //Check if the selected user has been changed
            if (!String.IsNullOrEmpty(HttpContext.Current.Request.Form["hidden_selected_username"]))
            {
                current_selected_user = new User_Object();
                string temp = HttpContext.Current.Request.Form["hidden_selected_username"];
                current_selected_user = user_list[temp];

                HttpContext.Current.Session["Selected_User"] = current_selected_user;
            }

            //Get the table of all previous entries created by this user, for display in the third edit tab
            //        previous_workflows_this_user = Database.SobekCM_Database.Tracking_Get_All_Entries_By_User(current_selected_user.UserName);

            //Fetch the dictionaries of current work from the session
            current_workflows = (HttpContext.Current.Session["Tracking_Current_Workflows"]) as Dictionary<string, Tracking_Workflow>;
            current_workflows_no_durations = (HttpContext.Current.Session["Tracking_Current_Workflows_No_Duration"]) as Dictionary<string, Tracking_Workflow>;

            //else create new ones
            if (current_workflows == null && page == 1)
            {
                current_workflows = new Dictionary<string, Tracking_Workflow>();
            }
            else if (current_workflows_no_durations == null && page == 2)
            {
                current_workflows_no_durations = new Dictionary<string, Tracking_Workflow>();
            }

            //If there is a valid item currently selected
            if (!String.IsNullOrEmpty(BibID) && !String.IsNullOrEmpty(VID))
            {
                if (page == 1)
                {
                    //Get the the form field values from the first tab
                    start_Time = Convert.ToDateTime(HttpContext.Current.Request.Form["txtStartTime"]).ToString("hh:mm tt");
                    end_Time = Convert.ToDateTime(HttpContext.Current.Request.Form["txtEndTime"]).ToString("hh:mm tt");
                    this_workflow_date = Convert.ToDateTime(HttpContext.Current.Request.Form["txtStartDate"]);
                }
                else if (page == 2)
                {
                    //Get the form values from the second tab
                    this_workflow_date = Convert.ToDateTime(HttpContext.Current.Request.Form["txtStartDate2"]);
                }
            }

            switch (hidden_request.ToLower())
            {
                case "decode_barcode":
                    barcodeString = hidden_value;
                    //Decode the scanned barcode
                    if (!String.IsNullOrEmpty(barcodeString))
                    {
                        //Find a match for a number within the string, which corresponds to the event
                        Match val = Regex.Match(barcodeString, @"\d");
                        if (val.Success)
                        {
                            int len = barcodeString.IndexOf(val.Value);
                            Int32.TryParse(val.Value, out stage);

                            //Extract the item ID & checksum from the barcode string
                            encodedItemID = barcodeString.Substring(0, len);
                            checksum = barcodeString.Substring(len + 1, (barcodeString.Length - len - 1));

                            //Verify that the checksum is valid
                            bool isValidChecksum = Is_Valid_Checksum(encodedItemID, val.Value, checksum);
                            if (!isValidChecksum)
                                error_message = "Invalid Barcode entered!";

                            //Save the item information for this itemID
                            bool IsValidItem = Get_Item_Info_from_Barcode(encodedItemID);
                            if (!IsValidItem)
                                error_message = "Barcode error - invalid ItemID referenced";
                            else
                            {
                                Get_Bib_VID_from_ItemID(itemID);
                            }

                        }
                        else
                        {
                            error_message = "Invalid barcode scanned!";
                        }
                    }
                    break;

                case "read_manual_entry":
                    //Get the related hidden values for the selected manual entry fields
                    string hidden_bibID = HttpContext.Current.Request.Form["hidden_BibID"] ?? String.Empty;
                    string hidden_VID = HttpContext.Current.Request.Form["hidden_VID"] ?? String.Empty;
                    string hidden_event_num = HttpContext.Current.Request.Form["hidden_event_num"] ?? String.Empty;
                    if (String.IsNullOrEmpty(hidden_bibID) || String.IsNullOrEmpty(hidden_VID) || String.IsNullOrEmpty(hidden_event_num))
                    {
                        error_message = "You must enter a valid BibID and VID!";
                    }
                    else
                    {
                        Int32.TryParse(hidden_event_num, out stage);
                        BibID = hidden_bibID;
                        VID = hidden_VID;
                        try
                        {
                            itemID = Resource_Object.Database.SobekCM_Database.Get_ItemID(BibID, VID);
                            Get_Bib_VID_from_ItemID(itemID);
                        }
                        catch (Exception ee)
                        {
                            error_message = "Invalid BibID or VID!";
                        }

                    }
                    break;

                case "save":
                    int thisWorkflowId = Convert.ToInt32(HttpContext.Current.Request.Form["Track_Item_hidden_value"]);
                    int hidden_itemID = Convert.ToInt32(HttpContext.Current.Request.Form["hidden_itemID"]);
                    current_workflow_id = thisWorkflowId;
                    itemID = hidden_itemID;
                    Get_Bib_VID_from_ItemID(hidden_itemID);
                    Add_or_Update_Workflow(thisWorkflowId, hidden_itemID);

                    break;

                case "delete":
                    int WorkflowId = Convert.ToInt32(HttpContext.Current.Request.Form["Track_Item_hidden_value"]);
                    current_workflow_id = WorkflowId;
                    Database.SobekCM_Database.Tracking_Delete_Workflow(WorkflowId);
                    if (page == 1 && current_workflows.ContainsKey(current_workflow_id.ToString()))
                        current_workflows.Remove(current_workflow_id.ToString());
                    else if (page == 2 && current_workflows_no_durations.ContainsKey(current_workflow_id.ToString()))
                        current_workflows_no_durations.Remove(current_workflow_id.ToString());
                    break;

                default:
                    break;
            }

            //Get the table of any previously opened workflows for this item
            if (!String.IsNullOrEmpty(itemID.ToString()) && itemID != 0 && page == 1)
            {
                DataView temp_open_workflows_all_users = new DataView(Database.SobekCM_Database.Tracking_Get_Open_Workflows(itemID, stage));

                //Filter the open workflows associated with the currently selected user
                open_workflows_from_DB = temp_open_workflows_all_users.ToTable().Clone();

                foreach (DataRowView rowView in temp_open_workflows_all_users)
                {
                    DataRow newRow = open_workflows_from_DB.NewRow();
                    newRow.ItemArray = rowView.Row.ItemArray;
                    string username_column = rowView["WorkPerformedBy"].ToString();
                    string start_event_column = rowView["Start_Event_Number"].ToString();
                    string current_start = (stage == 1 || stage == 2) ? "1" : "3";
                    if (username_column == current_selected_user.UserName && !(String.IsNullOrEmpty(start_event_column)) && (start_event_column == current_start))
                        open_workflows_from_DB.Rows.Add(newRow);
                }
                HttpContext.Current.Session["Open_Workflows"] = open_workflows_from_DB;

            }
            else if (!String.IsNullOrEmpty(itemID.ToString()) && itemID != 0 && page == 2)
            {
                open_workflows_from_DB = HttpContext.Current.Session["Open_Workflows"] as DataTable;
            }

            //If a valid Bib, VID workflow was entered, add this to the current session
            if (String.IsNullOrEmpty(error_message) && !String.IsNullOrEmpty(BibID) && !String.IsNullOrEmpty(VID) && hidden_request != "save")
            {
                Add_New_Workflow();
            }
        }
        /// <summary> Constructor for a new instance of the Thematic_Headings_AdminViewer class </summary>
        /// <param name="User"> Authenticated user information </param>
        /// <param name="Current_Mode">  Mode / navigation information for the current request </param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        /// <remarks> Postback from handling saving the new settings is handled here in the constructor </remarks>
        public Settings_AdminViewer(User_Object User, SobekCM_Navigation_Object Current_Mode, Custom_Tracer Tracer)
            : base(User)
        {
            // If the user cannot edit this, go back
            if (( user == null ) || ((!User.Is_System_Admin) && (!User.Is_Portal_Admin)))
            {
                currentMode.Mode = Display_Mode_Enum.My_Sobek;
                currentMode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                currentMode.Redirect();
            }

            // Establish some default, starting values
            idToSetting = new Dictionary<int, Setting_Info>();
            settingToId = new Dictionary<Setting_Info, int>();
            categorizedSettings = new Dictionary<string, List<Setting_Info>>();
            settingCounter = 1;
            actionMessage = String.Empty;
            category_view = Convert.ToBoolean(User.Get_Setting("Settings_AdminViewer:Category_View", "false"));

            // Get the current settings from the database
            settings = SobekCM_Database.Get_Settings(Tracer);

            // Add some keys, which are stored in this portion of the database,
            // but are not really setting values so shouldn't show here (or are hidden)
            standardSettingKeys = new List<string> { "Builder Last Message", "Builder Last Run Finished", "Builder Version", "Builder Operation Flag", "Spreadsheet Library License" };

            // Get the default URL and default system location
            string default_url = Current_Mode.Base_URL;
            string default_location = HttpContext.Current.Request.PhysicalApplicationPath;

            // NOTE: This code is exactly the same as found in the SobekCM_Configuration tool.  That is why
            // this feels a little strange, to be loading information about all the settings, and then handling
            // the display portion late.  This allows the settings to be added or subtracted from rather easily
            // in code and also keeps the exact same code chunk to keep the configuration tool and the web
            // app both kept current simultaneously.
            string[] empty_options = new string[] { };
            string[] boolean_options = new[] { "true", "false" };
            string[] language_options = Web_Language_Enum_Converter.Language_Name_Array;
            Add_Setting_UI("Application Server Network", "Server Configuration", -1, empty_options, "Server share for the web application's network location.\n\nExample: '\\\\lib-sandbox\\Production\\'", false, default_location);
            Add_Setting_UI("Application Server URL", "Server Configuration", -1, empty_options, "Base URL which points to the web application.\n\nExamples: 'http://localhost/sobekcm/', 'http://ufdc.ufl.edu/', etc..", false, default_url);
            Add_Setting_UI("Archive DropBox", "Archiving", -1, empty_options, "Network location for the archive drop box.  If this is set to a value, the builder/bulk loader will place a copy of the package in this folder for archiving purposes.  This folder is where any of your archiving processes should look for new packages.", false );
            Add_Setting_UI("Builder Log Expiration in Days", "Builder", 200, new[] { "10", "30", "365", "99999" }, "Number of days the SobekCM Builder logs are retained.", false, "10");
            Add_Setting_UI("Builder Operation Flag", "Builder", 200, new[] { "STANDARD OPERATION", "PAUSE REQUESTED", "ABORT REQUESTED", "NO BUILDER REQUESTED" }, "Last flag set when the builder/bulk loader ran.", false );
            Add_Setting_UI("Builder Seconds Between Polls", "Builder", 200, new[] { "15", "60", "300", "600" }, "Number of seconds the builder remains idle before checking for new incoming package again.", false, "60");
            Add_Setting_UI("Caching Server", "Server Configuration", -1, empty_options, "URL for the AppFabric Cache host machine, if a caching server/cluster is in use in this system.", false);
            Add_Setting_UI("Can Remove Single Search Term", "General Appearance", 70, boolean_options, "When this is set to TRUE, users can remove a single search term from their current search.  Setting this to FALSE, makes the display slightly cleaner.", false);
            Add_Setting_UI("Can Submit Edit Online", "Resource Files", 70, boolean_options, "Flag dictates if users can submit items online, or if this is disabled in this system.", false);
            Add_Setting_UI("Convert Office Files to PDF", "Resource Files", 70, boolean_options, "Flag dictates if users can submit items online, or if this is disabled in this system.", false, "false");
            Add_Setting_UI("Create MARC Feed By Default", "Interoperability", 70, boolean_options, "Flag indicates if the builder/bulk loader should create the MARC feed by default when operating in background mode.", false );
            Add_Config_Setting("Database Type", "Server Configuration", SobekCM_Library_Settings.Database_Connections[0].Database_Type_String, "Type of database used to drive the SobekCM system.\n\nCurrently, only Microsoft SQL Server is allowed with plans to add PostgreSQL to the supported database system.\n\nThis value resides in the configuration on the web server.  See your database and web server administrator to change this value.");
            Add_Config_Setting("Database Connection String", "Server Configuration", SobekCM_Library_Settings.Database_Connections[0].Connection_String, "Connection string used to connect to the SobekCM database\n\nThis value resides in the configuration file on the web server.  See your database and web server administrator to change this value.");
            Add_Setting_UI("Detailed User Permissions", "System Configuration", -1, boolean_options, "Flag indicates if more refined user permissions can be assigned, such as if a user can edit behaviors of an item in a collection vs. a more general flag that says a user can make all changes to an item in a collection.", false);
            Add_Setting_UI("Document Solr Index URL", "Server Configuration", -1, empty_options, "URL for the document-level solr index.\n\nExample: 'http://*****:*****@corp.edu;[email protected]'.\n\nThis value resides in the web.config file on the web server.  See your web server administrator to change this value.");
            Add_Config_Setting("Error HTML Page", "System Configuration", SobekCM_Library_Settings.System_Error_URL, "Static page the user should be redirected towards if an unexpected exception occurs which cannot be handled by the web application.\n\nExample: 'http://ufdc.ufl.edu/error.html'.\n\nThis value resides in the web.config file on the web server.  See your web server administrator to change this value.");
            Add_Setting_UI("Facets Collapsible", "General Appearance", 70, boolean_options, "Flag determines if the facets are collapsible like an accordian, or if they all start fully expanded.", false);
            Add_Setting_UI("FDA Report DropBox", "Florida SUS", -1, empty_options, "Location for the builder/bulk loader to look for incoming Florida Dark Archive XML reports to process and add to the history of digital resources.", true );
            Add_Setting_UI("Files To Exclude From Downloads", "Resource Files", -1, empty_options, "Regular expressions used to exclude files from being added by default to the downloads of resources.\n\nExample: '((.*?)\\.(jpg|tif|jp2|jpx|bmp|jpeg|gif|png|txt|pro|mets|db|xml|bak|job)$|qc_error.html)'", false );
            Add_Setting_UI("Help URL", "Help", -1, empty_options, "URL used for the main help pages about this system's basic functionality.\n\nExample (and default): 'http://ufdc.ufl.edu/'", false );
            Add_Setting_UI("Help Metadata URL", "Help", -1, empty_options, "URL used for the help pages when users request help on metadata elements during online submit and editing.\n\nExample (and default): 'http://ufdc.ufl.edu/'", false );
            Add_Setting_UI("Image Server Network", "Server Configuration", -1, empty_options, "Network location to the content for all of the digital resources (images, metadata, etc.).\n\nExample: 'C:\\inetpub\\wwwroot\\UFDC Web\\SobekCM\\content\\' or '\\\\ufdc-images\\content\\'", false, default_location + "content\\");
            Add_Setting_UI("Image Server URL", "Server Configuration", -1, empty_options, "URL which points to the digital resource images.\n\nExample: 'http://localhost/sobekcm/content/' or 'http://ufdcimages.uflib.ufl.edu/'", false, default_url + "content/");
            Add_Setting_UI("Include Partners On System Home", "System Configuration", 70, boolean_options, "This option controls whether a PARTNERS option appears on the main system home page, assuming there are multiple institutional aggregations.", false, "false");
            Add_Setting_UI("Include TreeView On System Home", "System Configuration", 70, boolean_options, "This option controls whether a TREE VIEW option appears on the main system home page which displays all the active aggregations hierarchically in a tree view.", false, "false");
            Add_Setting_UI("JPEG Height", "Resource Files", 60, empty_options, "Restriction on the size of the jpeg page images' height (in pixels) when generated automatically by the builder/bulk loader.\n\nDefault: '1000'", false);
            Add_Setting_UI("JPEG Width", "Resource Files", 60, empty_options, "Restriction on the size of the jpeg page images' width (in pixels) when generated automatically by the builder/bulk loader.\n\nDefault: '630'", false);
            Add_Setting_UI("JPEG2000 Server", "Server Configuration", -1, empty_options, "URL for the Aware JPEG2000 Server for displaying and zooming into JPEG2000 images.", false);
            Add_Setting_UI("JPEG2000 Server Type", "Server Configuration", -1, new[] { "Aware", "Built-In IIPImage", "None"}, "Type of the JPEG2000 server found at the URL above.", false);
            Add_Setting_UI("Kakadu JPEG2000 Create Command", "Resource Files", -1, empty_options, "Kakadu JPEG2000 script will override the specifications used when creating zoomable images.\n\nIf this is blank, the default specifications will be used which match those used by the National Digital Newspaper Program and University of Florida Digital Collections.", false);
            Add_Setting_UI("Log Files Directory", "Builder", -1, empty_options, "Network location for the share within which the builder/bulk loader logs should be copied to become web accessible.\n\nExample: '\\\\lib-sandbox\\Design\\extra\\logs\\'", false, default_location + "design\\extra\\logs\\");
            Add_Setting_UI("Log Files URL", "Builder", -1, empty_options, "URL for the builder/bulk loader logs files.\n\nExample: 'http://ufdc.ufl.edu/design/extra/logs/'", false, default_url + "design/exra/logs/");
            Add_Setting_UI("Main Builder Input Folder", "Builder", -1, empty_options, "This is the network location to the SobekCM Builder's main incoming folder.\n\nThis is used by the SMaRT tool when doing bulk imports from spreadsheet or MARC records.", false);
            Add_Setting_UI("Mango Union Search Base URL", "Florida SUS", -1, empty_options, "Florida SUS state-wide catalog base URL for determining the number of physical holdings which match a given search.\n\nExample: 'http://solrcits.fcla.edu/citsZ.jsp?type=search&base=uf'", true );
            Add_Setting_UI("Mango Union Search Text", "Florida SUS", -1, empty_options, "Text to display the number of hits found in the Florida SUS-wide catalog.\n\nUse the value '%1' in the string where the number of hits should be inserted.\n\nExample: '%1 matches found in the statewide catalog'", true );
            Add_Setting_UI("MarcXML Feed Location", "Interoperability", -1, empty_options, "Network location or share where any geneated MarcXML feed should be written.\n\nExample: '\\\\lib-sandbox\\Data\\'", false, default_location + "data\\");
            Add_Setting_UI("OAI Repository Identifier", "Interoperability", 200, empty_options, "Identification for this repository when serving the OAI-PMH feeds.\n\nThis appears when a as 'Repository Identifier' under the OAI-Identifier when a user identifies the OAI-PMH repository.\n\nExamples: 'ufdc', 'sobekcm', 'dloc', etc..", false);
            Add_Setting_UI("OAI Repository Name", "Interoperability", -1, empty_options, "Complete name for this repository when serving the OAI-PMH feeds.\n\nThis appears when a as 'Repository Name' when a user identifies the OAI-PMH repository.\n\nExamples: 'University of Florida Digital Collections', 'Digital Library of the Caribbean', etc..", false);
            Add_Setting_UI("OAI Resource Identifier Base", "Interoperability", 200, empty_options, "Base identifier used for all resources found within this repository when serving them via OAI-PMH.\n\nThe complete item identifier begins with this base and then adds the bibliographic identifier (BibID) to complete the unique resource identifier.\n\nExamples: 'oai:sobekcm:', 'oai:www.uflib.ufl.edu.ufdc:', etc..", false);
            Add_Setting_UI("OCR Engine Command", "Resource Files", -1, empty_options, "If you wish to utilize an OCR engine in the builder/bulk loader, add the command-line call to the engine here.\n\nUse %1 as a place holder for the ingoing image file name and %2 as a placeholder for the output text file name.\n\nExample: 'C:\\OCR\\Engine.exe -in %1 -out %2'", false );
            Add_Setting_UI("Page Solr Index URL", "Server Configuration", -1, empty_options, "URL for the resource-level solr index used when searching for matching pages within a single document.\n\nExample: 'http://*****:*****@corp.edu;[email protected]'", false );
            Add_Setting_UI("Shibboleth User Identity Attribute", "Authentication", 200, empty_options, "The name of the attribute from Shibboleth which holds the user identity information, for user identification.\n\nSpeak to your Shibboleth administrator for this information.", false);
            Add_Setting_UI("Shibboleth System Name", "Authentication", 200, empty_options, "Local name of the Shibboleth authentication system.\n\nExamples: 'GatorLink', 'PantherSoft', etc..", false );
            Add_Setting_UI("Shibboleth System URL", "Authentication", -1, empty_options, "URL for the Shibboleth authentication process.", false );
            Add_Setting_UI("Show Florida SUS Settings", "Florida SUS", 70, boolean_options, "Some system settings are only applicable to institutions which are part of the Florida State University System.  Setting this value to TRUE will show these settings, while FALSE will suppress them.\n\nIf this value is changed, you willl need to save the settings for it to reload and reflect the change.", false, "false");
            Add_Setting_UI("SobekCM Web Server IP", "Server Configuration", 200, empty_options, "IP address for the web server running this web repository software.\n\nThis is used for setting restricted or dark material to only be available for the web server, which then acts as a proxy/web server to serve that content to authenticated users.", false );
            Add_Setting_UI("Static Pages Location", "Server Configuration", -1, empty_options, "Location where the static files are located for providing the full citation and text for indexing, either on the same server as the web application or as a network share.\n\nIt is recommended that these files be on the same server as the web server, rather than remote storage, to increase the speed in which requests from search engine indexers can be fulfilled.\n\nExample: 'C:\\inetpub\\wwwroot\\UFDC Web\\SobekCM\\data\\'.", false, default_location + "data\\");
            Add_Setting_UI("Statistics Caching Enabled", "System Configuration", 70, boolean_options, "Flag indicates if the basic usage and item count information should be cached for up to 24 hours as static XML files written in the web server's temp directory.\n\nThis should be enabled if your library is quite large as it can take a fair amount of time to retrieve this information and these screens are made available for search engine index robots for indexing.", false);
            Add_Setting_UI("System Base Abbreviation", "System Configuration", 100, empty_options, "Base abbreviation to be used when the system refers to itself to the user, such as the main tabs to take a user to the home pages.\n\nThis abbreviation should be kept as short as possible.\n\nExamples: 'UFDC', 'dLOC', 'Sobek', etc..", false);
            Add_Setting_UI("System Base Name", "System Configuration", -1, empty_options, "Overall name of the system, to be used when creating MARC records and in several other locations.", false);
            Add_Setting_UI("System Base URL", "System Configuration", -1, empty_options, "Base URL which points to the web application.\n\nExamples: 'http://localhost/sobekcm/', 'http://ufdc.ufl.edu/', etc..", false, default_url);
            Add_Setting_UI("System Default Language", "System Configuration", 150, language_options, "Default system user interface language.  If the user's HTML request does not include a language supported by the interface or which does not include specific translations for a field, this default language is utilized.", false, "English");
            Add_Setting_UI("System Email", "Emails", -1, empty_options, "Default email address for the system, which is sent emails when users opt to contact the administrators.\n\nThis can be changed for individual aggregations but at least one email is required for the overall system.\n\nIf you are using multiple email addresses, seperate them with a semi-colon.\n\nExample: '[email protected];[email protected]'", false );
            Add_Setting_UI("System Error Email", "Emails", -1, empty_options, "Email address used when a critical system error occurs which may require investigation or correction.\n\nIf you are using multiple email addresses, seperate them with a semi-colon.\n\nExample: '[email protected];[email protected]'", false );
            Add_Setting_UI("Thumbnail Height", "Resource Files", 60, empty_options, "Restriction on the size of the page image thumbnails' height (in pixels) when generated automatically by the builder/bulk loader.\n\nDefault: '300'", false );
            Add_Setting_UI("Thumbnail Width", "Resource Files", 60, empty_options, "Restriction on the size of the page image thumbnails' width (in pixels) when generated automatically by the builder/bulk loader.\n\nDefault: '150'", false );
            Add_Setting_UI("Upload File Types", "Resource Files", -1, empty_options, "List of non-image extensions which are allowed to be uploaded into a digital resource.\n\nList should be the extensions, with the period, separated by commas.\n\nExample: .aif,.aifc,.aiff,.au,.avi,.bz2,.c,.c++,.css,.dbf,.ddl,...", false);
            Add_Setting_UI("Upload Image Types", "Resource Files", -1, empty_options, "List of page image extensions which are allowed to be uploaded into a digital resource to display as page images.\n\nList should be the extensions, with the period, separated by commas.\n\nExample: .txt,.tif,.jpg,.jp2,.pro", false);
            Add_Setting_UI("Web In Process Submission Location", "System Configuration", -1, empty_options, "Location where packages are built by users during online submissions and metadata updates.\n\nThis generally needs to be on the web server and have appropriate access for read/write.\n\nIf nothing is indicated in this field, the system will automatically use the 'mySobek\\InProcess' subfolder under the web application.", false, default_location + "mySobek\\InProcess\\");
            Add_Setting_UI("Web Output Caching Minutes", "System Configuration", 200, new[] { "0", "1", "2", "3", "5", "10", "15" }, "This setting controls how long the client's browser is instructed to cache the served web page.\n\nSetting this value higher removes the round-trip when requesting a recently requested page.  It also means that some changes may not be reflected until the refresh button is pressed.\n\nIn general, this setting is only applied to public-style pages, and not personalized pages, such as the bookshelf views.", false, "0");

            // Is this a post-back requesting to save all this data?
            if (Current_Mode.isPostBack)
            {
                NameValueCollection form = HttpContext.Current.Request.Form;

                if (form["admin_settings_order"] == "category")
                {
                    User.Add_Setting("Settings_AdminViewer:Category_View", "true");
                    category_view = true;
                }

                if (form["admin_settings_order"] == "alphabetical")
                {
                    User.Add_Setting("Settings_AdminViewer:Category_View", "false");
                    category_view = false;
                }

                string action_value = form["admin_settings_action"];
                if ((action_value == "save") && ( User.Is_System_Admin ))
                {
                    // Populate all the new settings
                    Dictionary<string, string> newSettings = new Dictionary<string, string>();
                    List<string> customSettingKeys = new List<string>();

                    int errors = 0;
                    // Step through each setting
                    foreach (int thisSettingCounter in idToSetting.Keys)
                    {
                        Setting_Info thisSetting = idToSetting[thisSettingCounter];
                        if (thisSetting.IsVariable)
                        {
                            string setting_key = thisSetting.Key;
                            if (form["setting" + thisSettingCounter] != null)
                            {
                                string setting_value = form["setting" + thisSettingCounter];
                                newSettings[setting_key] = setting_value;
                            }
                        }
                    }

                    // Step through each possible custom setting
                    for (int i = 0; i < (settings.Count - standardSettingKeys.Count) + 20; i++)
                    {
                        string key = form["admin_customkey_" + i];
                        if ( !String.IsNullOrEmpty(key))
                        {
                            string value = form["admin_customvalue_" + i];
                            if (!String.IsNullOrEmpty(value))
                            {
                                newSettings[key] = value;
                                customSettingKeys.Add(key);
                            }
                        }
                    }

                    // Determine which settings need to be DELETED from the database
                    foreach (KeyValuePair<string, string> customSetting in settings)
                    {
                        if ((!standardSettingKeys.Contains(customSetting.Key)) && ( !customSettingKeys.Contains(customSetting.Key)))
                        {
                            SobekCM_Database.Delete_Setting(customSetting.Key);
                        }
                    }

                    // Now, validate all this
                    errorBuilder = new StringBuilder();
                    isValid = true;
                    if (validate_update_entered_data(newSettings))
                    {
                        // Try to save each setting
                        errors += newSettings.Keys.Count(ThisKey => !SobekCM_Database.Set_Setting(ThisKey, newSettings[ThisKey]));

                        // Prepare the action message
                        if (errors > 0)
                            actionMessage = "Save completed, but with " + errors + " errors.";
                        else
                            actionMessage = "Settings saved";

                        // Get the current settings from the database
                        settings = SobekCM_Database.Get_Settings(Tracer);

                        // Assign this to be used by the system
                        SobekCM_Library_Settings.Refresh(SobekCM_Database.Get_Settings_Complete(null));
                    }
                    else
                    {
                        actionMessage = errorBuilder.ToString().Replace("\n", "<br />");
                        settings = newSettings;
                    }
                }
            }
        }