/// <summary> Constructor for a new instance of the Web_Content_HtmlSubwriter class </summary>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Static_Web_Content"> Object contains all the basic information about this info display </param>
        /// <param name="Site_Map"> Optional site map object used to render a navigational tree-view on left side of page</param>
        public Web_Content_HtmlSubwriter(Item_Aggregation Hierarchy_Object, SobekCM_Navigation_Object Current_Mode, SobekCM_Skin_Object HTML_Skin, HTML_Based_Content Static_Web_Content, SobekCM_SiteMap Site_Map)
        {
            base.Current_Aggregation = Hierarchy_Object;
            currentMode = Current_Mode;
            Skin = HTML_Skin;

            thisStaticBrowseObject = Static_Web_Content;
            siteMap = Site_Map;

            // If there is a sitemap, check if this is a robot request and then if the URL
            // for the sitemap pages is URL restricted
            if ((siteMap != null) && (siteMap.Is_URL_Restricted_For_Robots) && (currentMode.Is_Robot))
            {
                if (currentMode.Base_URL != siteMap.Restricted_Robot_URL)
                {
                    currentMode.Base_URL = siteMap.Restricted_Robot_URL;
                    string redirect_url = currentMode.Redirect_URL();

                    HttpContext.Current.Response.Status = "301 Moved Permanently";
                    HttpContext.Current.Response.AddHeader("Location", redirect_url);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    currentMode.Request_Completed = true;
                    return;
                }
            }
        }
        /// <summary> Constructor for a new instance of the Static_Pages_Builder class </summary>
        /// <param name="Primary_Web_Server_URL"> URL for the primary web server </param>
        /// <param name="Static_Data_Location"> Network location for the data directory </param>
        /// <param name="All_Items_Lookup"> Allows individual items to be retrieved by various methods as <see cref="Application_State.Single_Item"/> objects.</param>
        /// <param name="Code_Manager"> Code manager contains the list of all valid aggregation codes </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        public Static_Pages_Builder(string Primary_Web_Server_URL, string Static_Data_Location,
            Language_Support_Info Translator,
            Aggregation_Code_Manager Code_Manager,
            Item_Lookup_Object All_Items_Lookup,
            Dictionary<string, Wordmark_Icon> Icon_Table,
            SobekCM_Skin_Object HTML_Skin)
        {
            primaryWebServerUrl = Primary_Web_Server_URL;
            staticSobekcmDataLocation = Static_Data_Location;

            tracer = new Custom_Tracer();
            assistant = new SobekCM_Assistant();

               // marcWriter = new MARC_Writer();

            // Save all the objects needed by the UFDC Library
            iconList = Icon_Table;
            translations = Translator;
            codeManager = Code_Manager;
            itemList = All_Items_Lookup;
            ufdcInterface = HTML_Skin;
            dlocInterface = HTML_Skin;

            // Create the mode object
            currentMode = new SobekCM_Navigation_Object
                              {
                                  ViewerCode = "citation",
                                  Skin = "UFDC",
                                  Mode = Display_Mode_Enum.Item_Display,
                                  Language = Web_Language_Enum.English,
                                  Base_URL = primaryWebServerUrl
                              };
        }
        /// <summary> Add a new HTML skin to this collection, to be retained as long as the application is active </summary>
        /// <param name="Skin_Code"> Code for this new HTML skin</param>
        /// <param name="Base_Skin_Code"> Code for the base HTML skin which this new skin derives from</param>
        /// <param name="CSS_Style"> Additional CSS Stylesheet to be included for this new HTML skin</param>
        /// <param name="Banner_HTML"> Code for the banner to use, if this is set to override the banner</param>
        /// <returns> Newly constructed <see cref="SobekCM_Skin_Object"/> object </returns>
        public SobekCM_Skin_Object Add(string Skin_Code, string Base_Skin_Code, string CSS_Style, string Banner_HTML)
        {
            // Create the new skin object
            SobekCM_Skin_Object newSkin = new SobekCM_Skin_Object(Skin_Code, Base_Skin_Code, CSS_Style, Banner_HTML);

            // Add to the hashtable
            defaultSkins[Skin_Code.ToLower()] = newSkin;

            // Return the new, built skin object
            return(newSkin);
        }
 /// <summary> Add a new HTML skin to this collection, to be retained as long as the application is active </summary>
 /// <param name="NewSkin"> New HTML skin to retain in this collection </param>
 public void Add(SobekCM_Skin_Object NewSkin)
 {
     // Add to the hashtable
     if (NewSkin.Language_Code.Length == 0)
     {
         defaultSkins[NewSkin.Skin_Code.ToLower()] = NewSkin;
     }
     else
     {
         defaultSkins[NewSkin.Skin_Code.ToLower() + "_" + NewSkin.Language_Code.ToLower()] = NewSkin;
     }
 }
 /// <summary> Add a new HTML skin to this collection, to be retained as long as the application is active </summary>
 /// <param name="NewSkin"> New HTML skin to retain in this collection </param>
 public void Add(SobekCM_Skin_Object NewSkin)
 {
     // Add to the hashtable
     if (NewSkin.Language_Code.Length == 0)
     {
         defaultSkins[NewSkin.Skin_Code.ToLower()] = NewSkin;
     }
     else
     {
         defaultSkins[NewSkin.Skin_Code.ToLower() + "_" + NewSkin.Language_Code.ToLower()] = NewSkin;
     }
 }
        /// <summary> Constructor creates a new instance of the Aggregation_HtmlSubwriter class </summary>
        /// <param name="Current_Aggregation"> Current item aggregation object to display </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Browse_Object"> Object contains all the basic information about any browse or info display </param>
        /// <param name="Paged_Results"> Paged results to display within a browse or search result </param>
        /// <param name="Results_Statistics"> Information about the entire set of results for a search or browse </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Thematic_Headings"> Headings under which all the highlighted collections on the home page are organized </param>
        /// <param name="Current_User"> Currently logged on user (or object representing the unlogged on user's preferences) </param>
        /// <param name="Static_Web_Content"> HTML content-based browse, info, or imple CMS-style web content objects.  These are objects which are read from a static HTML file and much of the head information must be maintained </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public Aggregation_HtmlSubwriter(Item_Aggregation Current_Aggregation, 
            SobekCM_Navigation_Object Current_Mode, SobekCM_Skin_Object HTML_Skin, 
            Language_Support_Info Translator, 
            Item_Aggregation_Child_Page Browse_Object,
            Search_Results_Statistics Results_Statistics,
            List<iSearch_Title_Result> Paged_Results,
            Aggregation_Code_Manager Code_Manager, Item_Lookup_Object All_Items_Lookup,
            List<Thematic_Heading> Thematic_Headings, User_Object Current_User,
            HTML_Based_Content Static_Web_Content,
            Custom_Tracer Tracer )
        {
            currentUser = Current_User;
            base.Current_Aggregation = Current_Aggregation;
            currentMode = Current_Mode;
            Skin = HTML_Skin;
            translator = Translator;
            thisBrowseObject = Browse_Object;
            thisStaticBrowseObject = Static_Web_Content;
            codeManager = Code_Manager;
            itemList = All_Items_Lookup;
            thematicHeadings = Thematic_Headings;
            resultsStatistics = Results_Statistics;
            pagedResults = Paged_Results;
            leftButtons = String.Empty;
            rightButtons = String.Empty;

            // Check to see if the user should be able to edit the home page
            if ((currentMode.Mode == Display_Mode_Enum.Aggregation) && (currentMode.Aggregation_Type == Aggregation_Type_Enum.Home_Edit))
            {
                if ( currentUser == null )
                    currentMode.Aggregation_Type = Aggregation_Type_Enum.Home;
                else
                {
                    if ((!currentUser.Is_System_Admin) && (!currentUser.Is_Portal_Admin) && (!currentUser.Is_Aggregation_Admin(Current_Aggregation.Code)))
                    {
                        currentMode.Aggregation_Type = Aggregation_Type_Enum.Home;
                    }
                }
            }
            else if ( currentMode.Aggregation_Type == Aggregation_Type_Enum.Home_Edit )
                currentMode.Aggregation_Type = Aggregation_Type_Enum.Home;

            NameValueCollection form = HttpContext.Current.Request.Form;
            if ( form["item_action"] != null)
            {
                string action = form["item_action"].ToLower().Trim();

                if ((action == "add_aggregation") && ( currentUser != null ))
                {
                    SobekCM_Database.User_Set_Aggregation_Home_Page_Flag(currentUser.UserID, base.Current_Aggregation.Aggregation_ID, true, Tracer);
                    currentUser.Set_Aggregation_Home_Page_Flag(base.Current_Aggregation.Code, base.Current_Aggregation.Name, true);
                    HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "Added aggregation to your home page");
                }

                if (( action == "remove_aggregation") && ( currentUser != null ))
                {
                    int removeAggregationID = base.Current_Aggregation.Aggregation_ID;
                    string remove_code = base.Current_Aggregation.Code;
                    string remove_name = base.Current_Aggregation.Name;

                    if ((form["aggregation"] != null) && (form["aggregation"].Length > 0))
                    {
                        Item_Aggregation_Related_Aggregations aggrInfo = codeManager[form["aggregation"]];
                        if (aggrInfo != null)
                        {
                            remove_code = aggrInfo.Code;
                            removeAggregationID = aggrInfo.ID;
                        }
                    }

                    SobekCM_Database.User_Set_Aggregation_Home_Page_Flag(currentUser.UserID, removeAggregationID, false, Tracer);
                    currentUser.Set_Aggregation_Home_Page_Flag(remove_code, remove_name, false);

                    if (currentMode.Home_Type != Home_Type_Enum.Personalized)
                    {
                        HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "Removed aggregation from your home page");
                    }
                }

                if ((action == "private_folder") && ( currentUser != null ))
                {
                    User_Folder thisFolder = currentUser.Get_Folder(form["aggregation"]);
                    if (SobekCM_Database.Edit_User_Folder(thisFolder.Folder_ID, currentUser.UserID, -1, thisFolder.Folder_Name, false, String.Empty, Tracer) >= 0)
                        thisFolder.isPublic = false;
                }

                if ((action == "email") && ( currentUser != null ))
                {
                    string address = form["email_address"].Replace(";", ",").Trim();
                    string comments = form["email_comments"].Trim();
                    string format = form["email_format"].Trim().ToUpper();

                    if (address.Length > 0)
                    {
                        // Determine the email format
                        bool is_html_format = format != "TEXT";

                        // CC: the user, unless they are already on the list
                        string cc_list = currentUser.Email;
                        if (address.ToUpper().IndexOf(currentUser.Email.ToUpper()) >= 0)
                            cc_list = String.Empty;

                        // Send the email
                        string any_error = URL_Email_Helper.Send_Email(address, cc_list, comments, currentUser.Full_Name, currentMode.SobekCM_Instance_Abbreviation, is_html_format, HttpContext.Current.Items["Original_URL"].ToString(), base.Current_Aggregation.Name, "Collection", currentUser.UserID);
                        HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", any_error.Length > 0 ? any_error : "Your email has been sent");

                        currentMode.isPostBack = true;

                        // Do this to force a return trip (cirumnavigate cacheing)
                        string original_url = HttpContext.Current.Items["Original_URL"].ToString();
                        if (original_url.IndexOf("?") < 0)
                            HttpContext.Current.Response.Redirect(original_url + "?p=" + DateTime.Now.Millisecond, false);
                        else
                            HttpContext.Current.Response.Redirect(original_url + "&p=" + DateTime.Now.Millisecond, false);

                        HttpContext.Current.ApplicationInstance.CompleteRequest();
                        Current_Mode.Request_Completed = true;
                        return;
                    }
                }
            }

            if (( currentMode.Aggregation_Type == Aggregation_Type_Enum.Home_Edit ) && ( form["sbkAghsw_HomeTextEdit"] != null))
            {
                string aggregation_folder = SobekCM_Library_Settings.Base_Design_Location + "aggregations\\" + Current_Aggregation.Code + "\\";
                string file = aggregation_folder + Current_Aggregation.Home_Page_File(currentMode.Language);

                // Make a backup from today, if none made yet
                if (File.Exists(file))
                {
                    DateTime lastWrite = (new FileInfo(file)).LastWriteTime;
                    string new_file = file.ToLower().Replace(".txt", "").Replace(".html", "").Replace(".htm", "") + lastWrite.Year + lastWrite.Month.ToString().PadLeft(2, '0') + lastWrite.Day.ToString() .PadLeft(2, '0')+ ".bak";
                    if (File.Exists(new_file))
                        File.Delete(new_file);
                    File.Move(file, new_file);
                }

                // Write to the file now
                StreamWriter homeWriter = new StreamWriter(file, false);
                homeWriter.WriteLine(form["sbkAghsw_HomeTextEdit"]);
                homeWriter.Flush();
                homeWriter.Close();

                // Also save this change
                SobekCM_Database.Save_Item_Aggregation_Milestone(Current_Aggregation.Code, "Home page edited (" + Web_Language_Enum_Converter.Enum_To_Name(currentMode.Language) + ")", currentUser.Full_Name);

                // Clear this aggreation from the cache
                Cached_Data_Manager.Remove_Item_Aggregation(Current_Aggregation.Code, Tracer);

                // If this is all, save the new text as well.
                if (String.Compare("all", Current_Aggregation.Code, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    HttpContext.Current.Application["SobekCM_Home"] = form["sbkAghsw_HomeTextEdit"];
                }

                // Forward along
                currentMode.Aggregation_Type = Aggregation_Type_Enum.Home;
                string redirect_url = currentMode.Redirect_URL();
                if (redirect_url.IndexOf("?") > 0)
                    redirect_url = redirect_url + "&refresh=always";
                else
                    redirect_url = redirect_url + "?refresh=always";
                currentMode.Request_Completed = true;
                HttpContext.Current.Response.Redirect(redirect_url, false);
                HttpContext.Current.ApplicationInstance.CompleteRequest();

                return;
            }

            // If this is a search, verify it is a valid search type
            if (currentMode.Mode == Display_Mode_Enum.Search)
            {
                // Not every collection has every search type...
                ReadOnlyCollection<Search_Type_Enum> possibleSearches = base.Current_Aggregation.Search_Types;
                if (!possibleSearches.Contains(currentMode.Search_Type))
                {
                    bool found_valid = false;

                    if ((currentMode.Search_Type == Search_Type_Enum.Full_Text) && (possibleSearches.Contains(Search_Type_Enum.dLOC_Full_Text)))
                    {
                        found_valid = true;
                        currentMode.Search_Type = Search_Type_Enum.dLOC_Full_Text;
                    }

                    if ((!found_valid) && (currentMode.Search_Type == Search_Type_Enum.Basic) && (possibleSearches.Contains(Search_Type_Enum.Newspaper)))
                    {
                        found_valid = true;
                        currentMode.Search_Type = Search_Type_Enum.Newspaper;
                    }

                    if (( !found_valid ) && ( possibleSearches.Count > 0 ))
                    {
                        found_valid = true;
                        currentMode.Search_Type = possibleSearches[0];
                    }

                    if ( !found_valid )
                    {
                        currentMode.Mode = Display_Mode_Enum.Aggregation;
                        currentMode.Aggregation_Type = Aggregation_Type_Enum.Home;
                    }
                }
            }

            if (currentMode.Mode == Display_Mode_Enum.Search)
            {
                collectionViewer = AggregationViewer_Factory.Get_Viewer(currentMode.Search_Type, base.Current_Aggregation, currentMode, currentUser);
            }

            if (currentMode.Mode == Display_Mode_Enum.Aggregation)
            {
                switch (currentMode.Aggregation_Type)
                {
                    case Aggregation_Type_Enum.Home:
                    case Aggregation_Type_Enum.Home_Edit:
                        collectionViewer = AggregationViewer_Factory.Get_Viewer(base.Current_Aggregation.Views_And_Searches[0], base.Current_Aggregation, currentMode);
                        break;

                    case Aggregation_Type_Enum.Browse_Info:
                        if (resultsStatistics == null)
                        {
                            collectionViewer = new Static_Browse_Info_AggregationViewer(thisBrowseObject, thisStaticBrowseObject, Current_Aggregation, currentMode, Current_User);
                        }
                        else
                        {
                            collectionViewer = new DataSet_Browse_Info_AggregationViewer(thisBrowseObject, resultsStatistics, pagedResults, codeManager, itemList, currentUser);
                        }
                        break;

                    case Aggregation_Type_Enum.Child_Page_Edit:
                        collectionViewer = new Static_Browse_Info_AggregationViewer(thisBrowseObject, thisStaticBrowseObject, Current_Aggregation, currentMode, Current_User);
                        break;

                    case Aggregation_Type_Enum.Browse_By:
                        collectionViewer = new Metadata_Browse_AggregationViewer(Current_Mode, Current_Aggregation, Tracer);
                        break;

                    case Aggregation_Type_Enum.Browse_Map:
                        collectionViewer = new Map_Browse_AggregationViewer(Current_Mode, Current_Aggregation, Tracer);
                        break;

                    case Aggregation_Type_Enum.Browse_Map_Beta:
                        collectionViewer = new Map_Browse_AggregationViewer_Beta(Current_Mode, Current_Aggregation, Tracer);
                        break;

                    case Aggregation_Type_Enum.Item_Count:
                        collectionViewer = new Item_Count_AggregationViewer(Current_Mode, Current_Aggregation);
                        break;

                    case Aggregation_Type_Enum.Usage_Statistics:
                        collectionViewer = new Usage_Statistics_AggregationViewer(Current_Mode, Current_Aggregation);
                        break;

                    case Aggregation_Type_Enum.Private_Items:
                        collectionViewer = new Private_Items_AggregationViewer(Current_Mode, Current_Aggregation, Tracer);
                        break;
                }
            }

            // If execution should end, do it now
            if (currentMode.Request_Completed)
                return;

            if (collectionViewer != null)
            {
                collectionViewer.Translator = translator;
                collectionViewer.HTML_Skin = HTML_Skin;
                collectionViewer.CurrentMode = Current_Mode;
                collectionViewer.CurrentObject = Current_Aggregation;
                collectionViewer.Current_User = Current_User;

                // Pull the standard values
                switch (collectionViewer.Selection_Panel_Display)
                {
                    case Selection_Panel_Display_Enum.Selectable:
                        if (form["show_subaggrs"] != null)
                        {
                            string show_subaggrs = form["show_subaggrs"].ToUpper();
                            if (show_subaggrs == "TRUE")
                                currentMode.Show_Selection_Panel = true;
                        }
                        break;

                    case Selection_Panel_Display_Enum.Always:
                        currentMode.Show_Selection_Panel = true;
                        break;
                }
            }
        }
        /// <summary> Constructor for a new instance of the Edit_Item_Metadata_MySobekViewer class </summary>
        /// <param name="User"> Authenticated user information </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="All_Items_Lookup"> Allows individual items to be retrieved by various methods as <see cref="Single_Item"/> objects.</param>
        /// <param name="Current_Item"> Individual digital resource to be edited by the user </param>
        /// <param name="Code_Manager"> Code manager contains the list of all valid aggregation codes </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        public Edit_Item_Metadata_MySobekViewer(User_Object User,
                                                SobekCM_Navigation_Object Current_Mode, 
                                                Item_Lookup_Object All_Items_Lookup,
                                                SobekCM_Item Current_Item, Aggregation_Code_Manager Code_Manager,
                                                Dictionary<string, Wordmark_Icon> Icon_Table,
                                                SobekCM_Skin_Object HTML_Skin,
                                                Custom_Tracer Tracer)
            : base(User)
        {
            Tracer.Add_Trace("Edit_Item_Metadata_MySobekViewer.Constructor", String.Empty);

            currentMode = Current_Mode;
            item = Current_Item;
            itemList = All_Items_Lookup;
            codeManager = Code_Manager;
            iconList = Icon_Table;
            webSkin = HTML_Skin;
            popUpFormsHtml = String.Empty;

            // If the user cannot edit this item, go back
            if (!user.Can_Edit_This_Item( item ))
            {
                currentMode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                HttpContext.Current.Response.Redirect(currentMode.Redirect_URL());
            }

            // Is this a project
            isProject = false;
            if (item.Bib_Info.SobekCM_Type == TypeOfResource_SobekCM_Enum.Project )
                isProject = true;

            string template_code = user.Edit_Template_Code;
            if ((isProject) || (item.Contains_Complex_Content) || (item.Using_Complex_Template))
            {
                template_code = user.Edit_Template_MARC_Code;
            }
            template = Cached_Data_Manager.Retrieve_Template(template_code, Tracer);
            if (template != null)
            {
                Tracer.Add_Trace("Edit_Item_Metadata_MySobekViewer.Constructor", "Found template in cache");
            }
            else
            {
                Tracer.Add_Trace("Edit_Item_Metadata_MySobekViewer.Constructor", "Reading template file");

                // Read this template
                Template_XML_Reader reader = new Template_XML_Reader();
                template = new Template();
                reader.Read_XML( SobekCM_Library_Settings.Base_MySobek_Directory + "templates\\" + template_code + ".xml", template, true);

                // Add the current codes to this template
                template.Add_Codes(Code_Manager);

                // Save this into the cache
                Cached_Data_Manager.Store_Template(template_code, template, Tracer);
            }

            // Get the current page number, or default to 1
            page = 1;
            if (currentMode.My_Sobek_SubMode.Length > 0)
            {
                if ((currentMode.My_Sobek_SubMode == "preview") || (currentMode.My_Sobek_SubMode == "marc") || (currentMode.My_Sobek_SubMode == "mets"))
                {
                    page = 0;
                }
                else
                {
                    page = 1;
                    bool isNumber = currentMode.My_Sobek_SubMode.All(Char.IsNumber);
                    if (isNumber)
                    {
                        if (isProject)
                            Double.TryParse(currentMode.My_Sobek_SubMode[0].ToString(), out page);
                        else
                            Double.TryParse(currentMode.My_Sobek_SubMode, out page);
                    }
                    else if ( isProject )
                    {
                        if ( Char.IsNumber(currentMode.My_Sobek_SubMode[0]))
                            Double.TryParse(currentMode.My_Sobek_SubMode[0].ToString(), out page);
                    }
                }
            }
        }
        /// <summary> Constructor for a new instance of the New_Group_And_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="Current_Item"> Digital resource selected for file management </param>
        /// <param name="Item_List"> Allows individual items to be retrieved by various methods as <see cref="Single_Item"/> objects.</param>
        /// <param name="Code_Manager"> Code manager contains the list of all valid aggregation codes </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        public Page_Image_Upload_MySobekViewer(User_Object User,
                                             SobekCM_Navigation_Object Current_Mode,
                                             SobekCM_Item Current_Item,
                                             Item_Lookup_Object Item_List,
                                             Aggregation_Code_Manager Code_Manager,
                                             Dictionary<string, Wordmark_Icon> Icon_Table,
                                             SobekCM_Skin_Object HTML_Skin,
                                             Language_Support_Info Translator,
                                             Custom_Tracer Tracer)
            : base(User)
        {
            Tracer.Add_Trace("Page_Image_Upload_MySobekViewer.Constructor", String.Empty);

            // Save the parameters
            codeManager = Code_Manager;
            itemList = Item_List;
            iconList = Icon_Table;
            currentMode = Current_Mode;
            webSkin = HTML_Skin;
            this.validationErrors = validationErrors;
            base.Translator = Translator;
            item = Current_Item;

            // If the user cannot edit this item, go back
            if (!user.Can_Edit_This_Item(item))
            {
                currentMode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                currentMode.Redirect();
                return;
            }

            // Determine the in process directory for this
            digitalResourceDirectory = SobekCM_Library_Settings.In_Process_Submission_Location + "\\" + User.UserName.Replace(".", "").Replace("@", "") + "\\uploadimages\\" + Current_Item.METS_Header.ObjectID;
            if (User.ShibbID.Trim().Length > 0)
                digitalResourceDirectory = SobekCM_Library_Settings.In_Process_Submission_Location + "\\" + User.ShibbID + "\\uploadimages\\" + Current_Item.METS_Header.ObjectID;

            // Make the folder for the user in process directory
            if (!Directory.Exists(digitalResourceDirectory))
                Directory.CreateDirectory(digitalResourceDirectory);
            else
            {
                // Any post-processing to do?
                string[] files = Directory.GetFiles(digitalResourceDirectory);
                foreach (string thisFile in files)
                {
                    FileInfo thisFileInfo = new FileInfo(thisFile);
                    if ((thisFileInfo.Extension.ToUpper() == ".TIF") || (thisFileInfo.Extension.ToUpper() == ".TIFF"))
                    {
                        // Is there a JPEG and/or thumbnail?
                        string jpeg = digitalResourceDirectory + "\\" + thisFileInfo.Name.Replace(thisFileInfo.Extension, "") + ".jpg";
                        string jpeg_thumbnail = digitalResourceDirectory + "\\" + thisFileInfo.Name.Replace(thisFileInfo.Extension, "") + "thm.jpg";

                        // Is one missing?
                        if ((!File.Exists(jpeg)) || (!File.Exists(jpeg_thumbnail)))
                        {
                            try
                            {
                                var tiffImg = System.Drawing.Image.FromFile(thisFile);
                                var mainImg = ScaleImage(tiffImg, SobekCM_Library_Settings.JPEG_Width, SobekCM_Library_Settings.JPEG_Height);
                                mainImg.Save(jpeg, ImageFormat.Jpeg);
                                var thumbnailImg = ScaleImage(tiffImg, 150, 400);
                                thumbnailImg.Save(jpeg_thumbnail, ImageFormat.Jpeg);

                            }
                            catch (Exception)
                            {
                                bool error = true;
                            }
                        }
                    }
                }
            }

            // If this is post-back, handle it
            if (currentMode.isPostBack)
            {
                string[] getKeys = HttpContext.Current.Request.Form.AllKeys;
                string file_name_from_keys = String.Empty;
                string label_from_keys = String.Empty;
                foreach (string thisKey in getKeys)
                {
                    if (thisKey.IndexOf("upload_file") == 0)
                    {
                        file_name_from_keys = HttpContext.Current.Request.Form[thisKey];
                    }
                    if (thisKey.IndexOf("upload_label") == 0)
                    {
                        label_from_keys = HttpContext.Current.Request.Form[thisKey];
                    }
                    if ((file_name_from_keys.Length > 0) && (label_from_keys.Length > 0))
                    {
                        HttpContext.Current.Session["file_" + item.Web.ItemID + "_" + file_name_from_keys.Trim()] = label_from_keys.Trim();
                        file_name_from_keys = String.Empty;
                        label_from_keys = String.Empty;
                    }

                    if (thisKey == "url_input")
                    {
                        item.Bib_Info.Location.Other_URL = HttpContext.Current.Request.Form[thisKey];
                    }
                }

                string action = HttpContext.Current.Request.Form["action"];
                if (action == "delete")
                {
                    string filename = HttpContext.Current.Request.Form["phase"];
                    try
                    {
                        if (File.Exists(digitalResourceDirectory + "\\" + filename))
                            File.Delete(digitalResourceDirectory + "\\" + filename);

                        // Forward
                        currentMode.Redirect();
                        return;
                    }
                    catch
                    {
                        // Error was caught during attempted delete
                    }
                }

                if ( action == "next_phase")
                {
                    int phase = Convert.ToInt32(HttpContext.Current.Request.Form["phase"]);
                    switch( phase )
                    {
                        case 2:
                            // Clear all the file keys in the temporary folder
                            string[] allFiles = Directory.GetFiles(digitalResourceDirectory);
                            foreach (string thisFile in allFiles)
                            {
                                try
                                {
                                    File.Delete(thisFile);
                                }
                                catch
                                {
                                    // Do nothing - not a fatal problem
                                }
                            }

                            try
                            {
                                Directory.Delete(digitalResourceDirectory);
                            }
                            catch
                            {
                                // Do nothing - not a fatal problem
                            }

                            // Redirect to the item
                            currentMode.Mode = Display_Mode_Enum.Item_Display;
                            currentMode.Redirect();
                            break;

                        case 9:
                            if (!complete_item_submission(item, null))
                            {
                                // Also clear the item from the cache
                                Cached_Data_Manager.Remove_Digital_Resource_Object(item.BibID, item.VID, null);

                                // Redirect to the item
                                currentMode.Mode = Display_Mode_Enum.Item_Display;
                                currentMode.ViewerCode = "qc";
                                currentMode.Redirect();
                            }
                            break;
                    }
                }
            }
        }
        /// <summary> Constructor for a new instance of the Text_MainWriter class </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="Results_Statistics"> Information about the entire set of results for a search or browse </param>
        /// <param name="Paged_Results"> Single page of results for a search or browse, within the entire set </param>
        /// <param name="Browse_Object"> Object contains all the basic information about any browse or info display </param>
        /// <param name="Current_Item"> Current item to display </param>
        /// <param name="Current_Page"> Current page within the item</param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Current_User"> Currently logged on user </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="Item_List"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Stats_Date_Range"> Object contains the start and end dates for the statistical data in the database </param>
        /// <param name="Search_History"> List of recent searches performed against this digital library </param>
        /// <param name="Icon_Dictionary"> Dictionary of information about every wordmark/icon in this digital library, used to build the wordmarks subpage </param>
        /// <param name="Thematic_Headings"> Headings under which all the highlighted collections on the main home page are organized </param>
        /// <param name="Public_Folder"> Object contains the information about the public folder to display </param>
        /// <param name="Aggregation_Aliases"> List of all existing aliases for existing aggregations </param>
        /// <param name="Web_Skin_Collection"> Collection of all the web skins </param>
        /// <param name="Checked_Items"> List of all items which are currently checked out for single fair use and the IP address currently viewing the item</param>
        /// <param name="IP_Restrictions"> Any possible restriction on item access by IP ranges </param>
        /// <param name="URL_Portals"> List of all web portals into this system </param>
        /// <param name="Site_Map"> Optional site map object used to render a navigational tree-view on left side of static web content pages </param>
        /// <param name="Items_In_Title"> List of items within the current title ( used for the Item Group display )</param>
        /// <param name="Static_Web_Content"> HTML content-based browse, info, or imple CMS-style web content objects.  These are objects which are read from a static HTML file and much of the head information must be maintained </param>
        public Html_MainWriter(SobekCM_Navigation_Object Current_Mode,
            Item_Aggregation Hierarchy_Object,
            Search_Results_Statistics Results_Statistics,
            List<iSearch_Title_Result> Paged_Results,
            Item_Aggregation_Browse_Info Browse_Object,
            SobekCM_Item Current_Item,
            Page_TreeNode Current_Page,
            SobekCM_Skin_Object HTML_Skin,
            User_Object Current_User,
            Language_Support_Info Translator,
            Aggregation_Code_Manager Code_Manager,
            Item_Lookup_Object Item_List,
            Statistics_Dates Stats_Date_Range,
            Recent_Searches Search_History,
            Dictionary<string, Wordmark_Icon> Icon_Dictionary,
            List<Thematic_Heading> Thematic_Headings,
            Public_User_Folder Public_Folder,
            Dictionary<string, string> Aggregation_Aliases,
            SobekCM_Skin_Collection Web_Skin_Collection,
            Checked_Out_Items_List Checked_Items,
            IP_Restriction_Ranges IP_Restrictions,
            Portal_List URL_Portals,
            SobekCM_SiteMap Site_Map,
            SobekCM_Items_In_Title Items_In_Title,
            HTML_Based_Content Static_Web_Content )
            : base(Current_Mode, Hierarchy_Object, Results_Statistics, Paged_Results, Browse_Object,  Current_Item, Current_Page, Static_Web_Content)
        {
            // Save parameters
            htmlSkin = HTML_Skin;
            translator = Translator;
            codeManager = Code_Manager;
            itemList = Item_List;
            statsDateRange = Stats_Date_Range;
            searchHistory = Search_History;
            currentUser = Current_User;
            iconList = Icon_Dictionary;
            thematicHeadings = Thematic_Headings;
            publicFolder = Public_Folder;
            aggregationAliases = Aggregation_Aliases;
            webSkins = Web_Skin_Collection;
            checkedItems = Checked_Items;
            ipRestrictionInfo = IP_Restrictions;
            urlPortals = URL_Portals;
            siteMap = Site_Map;
            itemsInTitle = Items_In_Title;

            // Set some defaults
            finishPageInAddFinalHtmlMethod = false;

            // Handle basic events which may be fired by the internal header

            if (HttpContext.Current.Request.Form["internal_header_action"] != null)
            {
                // Pull the action value
                string internalHeaderAction = HttpContext.Current.Request.Form["internal_header_action"].Trim();

                // Was this to hide or show the header?
                if ((internalHeaderAction == "hide") || (internalHeaderAction == "show"))
                {
                    // Pull the current visibility from the session
                    bool shown = true;
                    if ((HttpContext.Current.Session["internal_header"] != null) && (HttpContext.Current.Session["internal_header"].ToString() == "hidden"))
                    {
                        shown = false;
                    }
                    if ((internalHeaderAction == "hide") && (shown))
                    {
                        HttpContext.Current.Session["internal_header"] = "hidden";
                        HttpContext.Current.Response.Redirect(currentMode.Redirect_URL(), true);
                    }
                    if ((internalHeaderAction == "show") && (!shown))
                    {
                        HttpContext.Current.Session["internal_header"] = "shown";
                        HttpContext.Current.Response.Redirect(currentMode.Redirect_URL(), true);
                    }
                }
            }
        }
        /// <summary> Constructor for a new instance of the New_Group_And_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="Current_Item"> Digital resource selected for file management </param>
        /// <param name="Item_List"> Allows individual items to be retrieved by various methods as <see cref="Single_Item"/> objects.</param>
        /// <param name="Code_Manager"> Code manager contains the list of all valid aggregation codes </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        public File_Management_MySobekViewer(User_Object User,
                                             SobekCM_Navigation_Object Current_Mode,
                                             SobekCM_Item Current_Item,
                                             Item_Lookup_Object Item_List,
                                             Aggregation_Code_Manager Code_Manager,
                                             Dictionary<string, Wordmark_Icon> Icon_Table,
                                             SobekCM_Skin_Object HTML_Skin,
                                             Language_Support_Info Translator,
                                             Custom_Tracer Tracer)
            : base(User)
        {
            Tracer.Add_Trace("File_Management_MySobekViewer.Constructor", String.Empty);

            // Save the parameters
            codeManager = Code_Manager;
            itemList = Item_List;
            iconList = Icon_Table;
            currentMode = Current_Mode;
            webSkin = HTML_Skin;
            this.validationErrors = validationErrors;
            base.Translator = Translator;
            item = Current_Item;
            digitalResourceDirectory = Current_Item.Source_Directory;

            // If the user cannot edit this item, go back
            if (!user.Can_Edit_This_Item(item))
            {
                currentMode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                HttpContext.Current.Response.Redirect(currentMode.Redirect_URL());
            }

            // If this is post-back, handle it
            if (currentMode.isPostBack)
            {
                string[] getKeys = HttpContext.Current.Request.Form.AllKeys;
                string file_name_from_keys = String.Empty;
                string label_from_keys = String.Empty;
                foreach (string thisKey in getKeys)
                {
                    if (thisKey.IndexOf("upload_file") == 0)
                    {
                        file_name_from_keys = HttpContext.Current.Request.Form[thisKey];
                    }
                    if (thisKey.IndexOf("upload_label") == 0)
                    {
                        label_from_keys = HttpContext.Current.Request.Form[thisKey];
                    }
                    if ((file_name_from_keys.Length > 0) && (label_from_keys.Length > 0))
                    {
                        HttpContext.Current.Session["file_" + item.Web.ItemID + "_" + file_name_from_keys.Trim()] = label_from_keys.Trim();
                        file_name_from_keys = String.Empty;
                        label_from_keys = String.Empty;
                    }

                    if (thisKey == "url_input")
                    {
                        item.Bib_Info.Location.Other_URL = HttpContext.Current.Request.Form[thisKey];
                    }
                }

                string action = HttpContext.Current.Request.Form["action"];
                if (action == "delete")
                {
                    string filename = HttpContext.Current.Request.Form["phase"];
                    try
                    {
                        if (File.Exists(digitalResourceDirectory + "\\" + filename))
                            File.Delete(digitalResourceDirectory + "\\" + filename);

                        // Forward
                        HttpContext.Current.Response.Redirect(currentMode.Redirect_URL());
                    }
                    catch
                    {
                        // Error was caught during attempted delete
                    }
                }

                if ( action == "next_phase")
                {
                    int phase = Convert.ToInt32(HttpContext.Current.Request.Form["phase"]);
                    switch( phase )
                    {
                        case 2:
                            // Clear all the file keys in the session state
                            List<string> keys = new List<string>();
                            foreach (string thisKey in HttpContext.Current.Session.Keys)
                            {
                                if (thisKey.IndexOf("file_" + item.Web.ItemID + "_") == 0)
                                    keys.Add(thisKey);
                            }
                            foreach (string thisKey in keys)
                            {
                                HttpContext.Current.Session.Remove(thisKey);
                            }

                            // Redirect to the item
                            currentMode.Mode = Display_Mode_Enum.Item_Display;
                            HttpContext.Current.Response.Redirect(currentMode.Redirect_URL());
                            break;

                        case 9:
                            if (!complete_item_submission(item, null))
                            {
                                // Clear all the file keys in the session state
                                List<string> keys2 = new List<string>();
                                foreach (string thisKey in HttpContext.Current.Session.Keys)
                                {
                                    if (thisKey.IndexOf("file_" + item.Web.ItemID + "_") == 0)
                                        keys2.Add(thisKey);
                                }
                                foreach (string thisKey in keys2)
                                {
                                    HttpContext.Current.Session.Remove(thisKey);
                                }

                                // Also clear the item from the cache
                                MemoryMgmt.Cached_Data_Manager.Remove_Digital_Resource_Object(item.BibID, item.VID, null);

                                // Redirect to the item
                                currentMode.Mode = Display_Mode_Enum.Item_Display;
                                HttpContext.Current.Response.Redirect(currentMode.Redirect_URL());
                            }
                            break;
                    }
                }
            }
        }
        /// <summary> Writes the static header to go at the top of the static digital resource page </summary>
        /// <param name="writer"> Open stream to write the HTML header to </param>
        /// <param name="htmlSkin"> Default html web skin/interface</param>
        public void Display_Header(TextWriter writer, SobekCM_Skin_Object htmlSkin)
        {
            string breadcrumbs = "<a href=\"" + currentMode.Base_URL + "\">UFDC Home</a>";

            writer.WriteLine(htmlSkin.Header_Item_HTML.Replace("<%URLOPTS%>", "").Replace("<%?URLOPTS%>", "").Replace("<%&URLOPTS%>", "").Replace("<%BREADCRUMBS%>", breadcrumbs).Replace("<%MYSOBEK%>", "").Replace("<%ENGLISH%>", "").Replace("<%FRENCH%>", "").Replace("<%SPANISH%>", "").Replace("<%LOWGRAPHICS%>", "").Replace("<%HIGHGRAPHICS%>", "").Replace("<%BASEURL%>", currentMode.Base_URL));
            writer.WriteLine(String.Empty);
        }
        /// <summary> Constructor for a new instance of the Text_MainWriter class </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="Results_Statistics"> Information about the entire set of results for a search or browse </param>
        /// <param name="Paged_Results"> Single page of results for a search or browse, within the entire set </param>
        /// <param name="Browse_Object"> Object contains all the basic information about any browse or info display </param>
        /// <param name="Current_Item"> Current item to display </param>
        /// <param name="Current_Page"> Current page within the item</param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Current_User"> Currently logged on user </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="Item_List"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Stats_Date_Range"> Object contains the start and end dates for the statistical data in the database </param>
        /// <param name="Search_History"> List of recent searches performed against this digital library </param>
        /// <param name="Icon_Dictionary"> Dictionary of information about every wordmark/icon in this digital library, used to build the wordmarks subpage </param>
        /// <param name="Thematic_Headings"> Headings under which all the highlighted collections on the main home page are organized </param>
        /// <param name="Public_Folder"> Object contains the information about the public folder to display </param>
        /// <param name="Aggregation_Aliases"> List of all existing aliases for existing aggregations </param>
        /// <param name="Web_Skin_Collection"> Collection of all the web skins </param>
        /// <param name="Checked_Items"> List of all items which are currently checked out for single fair use and the IP address currently viewing the item</param>
        /// <param name="IP_Restrictions"> Any possible restriction on item access by IP ranges </param>
        /// <param name="URL_Portals"> List of all web portals into this system </param>
        /// <param name="Site_Map"> Optional site map object used to render a navigational tree-view on left side of static web content pages </param>
        /// <param name="Items_In_Title"> List of items within the current title ( used for the Item Group display )</param>
        /// <param name="Static_Web_Content"> HTML content-based browse, info, or imple CMS-style web content objects.  These are objects which are read from a static HTML file and much of the head information must be maintained </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public Html_MainWriter(SobekCM_Navigation_Object Current_Mode,
            Item_Aggregation Hierarchy_Object,
            Search_Results_Statistics Results_Statistics,
            List<iSearch_Title_Result> Paged_Results,
            Item_Aggregation_Child_Page Browse_Object,
            SobekCM_Item Current_Item,
            Page_TreeNode Current_Page,
            SobekCM_Skin_Object HTML_Skin,
            User_Object Current_User,
            Language_Support_Info Translator,
            Aggregation_Code_Manager Code_Manager,
            Item_Lookup_Object Item_List,
            Statistics_Dates Stats_Date_Range,
            Recent_Searches Search_History,
            Dictionary<string, Wordmark_Icon> Icon_Dictionary,
            List<Thematic_Heading> Thematic_Headings,
            Public_User_Folder Public_Folder,
            Dictionary<string, string> Aggregation_Aliases,
            SobekCM_Skin_Collection Web_Skin_Collection,
            Checked_Out_Items_List Checked_Items,
            IP_Restriction_Ranges IP_Restrictions,
            Portal_List URL_Portals,
            SobekCM_SiteMap Site_Map,
            SobekCM_Items_In_Title Items_In_Title,
            HTML_Based_Content Static_Web_Content,
            Custom_Tracer Tracer )
            : base(Current_Mode, Hierarchy_Object, Results_Statistics, Paged_Results, Browse_Object,  Current_Item, Current_Page, Static_Web_Content)
        {
            // Save parameters
            htmlSkin = HTML_Skin;
            translator = Translator;
            codeManager = Code_Manager;
            itemList = Item_List;
            statsDateRange = Stats_Date_Range;
            searchHistory = Search_History;
            currentUser = Current_User;
            iconList = Icon_Dictionary;
            thematicHeadings = Thematic_Headings;
            publicFolder = Public_Folder;
            aggregationAliases = Aggregation_Aliases;
            webSkins = Web_Skin_Collection;
            checkedItems = Checked_Items;
            ipRestrictionInfo = IP_Restrictions;
            urlPortals = URL_Portals;
            siteMap = Site_Map;
            itemsInTitle = Items_In_Title;

            // Set some defaults

            // Handle basic events which may be fired by the internal header
            if (HttpContext.Current.Request.Form["internal_header_action"] != null)
            {
                // Pull the action value
                string internalHeaderAction = HttpContext.Current.Request.Form["internal_header_action"].Trim();

                // Was this to hide or show the header?
                if ((internalHeaderAction == "hide") || (internalHeaderAction == "show"))
                {
                    // Pull the current visibility from the session
                    bool shown = !((HttpContext.Current.Session["internal_header"] != null) && (HttpContext.Current.Session["internal_header"].ToString() == "hidden"));
                    if ((internalHeaderAction == "hide") && (shown))
                    {
                        HttpContext.Current.Session["internal_header"] = "hidden";
                        currentMode.Redirect();
                        return;
                    }
                    if ((internalHeaderAction == "show") && (!shown))
                    {
                        HttpContext.Current.Session["internal_header"] = "shown";
                        currentMode.Redirect();
                        return;
                    }
                }
            }

            try
            {

                // Create the html sub writer now
                switch (Current_Mode.Mode)
                {
                    case Display_Mode_Enum.Internal:
                        subwriter = new Internal_HtmlSubwriter(iconList, currentUser, codeManager);
                        break;

                    case Display_Mode_Enum.Statistics:
                        subwriter = new Statistics_HtmlSubwriter(searchHistory, codeManager, statsDateRange);
                        break;

                    case Display_Mode_Enum.Preferences:
                        subwriter = new Preferences_HtmlSubwriter(currentMode);
                        break;

                    case Display_Mode_Enum.Error:
                        subwriter = new Error_HtmlSubwriter(false);
                        // Send the email now
                        if (currentMode.Caught_Exception != null)
                        {
                            if (currentMode.Error_Message.Length == 0)
                                currentMode.Error_Message = "Unknown exception caught";
                            Email_Information(currentMode.Error_Message, currentMode.Caught_Exception, Tracer, false);
                        }
                        break;

                    case Display_Mode_Enum.Legacy_URL:
                        subwriter = new LegacyUrl_HtmlSubwriter();
                        break;

                    case Display_Mode_Enum.Item_Print:
                        subwriter = new Print_Item_HtmlSubwriter(currentItem, codeManager, translator, currentMode);
                        break;

                    case Display_Mode_Enum.Contact:

                        StringBuilder builder = new StringBuilder();
                        builder.Append("\n\nSUBMISSION INFORMATION\n");
                        builder.Append("\tDate:\t\t\t\t" + DateTime.Now.ToString() + "\n");
                        string lastMode = String.Empty;
                        try
                        {
                            if (HttpContext.Current.Session["Last_Mode"] != null)
                                lastMode = HttpContext.Current.Session["Last_Mode"].ToString();
                            builder.Append("\tIP Address:\t\t\t" + HttpContext.Current.Request.UserHostAddress + "\n");
                            builder.Append("\tHost Name:\t\t\t" + HttpContext.Current.Request.UserHostName + "\n");
                            builder.Append("\tBrowser:\t\t\t" + HttpContext.Current.Request.Browser.Browser + "\n");
                            builder.Append("\tBrowser Platform:\t\t" + HttpContext.Current.Request.Browser.Platform + "\n");
                            builder.Append("\tBrowser Version:\t\t" + HttpContext.Current.Request.Browser.Version + "\n");
                            builder.Append("\tBrowser Language:\t\t");
                            bool first = true;
                            string[] languages = HttpContext.Current.Request.UserLanguages;
                            if (languages != null)
                                foreach (string thisLanguage in languages)
                                {
                                    if (first)
                                    {
                                        builder.Append(thisLanguage);
                                        first = false;
                                    }
                                    else
                                    {
                                        builder.Append(", " + thisLanguage);
                                    }
                                }

                            builder.Append("\n\nHISTORY\n");
                            if (HttpContext.Current.Session["LastSearch"] != null)
                                builder.Append("\tLast Search:\t\t" + HttpContext.Current.Session["LastSearch"] + "\n");
                            if (HttpContext.Current.Session["LastResults"] != null)
                                builder.Append("\tLast Results:\t\t" + HttpContext.Current.Session["LastResults"] + "\n");
                            if (HttpContext.Current.Session["Last_Mode"] != null)
                                builder.Append("\tLast Mode:\t\t\t" + HttpContext.Current.Session["Last_Mode"] + "\n");
                            builder.Append("\tURL:\t\t\t\t" + HttpContext.Current.Items["Original_URL"]);
                        }
                        catch
                        {

                        }
                        subwriter = new Contact_HtmlSubwriter(lastMode, builder.ToString(), currentMode, hierarchyObject);
                        break;

                    case Display_Mode_Enum.Contact_Sent:
                        subwriter = new Contact_HtmlSubwriter(String.Empty, String.Empty, currentMode, hierarchyObject);
                        break;

                    case Display_Mode_Enum.Simple_HTML_CMS:
                        subwriter = new Web_Content_HtmlSubwriter(hierarchyObject, currentMode, htmlSkin, htmlBasedContent, siteMap);
                        break;

                    case Display_Mode_Enum.My_Sobek:
                        subwriter = new MySobek_HtmlSubwriter(results_statistics, paged_results, codeManager, itemList, hierarchyObject, htmlSkin, translator, currentMode, currentItem, currentUser, iconList, statsDateRange, webSkins, Tracer);
                        break;

                    case Display_Mode_Enum.Administrative:
                        subwriter = new Admin_HtmlSubwriter(codeManager, itemList, hierarchyObject, htmlSkin, translator, currentMode, aggregationAliases, webSkins, currentUser, ipRestrictionInfo, iconList, urlPortals, thematicHeadings, Tracer);
                        break;

                    case Display_Mode_Enum.Results:
                        subwriter = new Search_Results_HtmlSubwriter(results_statistics, paged_results, codeManager, translator, itemList, currentUser);
                        break;

                    case Display_Mode_Enum.Public_Folder:
                        subwriter = new Public_Folder_HtmlSubwriter(results_statistics, paged_results, codeManager, translator, itemList, currentUser, publicFolder);
                        break;

                    case Display_Mode_Enum.Search:
                    case Display_Mode_Enum.Aggregation:
                        subwriter = new Aggregation_HtmlSubwriter(hierarchyObject, currentMode, htmlSkin, translator, thisBrowseObject, results_statistics, paged_results, codeManager, itemList, thematicHeadings, currentUser, htmlBasedContent, Tracer);
                        break;

                    case Display_Mode_Enum.Item_Display:
                        if ((!currentMode.Invalid_Item) && (currentItem != null))
                        {
                            bool show_toc = false;
                            if (HttpContext.Current.Session["Show TOC"] != null)
                            {
                                Boolean.TryParse(HttpContext.Current.Session["Show TOC"].ToString(), out show_toc);
                            }

                            // Check that this item is not checked out by another user
                            bool itemCheckedOutByOtherUser = false;
                            if (currentItem.Behaviors.CheckOut_Required)
                            {
                                if (!checkedItems.Check_Out(currentItem.Web.ItemID, HttpContext.Current.Request.UserHostAddress))
                                {
                                    itemCheckedOutByOtherUser = true;
                                }
                            }

                            // Check to see if this is IP restricted
                            string restriction_message = String.Empty;
                            if (currentItem.Behaviors.IP_Restriction_Membership > 0)
                            {
                                if (HttpContext.Current != null)
                                {
                                    int user_mask = (int)HttpContext.Current.Session["IP_Range_Membership"];
                                    int comparison = currentItem.Behaviors.IP_Restriction_Membership & user_mask;
                                    if (comparison == 0)
                                    {
                                        int restriction = currentItem.Behaviors.IP_Restriction_Membership;
                                        int restriction_counter = 0;
                                        while (restriction % 2 != 1)
                                        {
                                            restriction = restriction >> 1;
                                            restriction_counter++;
                                        }
                                        restriction_message = ipRestrictionInfo[restriction_counter].Item_Restricted_Statement;
                                    }
                                }
                            }

                            // Create the item viewer writer
                            subwriter = new Item_HtmlSubwriter(currentItem, currentPage, currentUser, codeManager, translator, show_toc, (SobekCM_Library_Settings.JP2ServerUrl.Length > 0), currentMode, hierarchyObject, restriction_message, itemsInTitle, Tracer);
                            ((Item_HtmlSubwriter)subwriter).Item_Checked_Out_By_Other_User = itemCheckedOutByOtherUser;
                        }
                        else
                        {
                            // Create the invalid item html subwrite and write the HTML
                            subwriter = new Error_HtmlSubwriter(true);
                        }
                        break;

                }
            }
            catch (Exception ee)
            {
                // Send to the dashboard
                if ((HttpContext.Current.Request.UserHostAddress == "127.0.0.1") || (HttpContext.Current.Request.UserHostAddress == HttpContext.Current.Request.ServerVariables["LOCAL_ADDR"]) || (HttpContext.Current.Request.Url.ToString().IndexOf("localhost") >= 0))
                {
                    Tracer.Add_Trace("Html_MainWriter.Constructor", "Exception caught!", Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Html_MainWriter.Constructor", ee.Message, Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Html_MainWriter.Constructor", ee.StackTrace, Custom_Trace_Type_Enum.Error);

                    // Wrap this into the SobekCM Exception
                    SobekCM_Traced_Exception newException = new SobekCM_Traced_Exception("Exception caught while building the mode-specific HTML Subwriter", ee, Tracer);

                    // Save this to the session state, and then forward to the dashboard
                    HttpContext.Current.Session["Last_Exception"] = newException;
                    HttpContext.Current.Response.Redirect("dashboard.aspx", false);
                    Current_Mode.Request_Completed = true;

                    return;
                }
                else
                {
                    subwriter = new Error_HtmlSubwriter(false);
                }
            }

            if (subwriter != null)
            {
                subwriter.Mode = currentMode;
                subwriter.Skin = htmlSkin;
                subwriter.Current_Aggregation = hierarchyObject;
            }
        }
        public void Set_Main_Writer()
        {
            // Load the html writer
            string current_skin_code = currentMode.Skin.ToUpper();
            if ((currentMode.Writer_Type == Writer_Type_Enum.HTML) || (currentMode.Writer_Type == Writer_Type_Enum.HTML_LoggedIn))
            {
                // Check if a different skin should be used if this is an item display
                if ((currentMode.Mode == Display_Mode_Enum.Item_Display) || (currentMode.Mode == Display_Mode_Enum.Item_Print))
                {
                    if ((currentItem != null) && (currentItem.Behaviors.Web_Skin_Count > 0))
                    {
                        if (!currentItem.Behaviors.Web_Skins.Contains(current_skin_code))
                        {
                            string new_skin_code = currentItem.Behaviors.Web_Skins[0];
                            current_skin_code = new_skin_code;
                        }
                    }
                }

                // Check if a differente skin should be used if this is a collection display
                if ((hierarchyObject != null) && (hierarchyObject.Web_Skins.Count > 0))
                {
                    if (!hierarchyObject.Web_Skins.Contains(current_skin_code.ToLower()))
                    {
                        current_skin_code = hierarchyObject.Web_Skins[0];
                    }
                }

                SobekCM_Assistant assistant = new SobekCM_Assistant();

                // Try to get the web skin from the cache or skin collection, otherwise build it
                htmlSkin = assistant.Get_HTML_Skin(current_skin_code, currentMode, Global.Skins, true, tracer);

                // If there was no web skin returned, forward user to URL with no web skin.
                // This happens if the web skin code is invalid.  If a robot, just return a bad request
                // value though.
                if (htmlSkin == null)
                {
                    if ((currentMode == null) || (currentMode.Is_Robot))
                    {
                        HttpContext.Current.Response.StatusCode = 404;
                        HttpContext.Current.Response.Output.WriteLine("404 - INVALID URL");
                        HttpContext.Current.ApplicationInstance.CompleteRequest();
                        currentMode.Request_Completed = true;
                    }
                    else
                    {
                        currentMode.Skin = String.Empty;
                        currentMode.Redirect();
                        return;
                    }

                    return;
                }

                mainWriter = new Html_MainWriter(currentMode, hierarchyObject, searchResultStatistics, pagedSearchResults, thisBrowseObject,
                                                 currentItem, currentPage, htmlSkin, currentUser, Global.Translation, Global.Codes,
                                                 Global.Item_List, Global.Stats_Date_Range,
                                                 Global.Search_History, Global.Icon_List, Global.Thematic_Headings, publicFolder, Global.Collection_Aliases, Global.Skins, Global.Checked_List,
                                                 Global.IP_Restrictions, Global.URL_Portals, siteMap, itemsInTitle, staticWebContent, tracer);
            }

            // Load the OAI writer
            if (currentMode.Writer_Type == Writer_Type_Enum.OAI)
            {
                mainWriter = new Oai_MainWriter(HttpContext.Current.Request.QueryString, Global.Item_List);
            }

            // Load the DataSet writer
            if (currentMode.Writer_Type == Writer_Type_Enum.DataSet)
            {
                mainWriter = new Dataset_MainWriter(currentMode, hierarchyObject, searchResultStatistics, pagedSearchResults, thisBrowseObject, currentItem, currentPage);
            }

            // Load the DataProvider writer
            if (currentMode.Writer_Type == Writer_Type_Enum.Data_Provider)
            {
                mainWriter = new DataProvider_MainWriter(currentMode, hierarchyObject, searchResultStatistics, pagedSearchResults, thisBrowseObject, currentItem, currentPage);
            }

            // Load the XML writer
            if (currentMode.Writer_Type == Writer_Type_Enum.XML)
            {
                mainWriter = new Xml_MainWriter(currentMode, hierarchyObject, searchResultStatistics, pagedSearchResults, thisBrowseObject, currentItem, currentPage);
            }

            // Load the JSON writer
            if (currentMode.Writer_Type == Writer_Type_Enum.JSON)
            {
                mainWriter = new Json_MainWriter(currentMode, hierarchyObject, searchResultStatistics, pagedSearchResults, thisBrowseObject, currentItem, currentPage, Global.Item_List, SobekCM_Library_Settings.Image_URL);
            }

            // Load the HTML ECHO writer
            if (currentMode.Writer_Type == Writer_Type_Enum.HTML_Echo)
            {
                mainWriter = new Html_Echo_MainWriter(currentMode, browse_info_display_text);
            }

            // Default to HTML
            if (mainWriter == null)
            {
                SobekCM_Assistant assistant = new SobekCM_Assistant();
                htmlSkin = assistant.Get_HTML_Skin(currentMode, Global.Skins, true, tracer);

                mainWriter = new Html_MainWriter(currentMode, hierarchyObject, searchResultStatistics, pagedSearchResults, thisBrowseObject,
                                                 currentItem, currentPage, htmlSkin, currentUser, Global.Translation, Global.Codes,
                                                 Global.Item_List,
                                                 Global.Stats_Date_Range, Global.Search_History, Global.Icon_List, Global.Thematic_Headings, publicFolder,
                                                 Global.Collection_Aliases, Global.Skins, Global.Checked_List, Global.IP_Restrictions, Global.URL_Portals, siteMap, itemsInTitle, staticWebContent, tracer);
            }
        }
        /// <summary> Builds a specific <see cref="SobekCM_Skin_Object"/> when needed by a user's request </summary>
        /// <param name="Skin_Row"> Row from a database query with basic information about the interface to build ( codes, override flags, banner link )</param>
        /// <param name="Language_Code"> Code for the language, which determines which HTML to use </param>
        /// <returns> Completely built HTML interface object </returns>
        /// <remarks> The datarow for this method is retrieved from the database by calling the <see cref="Database.SobekCM_Database.Get_All_Web_Skins"/> method during
        /// application startup and is then stored in the <see cref="SobekCM_Skin_Collection"/> class until needed. </remarks>
        public static SobekCM_Skin_Object Build_Skin(DataRow Skin_Row, string Language_Code)
        {
            // Pull values out from this row
            string code            = Skin_Row["WebSkinCode"].ToString();
            string base_interface  = Skin_Row["BaseInterface"].ToString();
            bool   override_banner = Convert.ToBoolean(Skin_Row["OverrideBanner"]);
            string banner_link     = Skin_Row["BannerLink"].ToString();
            string this_style      = "design/skins/" + code + "/" + code + ".css";

            if (!File.Exists(SobekCM_Library_Settings.Base_Design_Location + "skins\\" + code + "\\" + code + ".css"))
            {
                this_style = String.Empty;
            }

            // Build the interface, along with any overriding banner
            SobekCM_Skin_Object thisInterface;

            if (override_banner)
            {
                string this_banner = String.Empty;

                // Find the LANGUAGE-SPECIFIC high-bandwidth banner image
                string[] banner_file = Directory.GetFiles(SobekCM_Library_Settings.Base_Design_Location + "skins/" + code, "banner_" + Language_Code + ".*");
                if (banner_file.Length > 0)
                {
                    if (banner_link.Length > 0)
                    {
                        this_banner = "<a href=\"" + banner_link + "\"><img border=\"0\" src=\"<%BASEURL%>skins/" + code + "/" + (new FileInfo(banner_file[0]).Name) + "\" alt=\"MISSING BANNER\" /></a>";
                    }
                    else
                    {
                        this_banner = "<img border=\"0\" src=\"<%BASEURL%>skins/" + code + "/" + (new FileInfo(banner_file[0]).Name) + "\" alt=\"MISSING BANNER\" />";
                    }
                }

                // If nothing was gotten, look for the ENGLISH banner image and use that
                if ((this_banner.Length == 0) && (Language_Code.Length > 0) && (Language_Code != "en"))
                {
                    banner_file = Directory.GetFiles(SobekCM_Library_Settings.Base_Design_Location + "skins/" + code, "banner.*");
                    if (banner_file.Length > 0)
                    {
                        if (banner_link.Length > 0)
                        {
                            this_banner = "<a href=\"" + banner_link + "\"><img border=\"0\" src=\"<%BASEURL%>design/skins/" + code + "/" + (new FileInfo(banner_file[0]).Name) + "\" alt=\"MISSING BANNER\" /></a>";
                        }
                        else
                        {
                            this_banner = "<img border=\"0\" src=\"<%BASEURL%>design/skins/" + code + "/" + (new FileInfo(banner_file[0]).Name) + "\" alt=\"MISSING BANNER\" />";
                        }
                    }
                }

                // Create this interface
                thisInterface = new SobekCM_Skin_Object(code, base_interface, this_style, this_banner);
            }
            else
            {
                // Create an interface without banner override
                thisInterface = new SobekCM_Skin_Object(code, base_interface, this_style);
            }

            // Assign the value to suppress top-level navigation
            thisInterface.Suppress_Top_Navigation = Convert.ToBoolean(Skin_Row["SuppressTopNavigation"]);

            // Assign the header and footer, or pass in the source
            string this_header;
            string this_footer;
            string this_item_header;
            string this_item_footer;

            // If the language isn't english, prepare to default to english
            if ((Language_Code.Length > 0) && (Language_Code != "en"))
            {
                // Assign the default locations for the banners
                this_header      = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header_" + Language_Code + ".html";
                this_footer      = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer_" + Language_Code + ".html";
                this_item_header = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header_item_" + Language_Code + ".html";
                this_item_footer = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer_item_" + Language_Code + ".html";

                if (!File.Exists(this_header))
                {
                    this_header = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header.html";
                }

                if (!File.Exists(this_footer))
                {
                    this_footer = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer.html";
                }

                if (!File.Exists(this_item_header))
                {
                    this_item_header = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header_item.html";
                }

                if (!File.Exists(this_item_footer))
                {
                    this_item_footer = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer_item.html";
                }
            }
            else
            {
                // Assign the default locations for the banners
                this_header      = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header.html";
                this_footer      = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer.html";
                this_item_header = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header_item.html";
                this_item_footer = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer_item.html";
            }

            // If the item specific stuff doesn't exist, use the regular
            if (!File.Exists(this_item_header))
            {
                this_item_header = this_header;
            }
            if (!File.Exists(this_item_footer))
            {
                this_item_footer = this_footer;
            }

            // Now, assign all of these
            thisInterface.Set_Header_Footer_Source(this_header, this_footer, this_item_header, this_item_footer);

            // Save the banner override and language code
            thisInterface.Override_Banner = override_banner;
            thisInterface.Language_Code   = Language_Code;

            // Return the built interface
            return(thisInterface);
        }
        /// <summary> Constructor for a new instance of the Admin_HtmlSubwriter class </summary>
        /// <param name="Results_Statistics"> Information about the entire set of results for a browse of a user's bookshelf folder </param>
        /// <param name="Paged_Results"> Single page of results for a browse of a user's bookshelf folder, within the entire set </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Current_Item">Current item to edit, if the user is requesting to edit an item</param>
        /// <param name="Aggregation_Aliases"> List of all existing aliases for existing aggregations </param>
        /// <param name="Web_Skin_Collection"> Collection of all the web skins </param>
        /// <param name="Current_User"> Currently logged on user </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="IP_Restrictions"> List of all IP Restriction ranges in use by this digital library </param>
        /// <param name="URL_Portals"> List of all web portals into this system </param>
        /// <param name="Stats_Date_Range"> Object contains the start and end dates for the statistical data in the database </param>
        /// <param name="Thematic_Headings"> Headings under which all the highlighted collections on the home page are organized </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public Admin_HtmlSubwriter(Search_Results_Statistics Results_Statistics,
                                     List<iSearch_Title_Result> Paged_Results,
                                     Aggregation_Code_Manager Code_Manager,
                                     Item_Lookup_Object All_Items_Lookup,
                                     Item_Aggregation Hierarchy_Object,
                                     SobekCM_Skin_Object HTML_Skin,
                                     Language_Support_Info Translator,
                                     SobekCM_Navigation_Object Current_Mode,
                                     SobekCM_Item Current_Item,
                                     Dictionary<string,string> Aggregation_Aliases,
                                     SobekCM_Skin_Collection Web_Skin_Collection,
                                     User_Object Current_User,
                                     IP_Restriction_Ranges IP_Restrictions,
                                     Dictionary<string, Wordmark_Icon> Icon_Table,
                                     Portal_List URL_Portals,
                                     Statistics_Dates Stats_Date_Range,
                                     List<Thematic_Heading> Thematic_Headings,
                                     Custom_Tracer Tracer )
        {
            Tracer.Add_Trace("Admin_HtmlSubwriter.Constructor", "Saving values and geting user object back from the session");

            resultsStatistics = Results_Statistics;
            pagedResults = Paged_Results;
            codeManager = Code_Manager;
            itemList = All_Items_Lookup;
            htmlSkin = HTML_Skin;
            translator = Translator;
            currentCollection = Hierarchy_Object;
            currentItem = Current_Item;
            user = Current_User;
            ipRestrictions = IP_Restrictions;
            iconTable = Icon_Table;
            statsDates = Stats_Date_Range;

            if (Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Log_Out)
            {
                Tracer.Add_Trace("Admin_HtmlSubwriter.Constructor", "Performing logout");

                HttpContext.Current.Session["user"] = null;
                HttpContext.Current.Response.Redirect("?");
            }

            if ((Current_Mode.My_Sobek_Type != My_Sobek_Type_Enum.Logon) && (user != null) && (user.Is_Temporary_Password))
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.New_Password;
            }

            if (Current_Mode.Logon_Required)
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Logon;

            // If the user is not an admin, and admin was selected, reroute this
            if ((!Current_User.Is_System_Admin) && (!Current_User.Is_Portal_Admin))
            {
                Current_Mode.Mode = Display_Mode_Enum.My_Sobek;
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                Current_Mode.My_Sobek_SubMode = String.Empty;
                HttpContext.Current.Response.Redirect(Current_Mode.Redirect_URL());
            }

            Tracer.Add_Trace("Admin_HtmlSubwriter.Constructor", "Building the my sobek viewer object");
            switch (Current_Mode.Admin_Type)
            {
                case Admin_Type_Enum.Aggregation_Single:
                    adminViewer = new Aggregation_Single_AdminViewer(user, Current_Mode, codeManager, Thematic_Headings, Web_Skin_Collection, Tracer);
                    break;

                case Admin_Type_Enum.Home:
                    adminViewer = new Home_AdminViewer(user, Current_Mode, Tracer);
                    break;

                case Admin_Type_Enum.Builder_Status:
                    adminViewer = new Builder_AdminViewer(user, Current_Mode);
                    break;

                case Admin_Type_Enum.Interfaces:
                    adminViewer = new Skins_AdminViewer(user, Current_Mode, Web_Skin_Collection, Tracer);
                    break;

                case Admin_Type_Enum.Forwarding:
                    adminViewer = new Aliases_AdminViewer(user, Current_Mode, Aggregation_Aliases, Tracer);
                    break;

                case Admin_Type_Enum.Wordmarks:
                    adminViewer = new Wordmarks_AdminViewer(user, Current_Mode, Tracer);
                    break;

                case Admin_Type_Enum.URL_Portals:
                    adminViewer = new Portals_AdminViewer(user, Current_Mode, URL_Portals, Tracer);
                    break;

                case Admin_Type_Enum.Users:
                    adminViewer = new Users_AdminViewer(user, Current_Mode, codeManager, Tracer);
                    break;

                case Admin_Type_Enum.User_Groups:
                    adminViewer = new User_Group_AdminViewer(user, Current_Mode, codeManager, Tracer);
                    break;

                case Admin_Type_Enum.Aggregations_Mgmt:
                    adminViewer = new Aggregations_Mgmt_AdminViewer(user, Current_Mode, codeManager, Tracer);
                    break;

                case Admin_Type_Enum.IP_Restrictions:
                    adminViewer = new IP_Restrictions_AdminViewer(user, Current_Mode, ipRestrictions, Tracer);
                    break;

                case Admin_Type_Enum.Thematic_Headings:
                    adminViewer = new Thematic_Headings_AdminViewer(user, Current_Mode, Thematic_Headings, Tracer);
                    break;

                case Admin_Type_Enum.Settings:
                    adminViewer = new Settings_AdminViewer(user, Current_Mode, Tracer);
                    break;

                case Admin_Type_Enum.Projects:
                    if (Current_Mode.My_Sobek_SubMode.Length > 1)
                    {
                        string project_code = Current_Mode.My_Sobek_SubMode.Substring(1);
                        Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Checking cache for valid project file");
                        if (user != null)
                        {
                            SobekCM_Item projectObject = Cached_Data_Manager.Retrieve_Project(user.UserID, project_code, Tracer);
                            if (projectObject != null)
                            {
                                Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Valid project file found in cache");
                                adminViewer = new Edit_Item_Metadata_MySobekViewer(user, Current_Mode, itemList, projectObject, codeManager, iconTable, htmlSkin, Tracer);
                            }
                            else
                            {
                                if (SobekCM_Database.Get_All_Projects_Templates(Tracer).Tables[0].Select("ProjectCode='" + project_code + "'").Length > 0)
                                {
                                    Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Building project file from (possible) PMETS");
                                    string pmets_file = SobekCM_Library_Settings.Base_MySobek_Directory + "projects\\" + Current_Mode.My_Sobek_SubMode.Substring(1) + ".pmets";
                                    SobekCM_Item pmets_item = File.Exists(pmets_file) ? SobekCM_Item.Read_METS(pmets_file) : new SobekCM_Item();
                                    pmets_item.Bib_Info.Main_Title.Title = "Project level metadata for '" + project_code + "'";
                                    pmets_item.Bib_Info.SobekCM_Type = TypeOfResource_SobekCM_Enum.Project;
                                    pmets_item.BibID = project_code.ToUpper();
                                    pmets_item.VID = "00001";
                                    pmets_item.Source_Directory = SobekCM_Library_Settings.Base_MySobek_Directory +  "projects\\";

                                    Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Adding project file to cache");

                                    Cached_Data_Manager.Store_Project(user.UserID, project_code, pmets_item, Tracer);

                                    adminViewer = new Edit_Item_Metadata_MySobekViewer(user, Current_Mode, itemList, pmets_item, codeManager, iconTable, htmlSkin, Tracer);
                                }
                            }
                        }
                    }

                    if (adminViewer == null)
                        adminViewer = new Projects_AdminViewer(user, Current_Mode, Tracer);
                    break;
            }

            // Pass in the navigation and translator information
            adminViewer.CurrentMode = Current_Mode;
            adminViewer.Translator = translator;
        }
        /// <summary> Constructor for a new instance of the New_Group_And_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="Item_List"> Allows individual items to be retrieved by various methods as <see cref="Single_Item"/> objects.</param>
        /// <param name="Code_Manager"> Code manager contains the list of all valid aggregation codes </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        public New_Group_And_Item_MySobekViewer(User_Object User, 
                                                SobekCM_Navigation_Object Current_Mode, Item_Lookup_Object Item_List,
                                                Aggregation_Code_Manager Code_Manager,
                                                Dictionary<string, Wordmark_Icon> Icon_Table,
                                                SobekCM_Skin_Object HTML_Skin,
                                                Language_Support_Info Translator,
                                                Custom_Tracer Tracer)
            : base(User)
        {
            Tracer.Add_Trace("New_Group_And_Item_MySobekViewer.Constructor", String.Empty);

            // Save the parameters
            currentMode = Current_Mode;
            codeManager = Code_Manager;
            iconList = Icon_Table;
            webSkin = HTML_Skin;
            base.Translator = Translator;

            // If the user cannot submit items, go back
            if (!user.Can_Submit)
            {
                currentMode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                HttpContext.Current.Response.Redirect(currentMode.Redirect_URL());
            }
            itemList = Item_List;

            // Determine the in process directory for this
            if (user.UFID.Trim().Length > 0)
                userInProcessDirectory = SobekCM_Library_Settings.In_Process_Submission_Location + "\\" + user.UFID + "\\newgroup";
            else
                userInProcessDirectory = SobekCM_Library_Settings.In_Process_Submission_Location + "\\" + user.UserName.Replace(".","").Replace("@","") + "\\newgroup";

            // Handle postback for changing the template or project
            templateCode = user.Current_Template;
            if (currentMode.isPostBack)
            {
                string action1 = HttpContext.Current.Request.Form["action"];
                if ((action1 != null) && ((action1 == "template") || (action1 == "project")))
                {
                    string newvalue = HttpContext.Current.Request.Form["phase"];
                    if ((action1 == "template") && ( newvalue != templateCode ))
                    {
                        user.Current_Template = newvalue;
                        templateCode = user.Current_Template;
                        if (File.Exists(userInProcessDirectory + "\\agreement.txt"))
                            File.Delete(userInProcessDirectory + "\\agreement.txt");
                    }
                    if ((action1 == "project") && (newvalue != user.Current_Project))
                    {
                        user.Current_Project = newvalue;
                    }
                    HttpContext.Current.Session["item"] = null;
                }
            }

            // Load the template
            templateCode = user.Current_Template;
            template = Cached_Data_Manager.Retrieve_Template(templateCode, Tracer);
            if ( template != null )
            {
                Tracer.Add_Trace("New_Group_And_Item_MySobekViewer.Constructor", "Found template in cache");
            }
            else
            {
                Tracer.Add_Trace("New_Group_And_Item_MySobekViewer.Constructor", "Reading template");

                // Read this template
                Template_XML_Reader reader = new Template_XML_Reader();
                template = new Template();
                reader.Read_XML( SobekCM_Library_Settings.Base_MySobek_Directory + "templates\\" + templateCode + ".xml", template, true);

                // Add the current codes to this template
                template.Add_Codes(Code_Manager);

                // Save this into the cache
                Cached_Data_Manager.Store_Template(templateCode, template, Tracer);
            }

            // Determine the number of total template pages
            totalTemplatePages = template.InputPages_Count;
            if (template.Permissions_Agreement.Length > 0)
                totalTemplatePages++;
            if (template.Upload_Types != Template.Template_Upload_Types.None)
                totalTemplatePages++;

            // Determine the title for this template, or use a default
            toolTitle = template.Title;
            if (toolTitle.Length == 0)
                toolTitle = "Self-Submittal Tool";

            // Determine the current phase
            currentProcessStep = 1;
            if ((currentMode.My_Sobek_SubMode.Length > 0) && (Char.IsNumber(currentMode.My_Sobek_SubMode[0])))
            {
                Int32.TryParse(currentMode.My_Sobek_SubMode.Substring(0), out currentProcessStep);
            }

            // If this is process step 1 and there is no permissions statement in the template,
            // just go to step 2
            if ((currentProcessStep == 1) && (template.Permissions_Agreement.Length == 0))
            {
                // Delete any pre-existing agreement from an earlier aborted submission process
                if (File.Exists(userInProcessDirectory + "\\agreement.txt"))
                    File.Delete(userInProcessDirectory + "\\agreement.txt");

                // Skip the permissions step
                currentProcessStep = 2;
            }

            // If there is a boundary infraction here, go back to step 2
            if (currentProcessStep < 0)
                currentProcessStep = 2;
            if ((currentProcessStep > template.InputPages.Count + 1 ) && ( currentProcessStep != 8 ) && ( currentProcessStep != 9 ))
                currentProcessStep = 2;

            // If this is to enter a file or URL, and the template does not include this, skip over this step
            if (( currentProcessStep == 8 ) && ( template.Upload_Types == Template.Template_Upload_Types.None ))
            {
                // For now, just forward to the next phase
                currentMode.My_Sobek_SubMode = "9";
                HttpContext.Current.Response.Redirect( currentMode.Redirect_URL());
            }

            // Look for the item in the session, then directory, then just create a new one
            if (HttpContext.Current.Session["Item"] == null)
            {
                // Clear any old files (older than 24 hours) that are in the directory
                if (!Directory.Exists(userInProcessDirectory))
                    Directory.CreateDirectory(userInProcessDirectory);
                else
                {
                    // Anything older than a day should be deleted
                    string[] files = Directory.GetFiles(userInProcessDirectory);
                    foreach (string thisFile in files)
                    {
                        DateTime modifiedDate = ((new FileInfo(thisFile)).LastWriteTime);
                        if (DateTime.Now.Subtract(modifiedDate).TotalHours > (24 * 7))
                        {
                            try
                            {
                                File.Delete(thisFile);
                            }
                            catch(Exception )
                            {
                                // Unable to delete existing file in the user's folder.
                                // This is an error, but how to report it?
                            }
                        }
                    }
                }

                // First, look for an existing METS file
                string[] existing_mets = Directory.GetFiles(userInProcessDirectory, "*.mets*");
                if (existing_mets.Length > 0)
                {
                    Tracer.Add_Trace("New_Group_And_Item_MySobekViewer.Constructor", "Reading existing METS file<br />(" + existing_mets[0] + ")");
                    item = SobekCM_Item.Read_METS(existing_mets[0]);

                    // Set the visibility information from the template
                    item.Behaviors.IP_Restriction_Membership = template.Default_Visibility;
                }

                // If there is still no item, just create a new one
                if (item == null)
                {
                    // Build a new empty METS file
                    new_item( Tracer );
                }

                // Save this to the session state now
                HttpContext.Current.Session["Item"] = item;
            }
            else
            {
                Tracer.Add_Trace("New_Group_And_Item_MySobekViewer.Constructor", "Item found in session cache");
                item = (SobekCM_Item)HttpContext.Current.Session["Item"];
            }

            #region Handle any other post back requests

            // If this is post-back, handle it
            if (currentMode.isPostBack)
            {
                // If this is a request from stage 8, save the new labels and url first
                if (currentProcessStep == 8)
                {
                    string[] getKeys = HttpContext.Current.Request.Form.AllKeys;
                    string file_name_from_keys = String.Empty;
                    string label_from_keys = String.Empty;
                    foreach (string thisKey in getKeys)
                    {
                        if (thisKey.IndexOf("upload_file") == 0)
                        {
                            file_name_from_keys = HttpContext.Current.Request.Form[thisKey];
                        }
                        if (thisKey.IndexOf("upload_label") == 0)
                        {
                            label_from_keys = HttpContext.Current.Request.Form[thisKey];
                        }
                        if ((file_name_from_keys.Length > 0) && (label_from_keys.Length > 0))
                        {
                            HttpContext.Current.Session["file_" + file_name_from_keys.Trim()] = label_from_keys.Trim();
                            file_name_from_keys = String.Empty;
                            label_from_keys = String.Empty;
                        }

                        if (thisKey == "url_input")
                        {
                            item.Bib_Info.Location.Other_URL = HttpContext.Current.Request.Form[thisKey];
                        }
                    }
                }

                string action = HttpContext.Current.Request.Form["action"];
                if (action == "cancel")
                {
                    // Clear all files in the user process folder
                    try
                    {
                        string[] all_files = Directory.GetFiles(userInProcessDirectory);
                        foreach (string thisFile in all_files)
                            Directory.Delete(thisFile);
                        Directory.Delete(userInProcessDirectory);
                    }
                    catch (Exception)
                    {
                        // Unable to delete existing file in the user's folder.
                        // This is an error, but how to report it?
                    }

                    // Clear all the information in memory
                    HttpContext.Current.Session["agreement_date"] = null;
                    HttpContext.Current.Session["item"] = null;

                    // Clear any temporarily assigned current project and template
                    user.Current_Project = null;
                    user.Current_Template = null;

                    // Forward back to my Sobek home
                    currentMode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                    HttpContext.Current.Response.Redirect(currentMode.Redirect_URL());
                }

                if ( action == "delete" )
                {
                    string filename = HttpContext.Current.Request.Form["phase"];
                    try
                    {
                        if (File.Exists(userInProcessDirectory + "\\" + filename))
                            File.Delete(userInProcessDirectory + "\\" + filename);

                        // Forward
                        HttpContext.Current.Response.Redirect( currentMode.Redirect_URL());
                    }
                    catch (Exception)
                    {
                        // Unable to delete existing file in the user's folder.
                        // This is an error, but how to report it?
                    }
                }

                if (action == "clear")
                {
                    // If there is an old METS file, delete it
                    if (File.Exists(userInProcessDirectory + "\\TEMP000001_00001.mets"))
                        File.Delete(userInProcessDirectory + "\\TEMP000001_00001.mets");

                    // Create the new METS file and add to the session
                    new_item(null);
                    HttpContext.Current.Session["Item"] = item;

                    // Forward back to the same URL
                    currentMode.My_Sobek_SubMode = "2";
                    HttpContext.Current.Response.Redirect( currentMode.Redirect_URL());
                }

                if (action == "next_phase")
                {

                    string next_phase = HttpContext.Current.Request.Form["phase"];

                    // If this goes from step 1 to step 2, write the permissions first
                    if ((currentProcessStep == 1) && (next_phase == "2") && ( template.Permissions_Agreement.Length > 0 ))
                    {
                        // Store this agreement in the session state
                        DateTime agreement_date = DateTime.Now;
                        HttpContext.Current.Session["agreement_date"] = agreement_date;

                        // Also, save this as a text file
                        string agreement_file = userInProcessDirectory + "\\agreement.txt";
                        StreamWriter writer = new StreamWriter(agreement_file, false);
                        writer.WriteLine("Permissions Agreement");
                        writer.WriteLine();
                        writer.WriteLine("User: "******" ( " + user.UFID + " )");
                        writer.WriteLine("Date: " + agreement_date.ToString());
                        writer.WriteLine();
                        writer.WriteLine(template.Permissions_Agreement);
                        writer.Flush();
                        writer.Close();
                    }

                    // If this is going from a step that includes the metadata entry portion, save this to the item
                    if ((currentProcessStep > 1) && (currentProcessStep < 8))
                    {
                        // Save to the item
                        template.Save_To_Bib(item, user, currentProcessStep - 1);
                        item.Save_METS();
                        HttpContext.Current.Session["Item"] = item;

                        // Save the pertinent data to the METS file package
                        item.METS_Header.Create_Date = DateTime.Now;
                        if ((HttpContext.Current.Session["agreement_date"] != null) && (HttpContext.Current.Session["agreement_date"].ToString().Length > 0))
                        {
                            DateTime asDateTime;
                            if (DateTime.TryParse(HttpContext.Current.Session["agreement_date"].ToString(), out asDateTime))
                                item.METS_Header.Create_Date = asDateTime;
                        }
                        HttpContext.Current.Session["Item"] = item;

                        // Save this item, just in case it gets lost somehow
                        item.Source_Directory = userInProcessDirectory;
                        string acquisition_append = "Submitted by " + user.Full_Name + ".";
                        if (item.Bib_Info.Notes_Count > 0)
                        {
                            foreach (Note_Info thisNote in item.Bib_Info.Notes.Where(thisNote => thisNote.Note_Type == Note_Type_Enum.acquisition))
                            {
                                if (thisNote.Note.IndexOf(acquisition_append) < 0)
                                    thisNote.Note = thisNote.Note.Trim() + "  " + acquisition_append;
                                break;
                            }
                        }

                        // Also, check all the authors to add the current users attribution information
                        if (user.Organization.Length > 0)
                        {
                            if ((item.Bib_Info.Main_Entity_Name.Full_Name.IndexOf(user.Family_Name) >= 0) && ((item.Bib_Info.Main_Entity_Name.Full_Name.IndexOf(user.Given_Name) >= 0) || ((user.Nickname.Length > 2) && (item.Bib_Info.Main_Entity_Name.Full_Name.IndexOf(user.Nickname) > 0))))
                            {
                                item.Bib_Info.Main_Entity_Name.Affiliation = user.Organization;
                                if (user.College.Length > 0)
                                    item.Bib_Info.Main_Entity_Name.Affiliation = item.Bib_Info.Main_Entity_Name.Affiliation + " -- " + user.College;
                                if (user.Department.Length > 0)
                                    item.Bib_Info.Main_Entity_Name.Affiliation = item.Bib_Info.Main_Entity_Name.Affiliation + " -- " + user.Department;
                                if (user.Unit.Length > 0)
                                    item.Bib_Info.Main_Entity_Name.Affiliation = item.Bib_Info.Main_Entity_Name.Affiliation + " -- " + user.Unit;
                            }
                            if (item.Bib_Info.Names_Count > 0)
                            {
                                foreach (Name_Info thisName in item.Bib_Info.Names)
                                {
                                    if ((thisName.Full_Name.IndexOf(user.Family_Name) >= 0) && ((thisName.Full_Name.IndexOf(user.Given_Name) >= 0) || ((user.Nickname.Length > 2) && (thisName.Full_Name.IndexOf(user.Nickname) > 0))))
                                    {
                                        thisName.Affiliation = user.Organization;
                                        if (user.College.Length > 0)
                                            thisName.Affiliation = thisName.Affiliation + " -- " + user.College;
                                        if (user.Department.Length > 0)
                                            thisName.Affiliation = thisName.Affiliation + " -- " + user.Department;
                                        if (user.Unit.Length > 0)
                                            thisName.Affiliation = thisName.Affiliation + " -- " + user.Unit;

                                    }
                                }
                            }
                        }
                        item.Save_METS();
                        HttpContext.Current.Session["Item"] = item;
                    }

                    // For now, just forward to the next phase
                    currentMode.My_Sobek_SubMode = next_phase;
                    HttpContext.Current.Response.Redirect( currentMode.Redirect_URL());
                }
            }

            #endregion

            #region Perform some validation to determine if the user should be at this step

            // If this is past the agreement phase, check that an agreement exists
            if (currentProcessStep > 1)
            {
                // Validate that an agreement.txt file exists, if the template has permissions
                if (( template.Permissions_Agreement.Length > 0 ) && (!File.Exists(userInProcessDirectory + "\\agreement.txt")))
                {
                    currentMode.My_Sobek_SubMode = "1";
                    HttpContext.Current.Response.Redirect( currentMode.Redirect_URL());
                }

                // Get the validation errors
                validationErrors = new List<string>();
                SobekCM_Item_Validator.Validate_SobekCM_Item(item, validationErrors);
            }

            // If this is to put up items or complete the item, validate the METS
            if ( currentProcessStep >= 8 )
            {
                // Validate that a METS file exists
                if (Directory.GetFiles( userInProcessDirectory, "*.mets*").Length == 0 )
                {
                    currentMode.My_Sobek_SubMode = "2";
                    HttpContext.Current.Response.Redirect( currentMode.Redirect_URL());
                }

                // Get the validation errors
                if ( validationErrors.Count == 0 )
                    item.Save_METS();
                else
                {
                    item.Web.Show_Validation_Errors = true;
                    currentMode.My_Sobek_SubMode = "2";
                    HttpContext.Current.Response.Redirect( currentMode.Redirect_URL());
                }
            }

            // If this is for step 8, ensure that this even takes this information, or go to step 9
            if (( currentProcessStep == 8 ) && ( template.Upload_Types == Template.Template_Upload_Types.None ))
            {
                currentMode.My_Sobek_SubMode = "9";
                HttpContext.Current.Response.Redirect( currentMode.Redirect_URL());
            }

            // If this is going into the last process step, check that any mandatory info (file, url, .. )
            // from the last step is present
            if ( currentProcessStep == 9 )
            {
                // Only check if this is mandatory
                if (( template.Upload_Mandatory ) && ( template.Upload_Types != Template.Template_Upload_Types.None ))
                {
                    // Does this require either a FILE or URL?
                    bool required_file_present = false;
                    bool required_url_present = false;

                    // If this accepts files, check for acceptable files
                    if (( template.Upload_Types == Template.Template_Upload_Types.File ) || ( template.Upload_Types == Template.Template_Upload_Types.URL ))
                    {
                        // Get list of files in this package
                        string[] all_files = Directory.GetFiles(userInProcessDirectory);
                        List<string> acceptable_files = all_files.Where(thisFile => (thisFile.IndexOf("agreement.txt") < 0) && (thisFile.IndexOf("TEMP000001_00001.mets") < 0)).ToList();

                        // Acceptable files found?
                        if ( acceptable_files.Count > 0 )
                            required_file_present = true;
                    }

                    // If this accepts URLs, check for a URL
                    if (( template.Upload_Types == Template.Template_Upload_Types.URL ) || ( template.Upload_Types == Template.Template_Upload_Types.File_or_URL ))
                    {
                        if ( item.Bib_Info.Location.Other_URL.Length > 0 )
                        {
                            required_url_present = true;
                        }
                    }

                    // If neither was present, go back to step 8
                    if (( !required_file_present ) && ( !required_url_present ))
                    {
                        currentMode.My_Sobek_SubMode = "8";
                        HttpContext.Current.Response.Redirect( currentMode.Redirect_URL());
                    }
                }

                // Complete the item submission
                complete_item_submission( item,  Tracer );
            }

            #endregion
        }
        /// <summary> Builds a specific <see cref="SobekCM_Skin_Object"/> when needed by a user's request </summary>
        /// <param name="Skin_Row"> Row from a database query with basic information about the interface to build ( codes, override flags, banner link )</param>
        /// <param name="Language_Code"> Code for the language, which determines which HTML to use </param>
        /// <returns> Completely built HTML interface object </returns>
        /// <remarks> The datarow for this method is retrieved from the database by calling the <see cref="Database.SobekCM_Database.Get_All_Web_Skins"/> method during 
        /// application startup and is then stored in the <see cref="SobekCM_Skin_Collection"/> class until needed. </remarks>
        public static SobekCM_Skin_Object Build_Skin(DataRow Skin_Row, string Language_Code )
        {
            // Pull values out from this row
            string code = Skin_Row["WebSkinCode"].ToString();
            string base_interface = Skin_Row["BaseInterface"].ToString();
            bool override_banner = Convert.ToBoolean(Skin_Row["OverrideBanner"]);
            string banner_link = Skin_Row["BannerLink"].ToString();
            string this_style = "design/skins/" + code + "/" + code + ".css";
            if (!File.Exists(SobekCM_Library_Settings.Base_Design_Location + "skins\\" + code + "\\" + code + ".css"))
                this_style = String.Empty;

            // Build the interface, along with any overriding banner
            SobekCM_Skin_Object thisInterface;
            if (override_banner)
            {
                string this_banner = String.Empty;

                // Find the LANGUAGE-SPECIFIC high-bandwidth banner image
                string[] banner_file = Directory.GetFiles(SobekCM_Library_Settings.Base_Design_Location + "skins/" + code, "banner_" + Language_Code + ".*");
                if (banner_file.Length > 0)
                {
                    if (banner_link.Length > 0)
                    {
                        this_banner = "<a href=\"" + banner_link + "\"><img border=\"0\" src=\"<%BASEURL%>skins/" + code + "/" + (new FileInfo(banner_file[0]).Name) + "\" alt=\"MISSING BANNER\" /></a>";
                    }
                    else
                    {
                        this_banner = "<img border=\"0\" src=\"<%BASEURL%>skins/" + code + "/" + (new FileInfo(banner_file[0]).Name) + "\" alt=\"MISSING BANNER\" />";
                    }
                }

                // If nothing was gotten, look for the ENGLISH banner image and use that
                if ((this_banner.Length == 0) && (Language_Code.Length > 0) && (Language_Code != "en"))
                {
                    banner_file = Directory.GetFiles(SobekCM_Library_Settings.Base_Design_Location + "skins/" + code, "banner.*");
                    if (banner_file.Length > 0)
                    {
                        if (banner_link.Length > 0)
                        {
                            this_banner = "<a href=\"" + banner_link + "\"><img border=\"0\" src=\"<%BASEURL%>design/skins/" + code + "/" + (new FileInfo(banner_file[0]).Name) + "\" alt=\"MISSING BANNER\" /></a>";
                        }
                        else
                        {
                            this_banner = "<img border=\"0\" src=\"<%BASEURL%>design/skins/" + code + "/" + (new FileInfo(banner_file[0]).Name) + "\" alt=\"MISSING BANNER\" />";
                        }
                    }
                }

                // Create this interface
                thisInterface = new SobekCM_Skin_Object(code, base_interface, this_style, this_banner);
            }
            else
            {
                // Create an interface without banner override
                thisInterface = new SobekCM_Skin_Object(code, base_interface, this_style);
            }

            // Assign the value to suppress top-level navigation
            thisInterface.Suppress_Top_Navigation = Convert.ToBoolean(Skin_Row["SuppressTopNavigation"]);

            // Assign the header and footer, or pass in the source
            string this_header;
            string this_footer;
            string this_item_header;
            string this_item_footer;

            // If the language isn't english, prepare to default to english
            if ((Language_Code.Length > 0) && (Language_Code != "en"))
            {
                // Assign the default locations for the banners
                this_header = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header_" + Language_Code + ".html";
                this_footer = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer_" + Language_Code + ".html";
                this_item_header = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header_item_" + Language_Code + ".html";
                this_item_footer = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer_item_" + Language_Code + ".html";

                if (!File.Exists(this_header))
                {
                    this_header = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header.html";
                }

                if (!File.Exists(this_footer))
                {
                    this_footer = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer.html";
                }

                if (!File.Exists(this_item_header))
                {
                    this_item_header = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header_item.html";
                }

                if (!File.Exists(this_item_footer))
                {
                    this_item_footer = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer_item.html";
                }
            }
            else
            {
                // Assign the default locations for the banners
                this_header = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header.html";
                this_footer = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer.html";
                this_item_header = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/header_item.html";
                this_item_footer = SobekCM_Library_Settings.Base_Design_Location + "skins/" + code + "/html/footer_item.html";
            }

            // If the item specific stuff doesn't exist, use the regular
            if (!File.Exists(this_item_header))
                this_item_header = this_header;
            if (!File.Exists(this_item_footer))
                this_item_footer = this_footer;

            // Now, assign all of these
            thisInterface.Set_Header_Footer_Source(this_header, this_footer, this_item_header, this_item_footer);

            // Save the banner override and language code
            thisInterface.Override_Banner = override_banner;
            thisInterface.Language_Code = Language_Code;

            // Return the built interface
            return thisInterface;
        }
        /// <summary> Add a new HTML skin to this collection, to be retained as long as the application is active </summary>
        /// <param name="Skin_Code"> Code for this new HTML skin</param>
        /// <param name="Base_Skin_Code"> Code for the base HTML skin which this new skin derives from</param>
        /// <param name="CSS_Style"> Additional CSS Stylesheet to be included for this new HTML skin</param>
        /// <param name="Banner_HTML"> Code for the banner to use, if this is set to override the banner</param>
        /// <returns> Newly constructed <see cref="SobekCM_Skin_Object"/> object </returns>
        public SobekCM_Skin_Object Add(string Skin_Code, string Base_Skin_Code, string CSS_Style, string Banner_HTML)
        {
            // Create the new skin object
            SobekCM_Skin_Object newSkin = new SobekCM_Skin_Object(Skin_Code, Base_Skin_Code, CSS_Style, Banner_HTML);

            // Add to the hashtable
            defaultSkins[Skin_Code.ToLower()] =  newSkin;

            // Return the new, built skin object
            return newSkin;
        }
        /// <summary> Constructor for a new instance of the Folder_Mgmt_MySobekViewer class </summary>
        /// <param name="User"> Authenticated user information </param>
        /// <param name="Results_Statistics"> Information about the entire set of results for the current folder </param>
        /// <param name="Paged_Results"> Single page of results for the current folder, within the entire set </param>
        /// <param name="Code_Manager"> Code manager object maintains mapping between SobekCM codes and greenstone codes (used by result_dataset_html_subwriter)</param>
        /// <param name="Item_List"> Object for pulling additional information about each item during display </param>
        /// <param name="currentCollection"> Current item aggregation [UNUSED?] </param>
        /// <param name="htmlSkin"> HTML interface, which determines the header, footer, stylesheet, and other design elements for the rendered HTML</param>
        /// <param name="Translator"> Translation / language support object for writing the user interface is multiple languages</param>
        /// <param name="currentMode"> 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 Folder_Mgmt_MySobekViewer(User_Object User,
            Search_Results_Statistics Results_Statistics,
            List<iSearch_Title_Result> Paged_Results,
            Aggregation_Code_Manager Code_Manager,
            Item_Lookup_Object Item_List,
            Item_Aggregation currentCollection, 
            SobekCM_Skin_Object htmlSkin,
            Language_Support_Info Translator, 
            SobekCM_Navigation_Object currentMode,
            Custom_Tracer Tracer)
            : base(User)
        {
            Tracer.Add_Trace("Folder_Mgmt_MySobekViewer.Constructor", String.Empty);

            user = User;
            pagedResults = Paged_Results;
            resultsStatistics = Results_Statistics;
            codeManager = Code_Manager;
            itemList = Item_List;
            this.htmlSkin = htmlSkin;
            base.Translator = Translator;
            this.currentCollection = currentCollection;

            properFolderName = String.Empty;
            int current_folder_id = -1;
            if (currentMode.My_Sobek_SubMode.Length > 0)
            {
                // Try to get this user folder from the user object
                User_Folder userFolder = user.Get_Folder( currentMode.My_Sobek_SubMode );

                // If the user folder is null, then this folder is not in the current user object
                // This may still be a valid folder though.  Check this by pulling folder list for this
                // user again
                if (userFolder == null)
                {
                    // Get the user from the database again
                    User_Object checkFolderUser = SobekCM_Database.Get_User(user.UserID, Tracer);

                    // Look for this folder in the new user object
                    userFolder = checkFolderUser.Get_Folder(currentMode.My_Sobek_SubMode);
                    if (userFolder == null)
                    {
                        // Invalid folder.. should not have gotten this far though
                        HttpContext.Current.Response.Redirect(currentMode.Base_URL);
                    }
                    else
                    {
                        // Save this to the user so this does not have to happen again
                        user.Add_Folder(userFolder);
                    }
                }

                // Get the proper name and folder id
                Debug.Assert(userFolder != null, "userFolder != null");
                properFolderName = userFolder.Folder_Name;
                current_folder_id = userFolder.Folder_ID;
            }

            if ((currentMode.isPostBack) || ((HttpContext.Current.Request.Form["item_action"] != null) && (HttpContext.Current.Request.Form["item_action"].Length > 0 )))
            {
                try
                {
                    // Pull the standard values
                    NameValueCollection form = HttpContext.Current.Request.Form;

                    string item_action = form["item_action"].Replace(",","").ToUpper().Trim();
                    string bookshelf_items = form["bookshelf_items"].Trim().Replace("%22", "\"").Replace("%27", "'").Replace("%3D", "=").Replace("%26", "&");
                    string bookshelf_params = form["bookshelf_params"].Trim();
                    string add_bookshelf = String.Empty;
                    if ( form["add_bookshelf"] != null )
                        add_bookshelf = form["add_bookshelf"].Trim();

                    if (item_action == "REFRESH_FOLDER")
                    {
                         refresh_user_folders(user, Tracer);
                         Cached_Data_Manager.Remove_All_User_Folder_Browses(user.UserID, Tracer);
                    }

                    if (item_action == "DELETE_FOLDER")
                    {
                        int folder_id = Convert.ToInt32(bookshelf_items);

                        SobekCM_Database.Delete_User_Folder(user.UserID, folder_id, Tracer);
                        Cached_Data_Manager.Clear_Public_Folder_Info(folder_id, Tracer);
                        refresh_user_folders(user, Tracer);
                    }

                    if (item_action == "NEW_BOOKSHELF")
                    {
                        string folder_name = form["new_bookshelf_name"].Trim().Replace("<", "(").Replace(">", ")");
                        int parent_id = Convert.ToInt32(form["new_bookshelf_parent"]);

                        if (SobekCM_Database.Edit_User_Folder(-1, user.UserID, parent_id, folder_name, false, String.Empty, Tracer) > 0)
                        {
                            refresh_user_folders(user, Tracer);
                        }
                    }

                    if ( item_action == "FOLDER_VISIBILITY" )
                    {
                        User_Folder thisFolder = user.Get_Folder(bookshelf_items);
                        if (bookshelf_params.ToUpper() == "PRIVATE")
                        {
                            if (SobekCM_Database.Edit_User_Folder(thisFolder.Folder_ID, user.UserID, -1, thisFolder.Folder_Name, false, String.Empty, Tracer) >= 0)
                                thisFolder.isPublic = false;

                            Cached_Data_Manager.Clear_Public_Folder_Info(thisFolder.Folder_ID, Tracer);
                        }

                        if (bookshelf_params.ToUpper() == "PUBLIC")
                        {
                            if (SobekCM_Database.Edit_User_Folder(thisFolder.Folder_ID, user.UserID, -1, thisFolder.Folder_Name, true, String.Empty, Tracer) >= 0 )
                                thisFolder.isPublic = true;
                        }
                    }

                    if ((item_action == "REMOVE") || ( item_action == "MOVE" ))
                    {
                        if (bookshelf_items.IndexOf("|") > 0)
                        {
                            string[] split_multi_items = bookshelf_items.Split("|".ToCharArray());
                            foreach (string[] split in split_multi_items.Select(thisItem => thisItem.Split("_".ToCharArray())).Where(split => split.Length == 2))
                            {
                                SobekCM_Database.Delete_Item_From_User_Folder(user.UserID, properFolderName, split[0], split[1], Tracer);
                                if (item_action == "MOVE")
                                {
                                    SobekCM_Database.Add_Item_To_User_Folder(user.UserID, add_bookshelf, split[0], split[1], 0, String.Empty, Tracer);
                                }
                            }

                            // Ensure this user folder is not sitting in the cache
                            Cached_Data_Manager.Remove_User_Folder_Browse(user.UserID, properFolderName, Tracer);
                            Cached_Data_Manager.Clear_Public_Folder_Info(current_folder_id, Tracer);
                            if (item_action == "MOVE")
                            {
                                Cached_Data_Manager.Remove_User_Folder_Browse(user.UserID, add_bookshelf, Tracer);
                                User_Folder moved_to_folder = user.Get_Folder(add_bookshelf);
                                if (moved_to_folder != null)
                                {
                                    Cached_Data_Manager.Clear_Public_Folder_Info(moved_to_folder.Folder_ID, Tracer);
                                }
                            }
                        }
                        else
                        {
                                string[] split = bookshelf_items.Split("_".ToCharArray());
                                if (split.Length == 2)
                                {
                                    SobekCM_Database.Delete_Item_From_User_Folder(user.UserID, properFolderName, split[0], split[1], Tracer);
                                    if (item_action == "MOVE")
                                    {
                                        SobekCM_Database.Add_Item_To_User_Folder(user.UserID, add_bookshelf, split[0], split[1], 1, String.Empty, Tracer);
                                    }
                                }

                            // Ensure this user folder is not sitting in the cache
                            Cached_Data_Manager.Remove_User_Folder_Browse(user.UserID, properFolderName, Tracer);
                            Cached_Data_Manager.Clear_Public_Folder_Info(current_folder_id, Tracer);
                            if (item_action == "MOVE")
                            {
                                Cached_Data_Manager.Remove_User_Folder_Browse(user.UserID, add_bookshelf, Tracer);
                                User_Folder moved_to_folder = user.Get_Folder(add_bookshelf);
                                if (moved_to_folder != null)
                                {
                                    Cached_Data_Manager.Clear_Public_Folder_Info(moved_to_folder.Folder_ID, Tracer);
                                }
                            }
                        }
                    }

                    if ( item_action == "EMAIL" )
                    {
                        string comments = form["email_comments"].Trim().Replace(">",")").Replace("<","(");
                        string email = form["email_address"].Trim();
                        string format = HttpContext.Current.Request.Form["email_format"].Trim().ToUpper();

                            string[] split = bookshelf_items.Split("_".ToCharArray());
                            if (split.Length == 2)
                            {
                                SobekCM_Assistant newAssistant = new SobekCM_Assistant();
                                SobekCM_Item newItem;
                                Page_TreeNode newPage;
                                SobekCM_Items_In_Title itemsInTitle;
                                newAssistant.Get_Item(currentMode, Item_List, SobekCM_Library_Settings.Image_URL, null, user, Tracer, out newItem, out newPage, out itemsInTitle );
                                SobekCM_Database.Add_Item_To_User_Folder(user.UserID, add_bookshelf, split[0], split[1], 1, comments, Tracer);

                                // Determine the email format
                                bool is_html_format = (format != "TEXT");

                                // Send this email
                                Item_Email_Helper.Send_Email(email, String.Empty, comments, user.Full_Name, currentMode.SobekCM_Instance_Abbreviation, newItem, is_html_format, currentMode.Base_URL + newItem.BibID + "/" + newItem.VID);
                            }
                    }

                    if ( item_action == "EDIT_NOTES" )
                    {
                        string notes = form["add_notes"].Trim().Replace(">",")").Replace("<","(");

                            string[] split = bookshelf_items.Split("_".ToCharArray());
                            if (split.Length == 2)
                            {
                                SobekCM_Database.Add_Item_To_User_Folder(user.UserID, add_bookshelf, split[0], split[1], 1, notes, Tracer);
                                Cached_Data_Manager.Remove_User_Folder_Browse(user.UserID, add_bookshelf, Tracer);
                            }

                    }
                }
                catch(Exception)
                {
                    // Catches any errors which may occur.  User will be sent back to the same URL,
                    // so any error that occurs should be obvious to the user
                }

                string return_url = HttpContext.Current.Items["Original_URL"].ToString();
                HttpContext.Current.Response.Redirect(return_url, false);

            }
        }
        /// <summary> Constructor for a new instance of the Static_Pages_Builder class </summary>
        /// <param name="Primary_Web_Server_URL"> URL for the primary web server </param>
        /// <param name="Static_Data_Location"> Network location for the data directory </param>
        /// <remarks> This constructor pulls all the needed information from the database</remarks>
        public Static_Pages_Builder(string Primary_Web_Server_URL, string Static_Data_Location )
        {
            primaryWebServerUrl = Primary_Web_Server_URL;
            staticSobekcmDataLocation = Static_Data_Location;

            tracer = new Custom_Tracer();
            assistant = new SobekCM_Assistant();

               // marcWriter = new MARC_Writer();

            // Get the list of all items
            SobekCM_Database.Connection_String = SobekCM_Library_Settings.Database_Connection_String; ;

            // Build all the objects needed by the UFDC Library
            iconList = new Dictionary<string, Wordmark_Icon>();
            SobekCM_Database.Populate_Icon_List(iconList, tracer);

            translations = new Language_Support_Info();
            SobekCM_Database.Populate_Translations(translations, tracer);

            codeManager = new Aggregation_Code_Manager();
            SobekCM_Database.Populate_Code_Manager(codeManager, tracer);

            // Get the item list and build the hashtable
               //     DataSet tempSet = SobekCM.Library.Database.SobekCM_Database.Get_Item_List(false, tracer);
            itemList = new Item_Lookup_Object();
            SobekCM_Database.Populate_Item_Lookup_Object(false, itemList, tracer);

            // Set some constant settings
            // SobekCM.Library.SobekCM_Library_Settings.Watermarks_URL = primary_web_server_url + "/design/wordmarks/";
            SobekCM_Library_Settings.Base_SobekCM_Location_Relative = primaryWebServerUrl;

            // Create the mode object
            currentMode = new SobekCM_Navigation_Object
                              {
                                  ViewerCode = "FC",
                                  Skin = "UFDC",
                                  Mode = Display_Mode_Enum.Item_Display,
                                  Language = Web_Language_Enum.English,
                                  Base_URL = primaryWebServerUrl
                              };

            // Create the ufdc interface object
            ufdcInterface = new SobekCM_Skin_Object("ufdc", String.Empty, currentMode.Base_Design_URL + "skins/ufdc/ufdc.css")
                                {
                                    Header_Item_HTML =GetHtmlPage(primaryWebServerUrl + "/design/skins/UFDC/html/header_item.html").Replace("<%BREADCRUMBS%>","<a href=\"" + primaryWebServerUrl + "\">UFDC Home</a>").Replace("<%MYSOBEK%>","<a href=\"" + primaryWebServerUrl + "my\">myUFDC Home</a>"),
                                    Footer_Item_HTML = GetHtmlPage(primaryWebServerUrl + "/design/skins/UFDC/html/footer_item.html").Replace("<%VERSION%>", SobekCM_Library_Settings.CURRENT_WEB_VERSION).Replace("src=\"" + currentMode.Base_URL + "design/", "src=\"" + primaryWebServerUrl + "/design/"),
                                    Header_HTML = GetHtmlPage(primaryWebServerUrl + "/design/skins/UFDC/html/header.html").Replace("<%BREADCRUMBS%>", "<a href=\"" + primaryWebServerUrl + "\">UFDC Home</a>").Replace("<%MYSOBEK%>","<a href=\"" + primaryWebServerUrl + "my\">myUFDC Home</a>"),
                                    Footer_HTML = GetHtmlPage(primaryWebServerUrl + "/design/skins/UFDC/html/footer.html").Replace("<%VERSION%>", SobekCM_Library_Settings.CURRENT_WEB_VERSION).Replace("src=\"" + currentMode.Base_URL + "design/", "src=\"" + primaryWebServerUrl + "/design/"),
                                    Language_Code = "",
                                    Override_Banner = false
                                };

            // Create the dLOC_English interface
            dlocInterface = new SobekCM_Skin_Object("dloc", String.Empty, currentMode.Base_Design_URL + "skins/dloc/dloc.css", "<img id=\"mainBanner\" src=\"" + currentMode.Base_URL + "design/skins/dloc/banner.jpg\" alt=\"MISSING BANNER\" />")
                                {
                                    Header_Item_HTML = GetHtmlPage(primaryWebServerUrl + "/design/skins/dloc/html/header_item.html").Replace("<%BREADCRUMBS%>", "<a href=\"" + primaryWebServerUrl + "\">UFDC Home</a>").Replace("<%MYSOBEK%>", "<a href=\"" + primaryWebServerUrl + "my\">myUFDC Home</a>"),
                                    Footer_Item_HTML = GetHtmlPage(primaryWebServerUrl + "/design/skins/dloc/html/footer_item.html").Replace("<%VERSION%>", SobekCM_Library_Settings.CURRENT_WEB_VERSION).Replace("src=\"" + currentMode.Base_URL + "design/", "src=\"" + primaryWebServerUrl + "/design/"),
                                    Header_HTML = GetHtmlPage(primaryWebServerUrl + "/design/skins/dloc/html/header.html").Replace("<%BREADCRUMBS%>", "<a href=\"" + primaryWebServerUrl + "\">UFDC Home</a>").Replace("<%MYSOBEK%>", "<a href=\"" + primaryWebServerUrl + "my\">myUFDC Home</a>"),
                                    Footer_HTML = GetHtmlPage(primaryWebServerUrl + "/design/skins/dloc/html/footer.html").Replace("<%VERSION%>", SobekCM_Library_Settings.CURRENT_WEB_VERSION).Replace("src=\"" + currentMode.Base_URL + "design/", "src=\"" + primaryWebServerUrl + "/design/"),
                                    Language_Code = "",
                                    Override_Banner = false
                                };

            // Disable the cached data manager
            Cached_Data_Manager.Disabled = true;
        }
        /// <summary> Constructor for a new instance of the Edit_Item_Metadata_MySobekViewer class </summary>
        /// <param name="User"> Authenticated user information </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="All_Items_Lookup"> Allows individual items to be retrieved by various methods as <see cref="Single_Item"/> objects.</param>
        /// <param name="Current_Item"> Individual digital resource to be edited by the user </param>
        /// <param name="Code_Manager"> Code manager contains the list of all valid aggregation codes </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="HTML_Skin_Collection"> HTML Web skin collection which controls the overall appearance of this digital library </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        public Edit_Item_Metadata_MySobekViewer(User_Object User,
            SobekCM_Navigation_Object Current_Mode,
            Item_Lookup_Object All_Items_Lookup,
            SobekCM_Item Current_Item, Aggregation_Code_Manager Code_Manager,
            Dictionary<string, Wordmark_Icon> Icon_Table,
            SobekCM_Skin_Object HTML_Skin,
            Language_Support_Info Translator,
            SobekCM_Skin_Collection HTML_Skin_Collection,
            Custom_Tracer Tracer)
            : base(User)
        {
            Tracer.Add_Trace("Edit_Item_Metadata_MySobekViewer.Constructor", String.Empty);

            currentMode = Current_Mode;
            item = Current_Item;
            itemList = All_Items_Lookup;
            codeManager = Code_Manager;
            iconList = Icon_Table;
            webSkin = HTML_Skin;
            popUpFormsHtml = String.Empty;
            delayed_popup = String.Empty;
            base.Translator = Translator;
            skins = HTML_Skin_Collection;

            // If the user cannot edit this item, go back
            if (!user.Can_Edit_This_Item( item ))
            {
                currentMode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                HttpContext.Current.Response.Redirect(currentMode.Redirect_URL());
            }

            // Is this a project
            isProject = item.Bib_Info.SobekCM_Type == TypeOfResource_SobekCM_Enum.Project;

            string template_code = user.Edit_Template_Code;
            if ((isProject) || (item.Contains_Complex_Content) || (item.Using_Complex_Template))
            {
                template_code = user.Edit_Template_MARC_Code;
            }
            template = Cached_Data_Manager.Retrieve_Template(template_code, Tracer);
            if (template != null)
            {
                Tracer.Add_Trace("Edit_Item_Metadata_MySobekViewer.Constructor", "Found template in cache");
            }
            else
            {
                Tracer.Add_Trace("Edit_Item_Metadata_MySobekViewer.Constructor", "Reading template file");

                // Read this template
                Template_XML_Reader reader = new Template_XML_Reader();
                template = new Template();
                reader.Read_XML( SobekCM_Library_Settings.Base_MySobek_Directory + "templates\\edit\\" + template_code + ".xml", template, true);

                // Add the current codes to this template
                template.Add_Codes(Code_Manager);

                // Save this into the cache
                Cached_Data_Manager.Store_Template(template_code, template, Tracer);
            }

            // Get the current page number, or default to 1
            page = 1;
            if (currentMode.My_Sobek_SubMode.Length > 0)
            {
                if ((currentMode.My_Sobek_SubMode == "preview") || (currentMode.My_Sobek_SubMode == "marc") || (currentMode.My_Sobek_SubMode == "mets"))
                {
                    page = 0;
                }
                else
                {
                    page = 1;
                    bool isNumber = currentMode.My_Sobek_SubMode.All(Char.IsNumber);
                    if (isNumber)
                    {
                        if (isProject)
                            Double.TryParse(currentMode.My_Sobek_SubMode[0].ToString(), out page);
                        else
                            Double.TryParse(currentMode.My_Sobek_SubMode, out page);
                    }
                    else if ( isProject )
                    {
                        if ( Char.IsNumber(currentMode.My_Sobek_SubMode[0]))
                            Double.TryParse(currentMode.My_Sobek_SubMode[0].ToString(), out page);
                    }
                }
            }

            // Handle post backs
            if (Current_Mode.isPostBack)
            {
                // See if there was a hidden request
                string hidden_request = HttpContext.Current.Request.Form["new_element_requested"] ?? String.Empty;

                // If this was a cancel request do that
                if (hidden_request == "cancel")
                {
                    if (isProject)
                    {
                        Cached_Data_Manager.Remove_Project(user.UserID, item.BibID, null);

                        currentMode.Mode = Display_Mode_Enum.Administrative;
                        currentMode.Admin_Type = Admin_Type_Enum.Default_Metadata;
                        currentMode.My_Sobek_SubMode = String.Empty;
                        currentMode.Redirect();
                    }
                    else
                    {
                        Cached_Data_Manager.Remove_Digital_Resource_Object(user.UserID, item.BibID, item.VID, null);

                        currentMode.Mode = Display_Mode_Enum.Item_Display;
                        currentMode.Redirect();
                    }
                    return;
                }

                // Save these changes to bib
                template.Save_To_Bib(item, user, ((int) page));

                // See if the user asked for a new element of a complex form type
                delayed_popup = String.Empty;
                switch (hidden_request.Trim())
                {
                    case "name":
                        delayed_popup = "name";
                        item.Bib_Info.Add_Named_Entity(String.Empty).Name_Type = Name_Info_Type_Enum.personal;
                        break;

                    case "title":
                        delayed_popup = "title";
                        item.Bib_Info.Add_Other_Title(String.Empty, Title_Type_Enum.alternative);
                        break;

                    case "subject":
                        delayed_popup = "subject";
                        item.Bib_Info.Add_Subject();
                        break;

                    case "spatial":
                        delayed_popup = "spatial";
                        item.Bib_Info.Add_Hierarchical_Geographic_Subject();
                        break;

                    case "relateditem":
                        delayed_popup = "relateditem";
                        item.Bib_Info.Add_Related_Item(new Related_Item_Info());
                        break;

                    case "save":
                        Complete_Item_Save();
                        break;

                    case "complicate":
                        item.Using_Complex_Template = true;
                        HttpContext.Current.Response.Redirect( "?" + HttpContext.Current.Request.QueryString, false);
                        HttpContext.Current.ApplicationInstance.CompleteRequest();
                        currentMode.Request_Completed = true;
                        return;

                    case "simplify":
                        item.Using_Complex_Template = false;
                        HttpContext.Current.Response.Redirect( "?" + HttpContext.Current.Request.QueryString, false);
                        HttpContext.Current.ApplicationInstance.CompleteRequest();
                        currentMode.Request_Completed = true;
                        return;
                }

                // Was this for a new page?
                if (hidden_request.IndexOf("newpage") == 0)
                {
                    string page_requested = hidden_request.Replace("newpage", "");
                    if (page_requested != currentMode.My_Sobek_SubMode)
                    {
                        // forward to requested page
                        currentMode.My_Sobek_SubMode = page_requested;
                        if (currentMode.My_Sobek_SubMode == "0")
                            currentMode.My_Sobek_SubMode = "preview";
                        if (isProject)
                            currentMode.My_Sobek_SubMode = page_requested + item.BibID;

                        HttpContext.Current.Response.Redirect(currentMode.Redirect_URL() + "#template", false);
                        HttpContext.Current.ApplicationInstance.CompleteRequest();
                        currentMode.Request_Completed = true;
                    }
                }
            }
        }
        /// <summary> Writes the static footer to go at the bottom of the static digital resource page </summary>
        /// <param name="Writer"> Open stream to write the HTML footer to </param>
        /// <param name="HTMLSkin"> Default html web skin/interface</param>
        public void Display_Footer(TextWriter Writer, SobekCM_Skin_Object HTMLSkin)
        {
            // Get the current contact URL
            Display_Mode_Enum thisMode = currentMode.Mode;
            currentMode.Mode = Display_Mode_Enum.Contact;
            string contact = currentMode.Redirect_URL();

            // Restore the old mode
            currentMode.Mode = thisMode;

            Writer.WriteLine(currentMode.Mode == Display_Mode_Enum.Item_Display
                                 ? HTMLSkin.Footer_Item_HTML.Replace("<%CONTACT%>", contact).Replace("<%URLOPTS%>", "").Replace("<%?URLOPTS%>", "").Replace("<%&URLOPTS%>", "").Replace("<%VERSION%>", "").Replace("<%BASEURL%>", currentMode.Base_URL).Trim()
                                 : HTMLSkin.Footer_HTML.Replace("<%CONTACT%>", contact).Replace("<%URLOPTS%>", "").Replace("<%?URLOPTS%>", "").Replace("<%&URLOPTS%>", "").Replace("<%VERSION%>", "").Replace("<%BASEURL%>", currentMode.Base_URL).Trim());
        }
        /// <summary> Constructor creates a new instance of the Aggregation_HtmlSubwriter class </summary>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Browse_Object"> Object contains all the basic information about any browse or info display </param>
        /// <param name="Paged_Results"> Paged results to display within a browse or search result </param>
        /// <param name="Results_Statistics"> Information about the entire set of results for a search or browse </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Thematic_Headings"> Headings under which all the highlighted collections on the home page are organized </param>
        /// <param name="Current_User"> Currently logged on user </param>
        /// <param name="IP_Restrictions"> IP restrictions, used to determine if a user has access to a particular item </param>
        /// <param name="Static_Web_Content"> HTML content-based browse, info, or imple CMS-style web content objects.  These are objects which are read from a static HTML file and much of the head information must be maintained </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public Aggregation_HtmlSubwriter(Item_Aggregation Hierarchy_Object, 
            SobekCM_Navigation_Object Current_Mode, SobekCM_Skin_Object HTML_Skin, 
            Language_Support_Info Translator, 
            Item_Aggregation_Browse_Info Browse_Object,
            Search_Results_Statistics Results_Statistics,
            List<iSearch_Title_Result> Paged_Results,
            Aggregation_Code_Manager Code_Manager, Item_Lookup_Object All_Items_Lookup,
            List<Thematic_Heading> Thematic_Headings, User_Object Current_User,
            IP_Restriction_Ranges IP_Restrictions,
            HTML_Based_Content Static_Web_Content,
            Custom_Tracer Tracer )
        {
            currentUser = Current_User;
            base.Hierarchy_Object = Hierarchy_Object;
            currentMode = Current_Mode;
            Skin = HTML_Skin;
            translator = Translator;
            thisBrowseObject = Browse_Object;
            thisStaticBrowseObject = Static_Web_Content;
            codeManager = Code_Manager;
            itemList = All_Items_Lookup;
            thematicHeadings = Thematic_Headings;
            ipRestrictions = IP_Restrictions;
            resultsStatistics = Results_Statistics;
            pagedResults = Paged_Results;

            NameValueCollection form = HttpContext.Current.Request.Form;
            if (form["item_action"] != null)
            {
                string action = form["item_action"].ToLower().Trim();

                if (action == "add_aggregation")
                {
                    SobekCM_Database.User_Set_Aggregation_Home_Page_Flag(currentUser.UserID, base.Hierarchy_Object.Aggregation_ID, true, Tracer);
                    currentUser.Set_Aggregation_Home_Page_Flag(base.Hierarchy_Object.Code, base.Hierarchy_Object.Name, true);
                    HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "Added aggregation to your home page");
                }

                if (action == "remove_aggregation")
                {
                    int removeAggregationID = base.Hierarchy_Object.Aggregation_ID;
                    string remove_code = base.Hierarchy_Object.Code;
                    string remove_name = base.Hierarchy_Object.Name;

                    if ((form["aggregation"] != null) && (form["aggregation"].Length > 0))
                    {
                        Item_Aggregation_Related_Aggregations aggrInfo = codeManager[form["aggregation"]];
                        if (aggrInfo != null)
                        {
                            remove_code = aggrInfo.Code;
                            removeAggregationID = aggrInfo.ID;
                        }
                    }

                    SobekCM_Database.User_Set_Aggregation_Home_Page_Flag(currentUser.UserID, removeAggregationID, false, Tracer);
                    currentUser.Set_Aggregation_Home_Page_Flag(remove_code, remove_name, false);

                    if (currentMode.Home_Type != Home_Type_Enum.Personalized)
                    {
                        HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "Removed aggregation from your home page");
                    }
                }

                if (action == "private_folder")
                {
                    User_Folder thisFolder = currentUser.Get_Folder(form["aggregation"]);
                    if (SobekCM_Database.Edit_User_Folder(thisFolder.Folder_ID, currentUser.UserID, -1, thisFolder.Folder_Name, false, String.Empty, Tracer) >= 0)
                        thisFolder.isPublic = false;
                }

                if (action == "email")
                {
                    string address = form["email_address"].Replace(";", ",").Trim();
                    string comments = form["email_comments"].Trim();
                    string format = form["email_format"].Trim().ToUpper();

                    if (address.Length > 0)
                    {
                        // Determine the email format
                        bool is_html_format = true;
                        if (format == "TEXT")
                            is_html_format = false;

                        // CC: the user, unless they are already on the list
                        string cc_list = currentUser.Email;
                        if (address.ToUpper().IndexOf(currentUser.Email.ToUpper()) >= 0)
                            cc_list = String.Empty;

                        // Send the email
                        string any_error = URL_Email_Helper.Send_Email(address, cc_list, comments, currentUser.Full_Name, currentMode.SobekCM_Instance_Abbreviation, is_html_format, HttpContext.Current.Items["Original_URL"].ToString(), base.Hierarchy_Object.Name, "home");
                        HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", any_error.Length > 0 ? any_error : "Your email has been sent");

                        currentMode.isPostBack = true;

                        // Do this to force a return trip (cirumnavigate cacheing)
                        string original_url = HttpContext.Current.Items["Original_URL"].ToString();
                        if (original_url.IndexOf("?") < 0)
                            HttpContext.Current.Response.Redirect(original_url + "?p=" + DateTime.Now.Millisecond, false);
                        else
                            HttpContext.Current.Response.Redirect(original_url + "&p=" + DateTime.Now.Millisecond, false);
                    }
                }
            }

            // If this is a search, verify it is a valid search type
            if (currentMode.Mode == Display_Mode_Enum.Search)
            {
                // Not every collection has every search type...
                ReadOnlyCollection<Search_Type_Enum> possibleSearches = base.Hierarchy_Object.Search_Types;
                if (!possibleSearches.Contains(currentMode.Search_Type))
                {
                    bool found_valid = false;

                    if ((currentMode.Search_Type == Search_Type_Enum.Full_Text) && (possibleSearches.Contains(Search_Type_Enum.dLOC_Full_Text)))
                    {
                        found_valid = true;
                        currentMode.Search_Type = Search_Type_Enum.dLOC_Full_Text;
                    }

                    if ((!found_valid) && (currentMode.Search_Type == Search_Type_Enum.Basic) && (possibleSearches.Contains(Search_Type_Enum.Newspaper)))
                    {
                        found_valid = true;
                        currentMode.Search_Type = Search_Type_Enum.Newspaper;
                    }

                    if (( !found_valid ) && ( possibleSearches.Count > 0 ))
                    {
                        found_valid = true;
                        currentMode.Search_Type = possibleSearches[0];
                    }

                    if ( !found_valid )
                    {
                        currentMode.Mode = Display_Mode_Enum.Aggregation_Home;
                    }
                }
            }

            if (currentMode.Mode == Display_Mode_Enum.Search)
            {
                collectionViewer = AggregationViewer_Factory.Get_Viewer(currentMode.Search_Type, base.Hierarchy_Object, currentMode, currentUser);
            }

            if (currentMode.Mode == Display_Mode_Enum.Aggregation_Home)
            {
                collectionViewer = AggregationViewer_Factory.Get_Viewer(base.Hierarchy_Object.Views_And_Searches[0], base.Hierarchy_Object, currentMode);
            }

            if (currentMode.Mode == Display_Mode_Enum.Aggregation_Browse_Info)
            {
                if ( resultsStatistics == null )
                {
                    collectionViewer = new Static_Browse_Info_AggregationViewer(thisBrowseObject, thisStaticBrowseObject);
                }
                else
                {
                    collectionViewer = new DataSet_Browse_Info_AggregationViewer(thisBrowseObject, resultsStatistics, pagedResults, codeManager, itemList, currentUser );
                }
            }

            if (currentMode.Mode == Display_Mode_Enum.Aggregation_Browse_By)
            {
                collectionViewer = new Metadata_Browse_AggregationViewer( Current_Mode, Hierarchy_Object, Tracer );
            }

            if (currentMode.Mode == Display_Mode_Enum.Aggregation_Browse_Map)
            {
                collectionViewer = new Map_Browse_AggregationViewer(Current_Mode, Hierarchy_Object, Tracer);
            }

            if (currentMode.Mode == Display_Mode_Enum.Aggregation_Item_Count)
            {
                collectionViewer = new Item_Count_AggregationViewer(Current_Mode, Hierarchy_Object);
            }

            if (currentMode.Mode == Display_Mode_Enum.Aggregation_Usage_Statistics)
            {
                collectionViewer = new Usage_Statistics_AggregationViewer(Current_Mode, Hierarchy_Object);
            }

            if (currentMode.Mode == Display_Mode_Enum.Aggregation_Private_Items)
            {
                collectionViewer = new Private_Items_AggregationViewer(Current_Mode, Hierarchy_Object, Tracer);
            }

            if (currentMode.Mode == Display_Mode_Enum.Aggregation_Admin_View)
            {
                collectionViewer = new Admin_AggregationViewer(Hierarchy_Object);
            }

            if (collectionViewer != null)
            {
                collectionViewer.Translator = translator;
                collectionViewer.HTML_Skin = HTML_Skin;
                collectionViewer.CurrentMode = Current_Mode;
                collectionViewer.CurrentObject = Hierarchy_Object;
                collectionViewer.Current_User = Current_User;

                // Pull the standard values
                switch (collectionViewer.Selection_Panel_Display)
                {
                    case Selection_Panel_Display_Enum.Selectable:
                        if (form["show_subaggrs"] != null)
                        {
                            string show_subaggrs = form["show_subaggrs"].ToUpper();
                            if (show_subaggrs == "TRUE")
                                currentMode.Show_Selection_Panel = true;
                        }
                        break;

                    case Selection_Panel_Display_Enum.Always:
                        currentMode.Show_Selection_Panel = true;
                        break;
                }
            }
        }
        /// <summary> Writes the static header to go at the top of the static digital resource page </summary>
        /// <param name="Writer"> Open stream to write the HTML header to </param>
        /// <param name="HTMLSkin"> Default html web skin/interface</param>
        /// <param name="CurrentItem"> Current item, to include the aggregations in the breadcrumbs </param>
        public void Display_Header(TextWriter Writer, SobekCM_Skin_Object HTMLSkin, SobekCM_Item CurrentItem )
        {
            StringBuilder breadcrumb_builder = new StringBuilder("<a href=\"" + currentMode.Base_URL + "\">" + SobekCM_Library_Settings.System_Abbreviation + " Home</a>");

            int codes_added = 0;
                if (CurrentItem.Behaviors.Aggregation_Count > 0)
                {
                    foreach (Aggregation_Info aggregation in CurrentItem.Behaviors.Aggregations)
                    {
                        string aggrCode = aggregation.Code;
                        if (aggrCode.ToLower() != currentMode.Aggregation)
                        {
                            if ((aggrCode.ToUpper() != "I" + CurrentItem.Bib_Info.Source.Code.ToUpper()) &&
                                (aggrCode.ToUpper() != "I" + CurrentItem.Bib_Info.Location.Holding_Code.ToUpper()))
                            {
                                Item_Aggregation_Related_Aggregations thisAggr = codeManager[aggrCode];
                                if ((thisAggr != null) && (thisAggr.Active))
                                {
                                    breadcrumb_builder.Append(" &nbsp;|&nbsp; <a href=\"" + currentMode.Base_URL +
                                                              aggrCode.ToLower() + "\">" +
                                                              thisAggr.ShortName +
                                                              "</a>");
                                    codes_added++;
                                }
                            }
                        }
                        if (codes_added == 5)
                            break;
                    }
                }

            if (codes_added < 5)
            {
                if (CurrentItem.Bib_Info.Source.Code.Length > 0)
                {
                    // Add source code
                    string source_code = CurrentItem.Bib_Info.Source.Code;
                    if ((source_code[0] != 'i') && (source_code[0] != 'I'))
                        source_code = "I" + source_code;
                    Item_Aggregation_Related_Aggregations thisSourceAggr = codeManager[source_code];
                    if ((thisSourceAggr != null) && (!thisSourceAggr.Hidden) && (thisSourceAggr.Active))
                    {
                        string source_name = thisSourceAggr.ShortName;
                        if (source_name.ToUpper() != "ADDED AUTOMATICALLY")
                        {
                            breadcrumb_builder.Append(" &nbsp;|&nbsp; <a href=\"" + currentMode.Base_URL +
                                                      source_code.ToLower() + "\">" +
                                                      source_name + "</a>");
                        }
                    }

                    // Add the holding code
                    if ((CurrentItem.Bib_Info.Location.Holding_Code.Length > 0) &&
                        (CurrentItem.Bib_Info.Location.Holding_Code != CurrentItem.Bib_Info.Source.Code))
                    {
                        // Add holding code
                        string holding_code = CurrentItem.Bib_Info.Location.Holding_Code;
                        if ((holding_code[0] != 'i') && (holding_code[0] != 'I'))
                            holding_code = "I" + holding_code;

                        Item_Aggregation_Related_Aggregations thisAggr = codeManager[holding_code];
                        if ((thisAggr != null) && (!thisAggr.Hidden) && (thisAggr.Active))
                        {
                            string holding_name = thisAggr.ShortName;

                            if (holding_name.ToUpper() != "ADDED AUTOMATICALLY")
                            {
                                breadcrumb_builder.Append(" &nbsp;|&nbsp; <a href=\"" + currentMode.Base_URL +
                                                          holding_code.ToLower() + "\">" +
                                                          holding_name + "</a>");
                            }
                        }
                    }
                }
                else
                {
                    if (CurrentItem.Bib_Info.Location.Holding_Code.Length > 0)
                    {
                        // Add holding code
                        string holding_code = CurrentItem.Bib_Info.Location.Holding_Code;
                        if ((holding_code[0] != 'i') && (holding_code[0] != 'I'))
                            holding_code = "I" + holding_code;
                        string holding_name = codeManager.Get_Collection_Short_Name(holding_code);
                        if (holding_name.ToUpper() != "ADDED AUTOMATICALLY")
                        {
                            breadcrumb_builder.Append(" &nbsp;|&nbsp; <a href=\"" + currentMode.Base_URL +
                                                      holding_code.ToLower() + "\">" +
                                                      holding_name + "</a>");
                        }
                    }
                }
            }
            string breadcrumbs = breadcrumb_builder.ToString();

            Writer.WriteLine(HTMLSkin.Header_Item_HTML.Replace("<%URLOPTS%>", "").Replace("<%?URLOPTS%>", "").Replace("<%&URLOPTS%>", "").Replace("<%BREADCRUMBS%>", breadcrumbs).Replace("<%MYSOBEK%>", "").Replace("<%ENGLISH%>", "").Replace("<%FRENCH%>", "").Replace("<%SPANISH%>", "").Replace("<%LOWGRAPHICS%>", "").Replace("<%HIGHGRAPHICS%>", "").Replace("<%BASEURL%>", currentMode.Base_URL).Replace("<%BANNER%>",String.Empty));
            Writer.WriteLine(String.Empty);
        }
        /// <summary> Constructor for a new instance of the Group_Add_Volume_MySobekViewer class </summary>
        /// <param name="User"> Authenticated user information </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="All_Items_Lookup"> Allows individual items to be retrieved by various methods as <see cref="Single_Item"/> objects.</param>
        /// <param name="Current_Item"> Individual digital resource to be edited by the user </param>
        /// <param name="Code_Manager"> Code manager contains the list of all valid aggregation codes </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="Items_In_Title"> List of items within this title </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="HTML_Skin_Collection"> HTML Web skin collection which controls the overall appearance of this digital library </param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        public Group_Add_Volume_MySobekViewer(User_Object User,
            SobekCM_Navigation_Object Current_Mode,
            Item_Lookup_Object All_Items_Lookup,
            SobekCM_Item Current_Item, Aggregation_Code_Manager Code_Manager,
            Dictionary<string, Wordmark_Icon> Icon_Table,
            SobekCM_Skin_Object HTML_Skin,
            SobekCM_Items_In_Title Items_In_Title,
            Language_Support_Info Translator,
			SobekCM_Skin_Collection HTML_Skin_Collection,
            Custom_Tracer Tracer)
            : base(User)
        {
            Tracer.Add_Trace("Group_Add_Volume_MySobekViewer.Constructor", String.Empty);

            currentMode = Current_Mode;
            item = Current_Item;
            itemList = All_Items_Lookup;
            codeManager = Code_Manager;
            iconList = Icon_Table;
            webSkin = HTML_Skin;
            itemsInTitle = Items_In_Title;
            base.Translator = Translator;
            skins = HTML_Skin_Collection;

            // Set some defaults
            ipRestrict = -1;
            title = String.Empty;
            date = String.Empty;
            level1 = String.Empty;
            level2 = String.Empty;
            level3 = String.Empty;
            level1Order = -1;
            level2Order = -1;
            level3Order = -1;
            hierarchyCopiedFromDate = false;
            message = String.Empty;
            trackingBox = String.Empty;
            bornDigital = false;
            materialRecdDate = null;
            materialRecdNotes = String.Empty;
            dispositionAdvice = -1;
            dispositionAdviceNotes = String.Empty;

            // If the user cannot edit this item, go back
            if (!user.Can_Edit_This_Item(item))
            {
                currentMode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                currentMode.Redirect();
                return;
            }

            // Determine the default template code
            string template_code = "addvolume";
            if (!user.Include_Tracking_In_Standard_Forms)
                template_code = "addvolume_notracking";

            // Load this template
            template = Cached_Data_Manager.Retrieve_Template(template_code, Tracer);
            if (template != null)
            {
                Tracer.Add_Trace("Group_Add_Volume_MySobekViewer.Constructor", "Found template in cache");
            }
            else
            {
                Tracer.Add_Trace("Group_Add_Volume_MySobekViewer.Constructor", "Reading template file");

                // Read this template
                Template_XML_Reader reader = new Template_XML_Reader();
                template = new Template();
                reader.Read_XML(SobekCM_Library_Settings.Base_MySobek_Directory + "templates\\defaults\\" + template_code + ".xml", template, true);

                // Add the current codes to this template
                template.Add_Codes(Code_Manager);

                // Save this into the cache
                Cached_Data_Manager.Store_Template(template_code, template, Tracer);
            }

            // See if there was a hidden request
            string hidden_request = HttpContext.Current.Request.Form["action"] ?? String.Empty;

            // If this was a cancel request do that
            if (hidden_request == "cancel")
            {
                currentMode.Mode = Display_Mode_Enum.Item_Display;
                currentMode.Redirect();
            }
            else if (hidden_request.IndexOf("save") == 0 )
            {
                // Get the VID that used as a source for this
                string vid = HttpContext.Current.Request.Form["base_volume"];

                if (string.IsNullOrEmpty(vid))
                {
                     message = "<span style=\"color: red\"><strong>No base volume selected!</strong></span>";
                }
                else
                {
                    try
                    {
                        // Get a new instance of this item
                        SobekCM_Item saveItem = SobekCM_Item_Factory.Get_Item(Current_Mode.BibID, vid, Icon_Table, null, Tracer);

                        // Clear some values for this item
                        saveItem.VID = String.Empty;
                        saveItem.Divisions.Clear();
                        saveItem.Behaviors.Serial_Info.Clear();
                        saveItem.Bib_Info.Series_Part_Info.Clear();
                        saveItem.Behaviors.Clear_Ticklers();
                        saveItem.Tracking.Internal_Comments = String.Empty;
                        saveItem.Bib_Info.Location.PURL = String.Empty;
                        saveItem.Behaviors.Main_Thumbnail = String.Empty;
                        saveItem.METS_Header.Create_Date = DateTime.Now;
                        saveItem.METS_Header.Modify_Date = saveItem.METS_Header.Create_Date;
                        saveItem.METS_Header.Creator_Software = "SobekCM Web - Online add a volume (derived from VID " + vid + ")";
                        saveItem.METS_Header.Clear_Creator_Individual_Notes();
                        saveItem.METS_Header.Creator_Individual = user.Full_Name;
                        saveItem.Bib_Info.Location.Other_URL = String.Empty;
                        saveItem.Bib_Info.Location.Other_URL_Display_Label = String.Empty;
                        saveItem.Bib_Info.Location.Other_URL_Note = String.Empty;

                        // Save the template changes to this item
                        template.Save_To_Bib(saveItem, user, 1);

                        // Save this item and copy over
                        complete_item_submission(saveItem, Tracer);

                        // Clear the volume list
                        Cached_Data_Manager.Remove_Items_In_Title(saveItem.BibID, Tracer);

                        // Forward differently depending on request
                        switch (hidden_request)
                        {
                            case "save_edit":
                                currentMode.Mode = Display_Mode_Enum.My_Sobek;
                                currentMode.My_Sobek_Type = My_Sobek_Type_Enum.Edit_Item_Metadata;
                                currentMode.VID = saveItem.VID;
                                currentMode.Redirect();
                                break;

                            case "save_again":
                                // No redirect, but save values
                                date = saveItem.Bib_Info.Origin_Info.Date_Issued;
                                ipRestrict = saveItem.Behaviors.IP_Restriction_Membership;
                                trackingBox = saveItem.Tracking.Tracking_Box;
                                bornDigital = saveItem.Tracking.Born_Digital;
                                dispositionAdvice = saveItem.Tracking.Disposition_Advice;
                                dispositionAdviceNotes = saveItem.Tracking.Disposition_Advice_Notes;
                                materialRecdDate = saveItem.Tracking.Material_Received_Date;
                                materialRecdNotes = saveItem.Tracking.Material_Received_Notes;
                                if (!hierarchyCopiedFromDate)
                                {
                                    if (saveItem.Behaviors.Serial_Info.Count > 0)
                                    {
                                        level1 = saveItem.Behaviors.Serial_Info[0].Display;
                                        level1Order = saveItem.Behaviors.Serial_Info[0].Order;
                                    }
                                    if (saveItem.Behaviors.Serial_Info.Count > 1)
                                    {
                                        level2 = saveItem.Behaviors.Serial_Info[1].Display;
                                        level2Order = saveItem.Behaviors.Serial_Info[1].Order;
                                    }
                                    if (saveItem.Behaviors.Serial_Info.Count > 2)
                                    {
                                        level3 = saveItem.Behaviors.Serial_Info[2].Display;
                                        level3Order = saveItem.Behaviors.Serial_Info[2].Order;
                                    }
                                }
                                message = message + "<span style=\"color: blue\"><strong>Saved new volume ( " + saveItem.BibID + " : " + saveItem.VID + ")</strong></span>";
                                break;

                            case "save_addfiles":
                                currentMode.Mode = Display_Mode_Enum.My_Sobek;
                                currentMode.My_Sobek_Type = My_Sobek_Type_Enum.File_Management;
                                currentMode.VID = saveItem.VID;
                                currentMode.Redirect();
                                break;

                            default:
                                currentMode.Mode = Display_Mode_Enum.Item_Display;
                                currentMode.VID = saveItem.VID;
                                currentMode.Redirect();
                                break;
                        }

                    }
                    catch ( Exception ee )
                    {
                        message = message + "<br /><span style=\"color: red\"><strong>EXCEPTION CAUGHT!<br /><br />" + ee.Message + "<br /><br />" + ee.StackTrace.Replace("\n","<br />") + "</strong></span>";

                    }
                }
            }
        }
 /// <summary> Writes the static header to go at the top of the static digital resource page </summary>
 /// <param name="Writer"> Open stream to write the HTML header to </param>
 /// <param name="HTMLSkin"> Default html web skin/interface</param>
 /// <param name="Banner"> Banner HTML</param>
 public void Display_Header(TextWriter Writer, SobekCM_Skin_Object HTMLSkin, string Banner)
 {
     string breadcrumbs = "<a href=\"" + currentMode.Base_URL + "\">" + SobekCM_Library_Settings.System_Name + " Home</a>";
     Writer.WriteLine(HTMLSkin.Header_Item_HTML.Replace("<%URLOPTS%>", "").Replace("<%?URLOPTS%>", "").Replace("<%&URLOPTS%>", "").Replace("<%BREADCRUMBS%>", breadcrumbs).Replace("<%MYSOBEK%>", "").Replace("<%ENGLISH%>", "").Replace("<%FRENCH%>", "").Replace("<%SPANISH%>", "").Replace("<%LOWGRAPHICS%>", "").Replace("<%HIGHGRAPHICS%>", "").Replace("<%BASEURL%>", currentMode.Base_URL).Replace("<%BANNER%>", Banner));
     Writer.WriteLine(String.Empty);
 }
        /// <summary> Stores the html skin object to the cache or caching server </summary>
        /// <param name="Skin_Code"> Code for this html display skin </param>
        /// <param name="Language_Code"> Current language code for the user interface ( skins are language-specific)</param>
        /// <param name="StoreObject"> HTML Skin object </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        public static void Store_Skin( string Skin_Code, string Language_Code, SobekCM_Skin_Object StoreObject, Custom_Tracer Tracer)
        {
            // If the cache is disabled, just return before even tracing
            if ((Disabled) || ( StoreObject == null ))
                return;

            // Determine the key
            string key = "SKIN_" + Skin_Code.ToLower();
            if ((Language_Code.Length > 0) && (Language_Code != "en"))
                key = key + "_" + Language_Code;

            // Check the number of item aggregations currently locally cached
            if ((LOCALLY_CACHED_SKINS_LIMIT > 0) || ( !caching_serving_enabled ))
            {
                int items_cached = HttpContext.Current.Cache.Cast<DictionaryEntry>().Count(ThisItem => ThisItem.Key.ToString().IndexOf("SKIN_") == 0);

                // Locally cache if this doesn't exceed the limit
                if ((items_cached < LOCALLY_CACHED_SKINS_LIMIT) || ( !caching_serving_enabled ))
                {
                    if (Tracer != null)
                    {
                        Tracer.Add_Trace("Cached_Data_Manager.Store_Skin", "Adding object '" + key + "' to the local cache with expiration of 1 minute");
                    }

                    HttpContext.Current.Cache.Insert(key, StoreObject, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(1));
                }
            }

            // try to store in the caching server, if enabled
            if (caching_serving_enabled)
            {
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Cached_Data_Manager.Store_Skin", "Adding object '" + key + "' to the caching server");
                }

                AppFabric_Manager.Add(key, StoreObject, Tracer);
            }
        }
        /// <summary> Constructor for a new instance of the MySobek_HtmlSubwriter class </summary>
        /// <param name="Results_Statistics"> Information about the entire set of results for a browse of a user's bookshelf folder </param>
        /// <param name="Paged_Results"> Single page of results for a browse of a user's bookshelf folder, within the entire set </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Current_Item">Current item to edit, if the user is requesting to edit an item</param>
        /// <param name="Current_User"> Currently logged on user </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="Stats_Date_Range"> Object contains the start and end dates for the statistical data in the database </param>
        /// <param name="HTML_Skin_Collection"> HTML Web skin collection which controls the overall appearance of this digital library </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public MySobek_HtmlSubwriter(Search_Results_Statistics Results_Statistics,
                                     List<iSearch_Title_Result> Paged_Results,
                                     Aggregation_Code_Manager Code_Manager,
                                     Item_Lookup_Object All_Items_Lookup,
                                     Item_Aggregation Hierarchy_Object,
                                     SobekCM_Skin_Object HTML_Skin,
                                     Language_Support_Info Translator,
                                     SobekCM_Navigation_Object Current_Mode,
                                     SobekCM_Item Current_Item,
                                     User_Object Current_User,
                                     Dictionary<string, Wordmark_Icon> Icon_Table,
                                     Statistics_Dates Stats_Date_Range,
									 SobekCM_Skin_Collection HTML_Skin_Collection,
                                     Custom_Tracer Tracer )
        {
            Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Saving values and geting user object back from the session");

            resultsStatistics = Results_Statistics;
            pagedResults = Paged_Results;
            codeManager = Code_Manager;
            itemList = All_Items_Lookup;
            htmlSkin = HTML_Skin;
            translator = Translator;
            currentCollection = Hierarchy_Object;
            currentItem = Current_Item;
            user = Current_User;
            iconTable = Icon_Table;
            statsDates = Stats_Date_Range;

            if (Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Log_Out)
            {
                Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Performing logout");

                HttpContext.Current.Session["user"] = null;
                HttpContext.Current.Response.Redirect("?", false);
                HttpContext.Current.ApplicationInstance.CompleteRequest();
                Current_Mode.Request_Completed = true;
                return;
            }

            if ((Current_Mode.My_Sobek_Type != My_Sobek_Type_Enum.Logon) && (user != null) && (user.Is_Temporary_Password))
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.New_Password;
            }

            if (Current_Mode.Logon_Required)
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Logon;

            Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Building the my sobek viewer object");
            switch (Current_Mode.My_Sobek_Type)
            {
                case My_Sobek_Type_Enum.Home:
                    mySobekViewer = new Home_MySobekViewer(user, Tracer);
                    break;

                case My_Sobek_Type_Enum.New_Item:
                    mySobekViewer = new New_Group_And_Item_MySobekViewer(user, Current_Mode, itemList, codeManager, iconTable, htmlSkin, translator, HTML_Skin_Collection, Tracer);
                    break;

                case My_Sobek_Type_Enum.Folder_Management:
                    mySobekViewer = new Folder_Mgmt_MySobekViewer(user, resultsStatistics, pagedResults, codeManager, itemList, currentCollection, htmlSkin, translator, Current_Mode, Tracer);
                    break;

                case My_Sobek_Type_Enum.Saved_Searches:
                    mySobekViewer = new Saved_Searches_MySobekViewer(user, translator, Current_Mode, Tracer);
                    break;

                case My_Sobek_Type_Enum.Preferences:
                    mySobekViewer = new Preferences_MySobekViewer(user, Current_Mode, Tracer);
                    break;

                case My_Sobek_Type_Enum.Logon:
                    mySobekViewer = new Logon_MySobekViewer(Current_Mode, Tracer);
                    break;

                case My_Sobek_Type_Enum.New_Password:
                    mySobekViewer = new NewPassword_MySobekViewer(user, Tracer);
                    break;

                case My_Sobek_Type_Enum.Delete_Item:
                    mySobekViewer = new Delete_Item_MySobekViewer(user, Current_Mode, currentItem, All_Items_Lookup, Tracer);
                    break;

                case My_Sobek_Type_Enum.Edit_Item_Behaviors:
                    mySobekViewer = new Edit_Item_Behaviors_MySobekViewer(user, Current_Mode, currentItem, codeManager, Tracer);
                    break;

                case My_Sobek_Type_Enum.Edit_Item_Metadata:
                    mySobekViewer = new Edit_Item_Metadata_MySobekViewer(user, Current_Mode, itemList, currentItem, codeManager, iconTable, htmlSkin, translator, HTML_Skin_Collection, Tracer);
                    break;

                case My_Sobek_Type_Enum.File_Management:
                    mySobekViewer = new File_Management_MySobekViewer(user, Current_Mode, Current_Item, itemList, codeManager, iconTable, htmlSkin, translator, HTML_Skin_Collection, Tracer);
                    break;

                case My_Sobek_Type_Enum.Edit_Group_Behaviors:
                    mySobekViewer = new Edit_Group_Behaviors_MySobekViewer(user, Current_Mode, currentItem, codeManager, Tracer);
                    break;

                case My_Sobek_Type_Enum.Edit_Group_Serial_Hierarchy:
                    mySobekViewer = new Edit_Serial_Hierarchy_MySobekViewer(user);
                    break;

                case My_Sobek_Type_Enum.Item_Tracking:
                    mySobekViewer = new Track_Item_MySobekViewer(user, Current_Mode, Tracer);
                    break;

                case My_Sobek_Type_Enum.Group_Add_Volume:
                    // Pull the list of items tied to this group
                    SobekCM_Items_In_Title itemsInTitle = Cached_Data_Manager.Retrieve_Items_In_Title(currentItem.BibID, Tracer);
                    if (itemsInTitle == null)
                    {
                        // Get list of information about this item group and save the item list
                        DataSet itemDetails = SobekCM_Database.Get_Item_Group_Details(currentItem.BibID, Tracer);
                        itemsInTitle = new SobekCM_Items_In_Title(itemDetails.Tables[1]);

                        // Store in cache if retrieved
                        Cached_Data_Manager.Store_Items_In_Title(currentItem.BibID, itemsInTitle, Tracer);
                    }
                    mySobekViewer = new Group_Add_Volume_MySobekViewer(user, Current_Mode, itemList, currentItem, codeManager, iconTable, htmlSkin, itemsInTitle, translator, HTML_Skin_Collection, Tracer);
                    break;

                case My_Sobek_Type_Enum.Group_AutoFill_Volumes:
                    mySobekViewer = new Group_AutoFill_Volume_MySobekViewer(user);
                    break;

                case My_Sobek_Type_Enum.Group_Mass_Update_Items:
                    mySobekViewer = new Mass_Update_Items_MySobekViewer(user, Current_Mode, currentItem, codeManager, Tracer);
                    break;

                case My_Sobek_Type_Enum.Page_Images_Management:
                    mySobekViewer = new Page_Image_Upload_MySobekViewer(user, Current_Mode, Current_Item, itemList, codeManager, iconTable, htmlSkin, translator, Tracer );
                    break;

                case My_Sobek_Type_Enum.User_Tags:
                    mySobekViewer = new User_Tags_MySobekViewer(user, Tracer);
                    break;

                case My_Sobek_Type_Enum.User_Usage_Stats:
                    mySobekViewer = new User_Usage_Stats_MySobekViewer(user, Current_Mode, statsDates, Tracer);
                    break;
            }

            // Pass in the navigation and translator information
            mySobekViewer.CurrentMode = Current_Mode;
            mySobekViewer.Translator = translator;
        }
        /// <summary>
        ///   Gets the banner image for this aggregation, by language
        /// </summary>
        /// <param name = "Language"> Language code </param>
        /// <param name = "thisWebSkin"> Web skin object which may override the banner</param>
        /// <returns> Either the language-specific banner image, or else the default banner image</returns>
        /// <remarks>
        ///   If NO banner images were included in the aggregation XML, then this could be the empty string.<br /><br />
        ///   If the provided web skin overrides the banner, then use that web skin's banner.
        /// </remarks>
        public string Banner_Image(Web_Language_Enum Language, SobekCM_Skin_Object thisWebSkin)
        {
            // Does the web skin exist and override the banner?  For non-institutional agggregations
            // use the web skin banner HTML instead of the aggregation's banner
            if ((thisWebSkin != null) && (thisWebSkin.Override_Banner) &&
                (Aggregation_Type.ToLower().IndexOf("institution") < 0))
            {
                return thisWebSkin.Banner_HTML;
            }

            // Does this language exist in the banner image lookup dictionary?
            if (bannerImagesByLanguage.ContainsKey(Language))
            {
                return "design/" + objDirectory + bannerImagesByLanguage[Language];
            }

            // Default to the system language then
            if (bannerImagesByLanguage.ContainsKey(SobekCM_Library_Settings.Default_UI_Language))
            {
                return "design/" + objDirectory + bannerImagesByLanguage[SobekCM_Library_Settings.Default_UI_Language];
            }

            // Just return the first, assuming one exists
            return bannerImagesByLanguage.Count > 0 ? bannerImagesByLanguage.ElementAt(0).Value : String.Empty;
        }
        /// <summary> Adds the banner to the response stream from either the html web skin
        /// or from the current item aggreagtion object, depending on flags in the web skin object </summary>
        /// <param name="Output"> Stream to which to write the HTML for the banner </param>
        /// <param name="Banner_Division_Name"> Name for the wrapper division around the banner </param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="CurrentMode"> Mode / navigation information for the current request</param>
        /// <remarks> This is called by several html subwriters that otherwise tell this class to suppress writing the banner </remarks>
        public static void Add_Banner(TextWriter Output, string Banner_Division_Name, SobekCM_Navigation_Object CurrentMode, SobekCM_Skin_Object HTML_Skin, Item_Aggregation Hierarchy_Object)
        {
            Output.WriteLine("<!-- Write the main collection, interface, or institution banner -->");
            if ((HTML_Skin != null) && (HTML_Skin.Override_Banner))
            {
                Output.WriteLine(HTML_Skin.Banner_HTML);
            }
            else
            {
                string url_options = CurrentMode.URL_Options();
                if (url_options.Length > 0)
                    url_options = "?" + url_options;

                if ((Hierarchy_Object != null) && (Hierarchy_Object.Code != "all"))
                {
                    Output.WriteLine("<div id=\"sbkAhs_BannerDiv\"><a alt=\"" + Hierarchy_Object.ShortName + "\" href=\"" + CurrentMode.Base_URL + Hierarchy_Object.Code + url_options + "\"><img id=\"mainBanner\" src=\"" + CurrentMode.Base_URL + Hierarchy_Object.Banner_Image(CurrentMode.Language, HTML_Skin) + "\" alt=\"\" /></a></div>");
                }
                else
                {
                    if ((Hierarchy_Object != null) && (Hierarchy_Object.Banner_Image(CurrentMode.Language, HTML_Skin).Length > 0))
                    {
                        Output.WriteLine("<div id=\"sbkAhs_BannerDiv\"><a href=\"" + CurrentMode.Base_URL + url_options + "\"><img id=\"mainBanner\" src=\"" + CurrentMode.Base_URL + Hierarchy_Object.Banner_Image(CurrentMode.Language, HTML_Skin) + "\" alt=\"\" /></a></div>");
                    }
                    else
                    {
                        string skin_url = CurrentMode.Base_Design_URL + "skins/" + CurrentMode.Skin + "/";
                        Output.WriteLine("<div id=\"sbkAhs_BannerDiv\"><a href=\"" + CurrentMode.Base_URL + url_options + "\"><img id=\"mainBanner\" src=\"" + skin_url + "default.jpg\" alt=\"\" /></a></div>");
                    }
                }
            }
            Output.WriteLine();
        }