/// <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();
            }
        }
        private static User_Object build_user_object_from_dataset(DataSet ResultSet )
        {
            User_Object user = new User_Object();

            DataRow userRow = ResultSet.Tables[0].Rows[0];
            user.ShibbID = userRow["ShibbID"].ToString();
            user.UserID = Convert.ToInt32(userRow["UserID"]);
            user.UserName = userRow["username"].ToString();
            user.Email = userRow["EmailAddress"].ToString();
            user.Given_Name = userRow["FirstName"].ToString();
            user.Family_Name = userRow["LastName"].ToString();
            user.Send_Email_On_Submission = Convert.ToBoolean(userRow["SendEmailOnSubmission"]);
            user.Can_Submit = Convert.ToBoolean(userRow["Can_Submit_Items"]);
            user.Is_Temporary_Password = Convert.ToBoolean(userRow["isTemporary_Password"]);
            user.Nickname = userRow["Nickname"].ToString();
            user.Organization = userRow["Organization"].ToString();
            user.Organization_Code = userRow["OrganizationCode"].ToString();
            user.Department = userRow["Department"].ToString();
            user.College = userRow["College"].ToString();
            user.Unit = userRow["Unit"].ToString();
            user.Default_Rights = userRow["Rights"].ToString();
            user.Preferred_Language = userRow["Language"].ToString();
            user.Is_Internal_User = Convert.ToBoolean(userRow["Internal_User"]);
            user.Edit_Template_Code = userRow["EditTemplate"].ToString();
            user.Edit_Template_MARC_Code = userRow["EditTemplateMarc"].ToString();
            user.Can_Delete_All = Convert.ToBoolean(userRow["Can_Delete_All_Items"]);
            user.Is_System_Admin = Convert.ToBoolean(userRow["IsSystemAdmin"]);
            user.Is_Portal_Admin = Convert.ToBoolean(userRow["IsPortalAdmin"]);
            user.Include_Tracking_In_Standard_Forms = Convert.ToBoolean(userRow["Include_Tracking_Standard_Forms"]);
            user.Receive_Stats_Emails = Convert.ToBoolean(userRow["Receive_Stats_Emails"]);
            user.Has_Item_Stats = Convert.ToBoolean(userRow["Has_Item_Stats"]);
            user.LoggedOn = true;
            user.Internal_Notes = userRow["InternalNotes"].ToString();
            user.Processing_Technician = Convert.ToBoolean(userRow["ProcessingTechnician"]);
            user.Scanning_Technician = Convert.ToBoolean(userRow["ScanningTechnician"]);

            if (Convert.ToInt32(userRow["descriptions"]) > 0)
                user.Has_Descriptive_Tags = true;

            foreach (DataRow thisRow in ResultSet.Tables[1].Rows)
            {
                user.Add_Template(thisRow["TemplateCode"].ToString(), Convert.ToBoolean(thisRow["GroupDefined"].ToString()));
            }

            foreach (DataRow thisRow in ResultSet.Tables[2].Rows)
            {
                user.Add_Default_Metadata_Set(thisRow["MetadataCode"].ToString(), Convert.ToBoolean(thisRow["GroupDefined"].ToString()));
            }

            user.Items_Submitted_Count = ResultSet.Tables[3 ].Rows.Count;
            foreach (DataRow thisRow in ResultSet.Tables[3 ].Rows)
            {
                if (!user.BibIDs.Contains(thisRow["BibID"].ToString().ToUpper()))
                    user.Add_BibID(thisRow["BibID"].ToString().ToUpper());
            }

            // Add links to regular expressions
            foreach (DataRow thisRow in ResultSet.Tables[4 ].Rows)
            {
                user.Add_Editable_Regular_Expression(thisRow["EditableRegex"].ToString());
            }

            // Add links to aggregations
            foreach (DataRow thisRow in ResultSet.Tables[5 ].Rows)
            {

                user.Add_Aggregation(thisRow["Code"].ToString(), thisRow["Name"].ToString(), Convert.ToBoolean(thisRow["CanSelect"]), Convert.ToBoolean(thisRow["CanEditMetadata"]), Convert.ToBoolean(thisRow["CanEditBehaviors"]), Convert.ToBoolean(thisRow["CanPerformQc"]), Convert.ToBoolean(thisRow["CanUploadFiles"]), Convert.ToBoolean(thisRow["CanChangeVisibility"]), Convert.ToBoolean(thisRow["CanDelete"]), Convert.ToBoolean(thisRow["IsCollectionManager"]), Convert.ToBoolean(thisRow["OnHomePage"]), Convert.ToBoolean(thisRow["IsAggregationAdmin"]), Convert.ToBoolean(thisRow["GroupDefined"]));

            }

            // Add the current folder names
            Dictionary<int, User_Folder> folderNodes = new Dictionary<int, User_Folder>();
            List<User_Folder> parentNodes = new List<User_Folder>();
            foreach (DataRow folderRow in ResultSet.Tables[6 ].Rows)
            {
                string folderName = folderRow["FolderName"].ToString();
                int folderid = Convert.ToInt32(folderRow["UserFolderID"]);
                int parentid = Convert.ToInt32(folderRow["ParentFolderID"]);
                bool isPublic = Convert.ToBoolean(folderRow["isPublic"]);

                User_Folder newFolderNode = new User_Folder(folderName, folderid) {isPublic = isPublic};
                if (parentid == -1)
                    parentNodes.Add(newFolderNode);
                folderNodes.Add(folderid, newFolderNode);
            }
            foreach (DataRow folderRow in ResultSet.Tables[6 ].Rows)
            {
                int folderid = Convert.ToInt32(folderRow["UserFolderID"]);
                int parentid = Convert.ToInt32(folderRow["ParentFolderID"]);
                if (parentid > 0)
                {
                    folderNodes[parentid].Add_Child_Folder(folderNodes[folderid]);
                }
            }
            foreach (User_Folder rootFolder in parentNodes)
                user.Add_Folder(rootFolder);

            // Get the list of BibID/VID associated with this
            foreach (DataRow itemRow in ResultSet.Tables[7 ].Rows)
            {
                user.Add_Bookshelf_Item(itemRow["BibID"].ToString(), itemRow["VID"].ToString());
            }

            // Add the user groups to which this user is a member
            foreach (DataRow groupRow in ResultSet.Tables[8].Rows)
            {
                user.Add_User_Group(groupRow[0].ToString());
            }

            // Get all the user settings
            foreach (DataRow settingRow in ResultSet.Tables[9].Rows)
            {
                user.Add_Setting(settingRow["Setting_Key"].ToString(), settingRow["Setting_Value"].ToString(), false);
            }

            return user;
        }
        /// <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;
                    }
                }
            }
        }
        /// <summary> Constructor for a new instance of the QC_ItemViewer class </summary>
        /// <param name="Current_Object"> Digital resource to display </param>
        /// <param name="Current_User"> Current user for this session </param>
        /// <param name="Current_Mode"> Navigation object which encapsulates the user's current request </param>
        public QC_ItemViewer(SobekCM_Item Current_Object, User_Object Current_User, SobekCM_Navigation_Object Current_Mode)
        {
            // Save the current user and current mode information (this is usually populated AFTER the constructor completes,
            // but in this case (QC viewer) we need the information for early processing
            CurrentMode = Current_Mode;
            CurrentUser = Current_User;

            //Assign the current resource object to qc_item
            qc_item = Current_Object;
            //Save to the User's session
            HttpContext.Current.Session[Current_Object.BibID + "_" + Current_Object.VID + " QC Work"] = qc_item;

            // If there is no user, send to the login
            if (CurrentUser == null)
            {
                CurrentMode.Mode = Display_Mode_Enum.My_Sobek;
                CurrentMode.My_Sobek_Type = My_Sobek_Type_Enum.Logon;
                CurrentMode.Redirect();
                return;
            }

            // If the user cannot edit this item, go back
            if (!CurrentUser.Can_Edit_This_Item(Current_Object))
            {
                CurrentMode.ViewerCode = String.Empty;
                CurrentMode.Redirect();
                return;
            }

            //If there are no pages for this item, redirect to the image upload screen
            if (qc_item.Web.Static_PageCount == 0)
            {
                CurrentMode.Mode = Display_Mode_Enum.My_Sobek;
                CurrentMode.My_Sobek_Type = My_Sobek_Type_Enum.Page_Images_Management;
                CurrentMode.Redirect();
                return;
            }

            // Get the links for the METS
            string greenstoneLocation = Current_Object.Web.Source_URL + "/";
            complete_mets = greenstoneLocation + Current_Object.BibID + "_" + Current_Object.VID + ".mets.xml";

            // MAKE THIS USE THE FILES.ASPX WEB PAGE if this is restricted (or dark)
            if ((Current_Object.Behaviors.Dark_Flag) || (Current_Object.Behaviors.IP_Restriction_Membership > 0))
            {
                complete_mets = CurrentMode.Base_URL + "files/" + qc_item.BibID + "/" + qc_item.VID + "/" + qc_item.BibID + "_" + qc_item.VID + ".mets.xml";
            }

            // Get the special qc_item, which matches the passed in Current_Object, at least the first time.
            // If the QC work is already in process, we may find a temporary METS file to read.

            // Determine the in process directory for this
            userInProcessDirectory = SobekCM_Library_Settings.In_Process_Submission_Location + "\\" + Current_User.UserName.Replace(".", "").Replace("@", "") + "\\qcwork\\" + qc_item.METS_Header.ObjectID;
            if (Current_User.ShibbID.Trim().Length > 0)
                userInProcessDirectory = SobekCM_Library_Settings.In_Process_Submission_Location + "\\" + Current_User.ShibbID + "\\qcwork\\" + qc_item.METS_Header.ObjectID;

            // Make the folder for the user in process directory
            if (!Directory.Exists(userInProcessDirectory))
                Directory.CreateDirectory(userInProcessDirectory);

            // Create the name for the tempoary METS file?
            metsInProcessFile = userInProcessDirectory + "\\" + Current_Object.BibID + "_" + Current_Object.VID + ".mets.xml";

            // Is this work in the user's SESSION state?
            qc_item = HttpContext.Current.Session[Current_Object.BibID + "_" + Current_Object.VID + " QC Work"] as SobekCM_Item;
            if (qc_item == null)
            {

                // Is there a temporary METS for this item, which is not expired?
                if ((File.Exists(metsInProcessFile)) &&
                    (File.GetLastWriteTime(metsInProcessFile).Subtract(DateTime.Now).Hours < 8))
                {
                    // Read the temporary METS file, and use that to build the qc_item
                    qc_item = SobekCM_Item_Factory.Get_Item(metsInProcessFile, Current_Object.BibID, Current_Object.VID, null, null, null);
                    qc_item.Source_Directory = Current_Object.Source_Directory;
                }
                else
                {
                    // Just read the normal otherwise ( if we had the ability to deep copy a SobekCM_Item, we could skip this )
                    qc_item = SobekCM_Item_Factory.Get_Item(Current_Object.BibID, Current_Object.VID, null, null, null);
                }

                // Save to the session, so it is easily available for next time
                HttpContext.Current.Session[Current_Object.BibID + "_" + Current_Object.VID + " QC Work"] = qc_item;
            }

            // If no QC item, this is an error
            if (qc_item == null)
            {
                throw new ApplicationException("Unable to retrieve the item for Quality Control in QC_ItemViewer.Constructor");
            }

            // Get the default QC profile
            qc_profile = QualityControl_Configuration.Default_Profile;

            title = "Quality Control";

            // If this was a post-back keep the required height and width for the qc area
            allThumbnailsOuterDiv1Width = -1;
            allThumbnailsOuterDiv1Height = -1;
            string temp_width = HttpContext.Current.Request.Form["QC_window_width"] ?? String.Empty;
            string temp_height = HttpContext.Current.Request.Form["QC_window_height"] ?? String.Empty;

            if ((temp_width.Length > 0) && (temp_height.Length > 0))
            {
                // Parse the values and save to the session
                if (Int32.TryParse(temp_width, out allThumbnailsOuterDiv1Width))
                    HttpContext.Current.Session["QC_AllThumbnailsWidth"] = allThumbnailsOuterDiv1Width;
                if (Int32.TryParse(temp_height, out allThumbnailsOuterDiv1Height))
                    HttpContext.Current.Session["QC_AllThumbnailsHeight"] = allThumbnailsOuterDiv1Height;

            }
            else
            {
                object session_width = HttpContext.Current.Session["QC_AllThumbnailsWidth"];
                if (session_width != null)
                    allThumbnailsOuterDiv1Width = (int) session_width;
                object session_height = HttpContext.Current.Session["QC_AllThumbnailsHeight"];
                if (session_height != null)
                    allThumbnailsOuterDiv1Height = (int) session_height;
            }

            // See if there were hidden requests
            hidden_request = HttpContext.Current.Request.Form["QC_behaviors_request"] ?? String.Empty;
            hidden_main_thumbnail = HttpContext.Current.Request.Form["Main_Thumbnail_File"] ?? String.Empty;
            hidden_move_relative_position = HttpContext.Current.Request.Form["QC_move_relative_position"] ?? String.Empty;
            hidden_move_destination_fileName = HttpContext.Current.Request.Form["QC_move_destination"] ?? String.Empty;
            autonumber_number_system = HttpContext.Current.Request.Form["Autonumber_number_system"] ?? String.Empty;
            string temp = HttpContext.Current.Request.Form["autonumber_mode_from_form"] ?? "0";
            Int32.TryParse(temp, out autonumber_mode_from_form);
            autonumber_text_only = HttpContext.Current.Request.Form["Autonumber_text_without_number"] ?? String.Empty;
            autonumber_number_only = HttpContext.Current.Request.Form["Autonumber_number_only"] ?? String.Empty;
            autonumber_number_system = HttpContext.Current.Request.Form["Autonumber_number_system"] ?? String.Empty;
            hidden_autonumber_filename = HttpContext.Current.Request.Form["Autonumber_last_filename"] ?? String.Empty;
            temp = HttpContext.Current.Request.Form["QC_sortable_option"] ?? "-1";
            if (Int32.TryParse(temp, out makeSortable) && (makeSortable > 0) && (makeSortable <= 3))
            {
                CurrentUser.Add_Setting("QC_ItemViewer:SortableMode",makeSortable);
            }
            temp = HttpContext.Current.Request.Form["QC_autonumber_option"] ?? "-1";
            if ((Int32.TryParse(temp, out autonumber_mode)) && ( autonumber_mode >= 0 ) && ( autonumber_mode <= 2 ))
            {
                CurrentUser.Add_Setting("QC_ItemViewer:AutonumberingMode", autonumber_mode);
            }

            //Get any notes/comments entered by the user
            notes = HttpContext.Current.Request.Form["txtComments"] ?? String.Empty;

            if (!(Int32.TryParse(HttpContext.Current.Request.Form["QC_Sortable"], out makeSortable))) makeSortable = 3;
            // If the hidden move relative position is BEFORE, it is before the very first page
            if (hidden_move_relative_position == "Before")
                hidden_move_destination_fileName = "[BEFORE FIRST]";

            try
            {

                //Call the JavaScript autosave function based on the option selected
                bool autosaveCacheValue = true;
                bool autosaveCache = false;

                //Conversion result of autosaveCacheValue(conversion successful or not) saved in autosaveCache

                if (HttpContext.Current.Session["autosave_option"] != null)
                    autosaveCache = bool.TryParse(HttpContext.Current.Session["autosave_option"].ToString(), out autosaveCacheValue);
                bool convert = bool.TryParse(HttpContext.Current.Request.Form["Autosave_Option"], out autosave_option);
                if (!convert && !autosaveCache)
                {
                    autosave_option = true;
                }
                else if (!convert && autosaveCache)
                {
                    autosave_option = autosaveCacheValue;
                }

                else
                {
                    HttpContext.Current.Session["autosave_option"] = autosave_option;
                }
            }
            catch (Exception e)
            {
                throw new ApplicationException("Error retrieving auto save option. " + e.Message);
            }

            // Check for a previously set main thumbnail, or one from the requesting form
            if (!String.IsNullOrEmpty(hidden_main_thumbnail))
            {
                HttpContext.Current.Session["main_thumbnail_" + qc_item.BibID + "_" + qc_item.VID] = hidden_main_thumbnail;
            }
            else if (HttpContext.Current.Session["main_thumbnail_" + qc_item.BibID + "_" + qc_item.VID] == null )
            {
                hidden_main_thumbnail = qc_item.Behaviors.Main_Thumbnail.Replace("thm.jpg", "");
                HttpContext.Current.Session["main_thumbnail_" + qc_item.BibID + "_" + qc_item.VID] = hidden_main_thumbnail;
            }
            else
            {
                hidden_main_thumbnail = HttpContext.Current.Session["main_thumbnail_" + qc_item.BibID + "_" + qc_item.VID].ToString();
            }

            //Get the list of associated errors for this item from the database
            int itemID = Resource_Object.Database.SobekCM_Database.Get_ItemID(Current_Object.BibID, Current_Object.VID);
            Get_QC_Errors(itemID);

            // Perform any requested actions
            switch (hidden_request)
            {
                case "autosave":
                case "save":
                case "complete":
                    //Save the current time
                    HttpContext.Current.Session["QC_timeUpdated"] = DateTime.Now.ToString("hh:mm tt");

                    // Read the data from the http form, perform all requests, and
                    // update the qc_item (also updates the session and temporary files)
                    // Save this updated information in the temporary folder's METS file for reading later if necessary.
                    if ((Save_From_Form_Request_To_Item(String.Empty, String.Empty)) && (( hidden_request == "save" ) || ( hidden_request == "complete")))
                    {
                        // If the user selected SAVE or COMPLETE, roll out the new version
                        Move_Temp_Changes_To_Production();

                        // Redirect differently depending on SAVE or COMPLETE
                        if (hidden_request == "save")
                        {
                            // Forward back to the QC form
                            HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            CurrentMode.Request_Completed = true;
                        }
                        else if (hidden_request == "complete")
                        {
                            // Forward to the item
                            CurrentMode.ViewerCode = String.Empty;
                            CurrentMode.Redirect();
                        }
                    }
                    break;

                case "cancel":
                    Cancel_Current_QC();

                    // Forward back to the default item view
                    CurrentMode.ViewerCode = String.Empty;
                    CurrentMode.Redirect();
                    break;

                case "clear_pagination":
                    ClearPagination();
                    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    CurrentMode.Request_Completed = true;
                    break;

                case "clear_reorder":
                    Clear_Pagination_And_Reorder_Pages();
                    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    CurrentMode.Request_Completed = true;
                    break;

                case "save_error":
                    string error_code = HttpContext.Current.Request.Form["QC_error_number"] ?? String.Empty;
                    string affected_page_index = HttpContext.Current.Request.Form["QC_affected_file"] ?? String.Empty;
                    SaveQcError(itemID,error_code, affected_page_index);
                    break;

                case "delete_page":
                    // Read the data from the http form, perform all requests, and
                    // update the qc_item (also updates the session and temporary files)
                    string filename_to_delete = HttpContext.Current.Request.Form["QC_affected_file"] ?? String.Empty;
                    if (Save_From_Form_Request_To_Item(String.Empty, filename_to_delete))
                    {
                        Delete_Resource_File(filename_to_delete);
                    }

                    // Since we deleted a page, we need to roll out our new version
                    Move_Temp_Changes_To_Production();

                    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    CurrentMode.Request_Completed = true;
                    break;

                case "delete_selected_pages":
                    // Read the data from the http form, perform all requests, and
                    // update the qc_item (also updates the session and temporary files)
                    List<QC_Viewer_Page_Division_Info> selected_page_div_from_form;
                    if (Save_From_Form_Request_To_Item(String.Empty, String.Empty, out selected_page_div_from_form))
                    {
                        foreach (QC_Viewer_Page_Division_Info thisPage in selected_page_div_from_form)
                        {
                            Delete_Resource_File(thisPage.METS_StructMap_Page_Node.Files[0].File_Name_Sans_Extension);
                        }
                    }

                    // Since we deleted a page, we need to roll out our new version
                    Move_Temp_Changes_To_Production();

                    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    CurrentMode.Request_Completed = true;
                    break;

                case "move_selected_pages":
                    // Read the data from the http form, perform all requests, and
                    // update the qc_item (also updates the session and temporary files)
                    Save_From_Form_Request_To_Item(hidden_move_destination_fileName, String.Empty);

                    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    CurrentMode.Request_Completed = true;
                    break;
            }
        }