[SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // parameter is validated protected void WriteError(PlainTextString message, bool allowReloadCurrentActivity) { FramesetUtil.ValidateNonNullParameter("message", message); string msgToDisplay; // If the message will contain a link to reload the current activity, then add the link to have the // framesetMgr load the activity. We have to do this (rather than a get request) since we need to // re-initialize the RTE object at this point. if (allowReloadCurrentActivity) { JScriptString js = new JScriptString( ResHelper.FormatInvariant( "API_GetFramesetManager().DoChoice(\"{0}\");", FramesetUtil.GetStringInvariant(this.mSession.CurrentActivityId))); string origMessage = message.ToString(); StringBuilder sb = new StringBuilder(origMessage.Length * 2); sb.Append( ResHelper.Format( "{0}<br><br><a href='{1}' >{2}</a>", origMessage, js.ToJavascriptProtocol(), Localization.GetMessage("HID_ReloadCurrentContent"))); msgToDisplay = sb.ToString(); } else { msgToDisplay = message.ToString(); } this.RegisterError( Localization.GetMessage("HID_ServerErrorTitle"), msgToDisplay, false); }
[SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // parameter is validated protected void WriteSubmitPage(string titleHtml, string messageHtml, string saveButtonHtml) { FramesetUtil.ValidateNonNullParameter("messageHtml", messageHtml); string msgToDisplay; bool hasCurrentActivity = this.Session.HasCurrentActivity; // The message will contain a link to submit the attempt. StringBuilder sb = new StringBuilder(messageHtml.Length * 2 + 500); sb.AppendLine("<script>"); // If there is a current activity to return to, allow the user to do that. if (hasCurrentActivity) { sb.AppendLine("function onCancel(event)"); sb.AppendLine("{"); sb.AppendLine(" var frameMgr = API_GetFramesetManager();"); sb.AppendLine(" if (frameMgr.ReadyForNavigation())"); sb.AppendLine(" {"); sb.AppendLine( ResHelper.Format( " frameMgr.DoChoice(\"{0}\");", FramesetUtil.GetStringInvariant(this.mSession.CurrentActivityId))); sb.AppendLine(" }"); sb.AppendLine(" event.cancelBubble = true;"); sb.AppendLine(" event.returnValue = false;"); sb.AppendLine("}"); } sb.AppendLine("function onSubmit(event)"); sb.AppendLine("{"); sb.AppendLine(" var frameMgr = API_GetFramesetManager();"); sb.AppendLine(" if (frameMgr.ReadyForNavigation())"); sb.AppendLine(" {"); sb.AppendLine(" frameMgr.DoSubmit();"); sb.AppendLine(" }"); sb.AppendLine(" event.cancelBubble = true;"); sb.AppendLine(" event.returnValue = false;"); sb.AppendLine("}"); sb.AppendLine("</script>"); sb.AppendLine( ResHelper.Format( "{0}<br><br><input type='button' value='{1}' id='submitBtn' onClick='onSubmit(event)'/>", messageHtml, saveButtonHtml)); if (hasCurrentActivity) { sb.AppendLine( ResHelper.Format( " <input type='button' value='{0}' id='cancelBtn' onClick='onCancel(event)'/>", Localization.GetMessage("POST_ContinueHtml"))); } msgToDisplay = sb.ToString(); this.RegisterError(titleHtml, msgToDisplay, true); this.SubmitPageDisplayed = true; }
/// <summary>Writes the frame manager initialization javascript.</summary> public void WriteFrameMgrInit() { Response.Write(ResHelper.Format("frameMgr.SetAttemptId({0});\r\n", FramesetUtil.GetString(m_attemptId))); Response.Write(ResHelper.Format("frameMgr.SetView({0});\r\n", FramesetUtil.GetString(m_view))); Response.Write("frameMgr.SetPostFrame(\"frameHidden\");\r\n"); Response.Write("frameMgr.SetPostableForm(GetHiddenFrame().contentWindow.document.forms[0]);\r\n"); // Tell frameMgr to move to new activity Response.Write(ResHelper.Format("frameMgr.DoChoice(\"{0}\", true);\r\n", FramesetUtil.GetStringInvariant(m_activityId))); }
/// <summary> /// Gets the string to use to redirect the current response to ChangeActivity page. /// </summary> /// <returns></returns> private string GetRedirectLocation() { string url = ResHelper.Format("./ChangeActivity.aspx?{0}={1}&{2}={3}&{4}={5}", FramesetQueryParameter.View, FramesetUtil.GetString(Session.View), FramesetQueryParameter.AttemptId, FramesetUtil.GetStringInvariant(Session.AttemptId.GetKey()), FramesetQueryParameter.ActivityId, FramesetUtil.GetStringInvariant(Session.CurrentActivityId)); UrlString urlStr = new UrlString(url); return(urlStr.ToAscii()); }
/// <summary> /// Allow application to process posted data. /// </summary> public bool ProcessPostedData(LearningSession session, HttpRequest request, Dictionary <string, HttpPostedFile> fileCollection) { // Verify that posted files map to files that actually exist. HttpFileCollection files = request.Files; StringBuilder messageBuffer = new StringBuilder(); bool firstError = true; foreach (string fileId in files) { HttpPostedFile postedFile = files[fileId]; string filename = postedFile.FileName; // If contentLength == 0 and fileName == emptyString, then this is probably a posting after // the initial file posting. (For instance, to remove the file.) This is a valid file and is added to the // collection. // If the contentLength == 0 and fileName != emptyString, then user is trying to attach a file // that has no contents. This is not allowed. if ((String.IsNullOrEmpty(filename) && (postedFile.ContentLength == 0)) || (!String.IsNullOrEmpty(filename) && (postedFile.ContentLength > 0))) { fileCollection.Add(fileId, postedFile); } else { // This is not a valid file. if (firstError) { messageBuffer.Append(IUDICO.TestingSystem.Localization.getMessage("CON_AttachedFileDoesNotExistHtml")); messageBuffer.Append("\r\n<br><br><ul>\r\n"); firstError = false; } messageBuffer.AppendFormat("<li>{0}</li>", HttpUtility.HtmlEncode(filename)); } } if (!firstError) { messageBuffer.Append("</ul><br>"); messageBuffer.Append(IUDICO.TestingSystem.Localization.getMessage("CON_FileAttachmentErrorEndHtml")); // Add information for the 'Continue' link JScriptString js = new JScriptString(ResHelper.FormatInvariant("API_GetFramesetManager().DoChoice(\"{0}\");", FramesetUtil.GetStringInvariant(session.CurrentActivityId))); messageBuffer.AppendFormat(CultureInfo.CurrentCulture, "<br><br><a href='{0}' >{1}</a>", js.ToJavascriptProtocol(), HttpUtility.HtmlEncode(IUDICO.TestingSystem.Localization.getMessage("HID_ReloadCurrentContent"))); RegisterError(IUDICO.TestingSystem.Localization.getMessage("CON_FileAttachmentErrorTitleHtml"), messageBuffer.ToString(), false); } return(true); }
[SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] // parameter is validated private void WriteTocEntry(HtmlStringWriter sw, TableOfContentsElement currentElement) { FramesetUtil.ValidateNonNullParameter("sw", sw); FramesetUtil.ValidateNonNullParameter("currentElement", currentElement); string activityId = FramesetUtil.GetStringInvariant(currentElement.ActivityId); bool elementHasChildren = currentElement.Children.Count > 0; HtmlString activityIdHtml = new PlainTextString(activityId).ToHtmlString(); HtmlString titleHtml = new PlainTextString(currentElement.Title).ToHtmlString(); // If the current element is visible or is an invisible leaf node, then render it. (If it's an // invisible leaf node, the node will exist but not be visible.) if (RenderThisNode(currentElement)) { sw.AddAttribute(HtmlTextWriterAttribute.Class, new PlainTextString("NodeParent")); sw.AddAttribute("activityId", activityIdHtml); sw.AddAttribute("isValidChoice", (currentElement.IsValidChoiceNavigationDestination ? "true" : "false")); sw.AddAttribute(HtmlTextWriterAttribute.Id, ResHelper.FormatInvariant("div{0}", activityIdHtml)); sw.RenderBeginTag(HtmlTextWriterTag.Div); // #Div1 if (currentElement.IsVisible) { sw.AddAttribute(HtmlTextWriterAttribute.Id, ResHelper.FormatInvariant("icon{0}", activityIdHtml)); if (currentElement.HasVisibleChildren) { sw.AddAttribute(HtmlTextWriterAttribute.Src, "Theme/MinusBtn.gif"); } else { sw.AddAttribute(HtmlTextWriterAttribute.Src, "Theme/Leaf.gif"); } sw.AddAttribute(HtmlTextWriterAttribute.Align, "absMiddle"); sw.RenderBeginTag(HtmlTextWriterTag.Img); sw.RenderEndTag(); sw.AddAttribute(HtmlTextWriterAttribute.Src, "Theme/1px.gif"); sw.AddAttribute(HtmlTextWriterAttribute.Align, "absMiddle"); sw.RenderBeginTag(HtmlTextWriterTag.Img); sw.RenderEndTag(); sw.WriteLine(); sw.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:void(0)"); sw.AddAttribute(HtmlTextWriterAttribute.Id, ResHelper.FormatInvariant("a{0}", activityIdHtml)); if (!currentElement.IsValidChoiceNavigationDestination) { sw.AddAttribute(HtmlTextWriterAttribute.Disabled, "true"); sw.AddAttribute("class", "disable"); } sw.AddAttribute(HtmlTextWriterAttribute.Style, ResHelper.FormatInvariant("FONT-WEIGHT: normal;visibility:{0}", (currentElement.IsVisible ? "visible" : "hidden"))); sw.AddAttribute(HtmlTextWriterAttribute.Title, titleHtml); sw.RenderBeginTag(HtmlTextWriterTag.A); sw.WriteHtml(titleHtml); sw.RenderEndTag(); } } // Write sub-elements (regardless of whether or not this node is rendered) if (elementHasChildren) { sw.WriteLine(); bool clusterStarted = false; if (currentElement.IsVisible) { sw.AddAttribute(HtmlTextWriterAttribute.Id, ResHelper.FormatInvariant("divCluster{0}", activityIdHtml)); sw.AddAttribute(HtmlTextWriterAttribute.Style, "MARGIN-TOP: 5px; DISPLAY: block; MARGIN-LEFT: 18px;"); sw.RenderBeginTag(HtmlTextWriterTag.Div); clusterStarted = true; } foreach (TableOfContentsElement childElement in currentElement.Children) { WriteTocEntry(sw, childElement); } if (clusterStarted) { sw.RenderEndTag(); // end div sw.WriteLine(); } } if (RenderThisNode(currentElement)) { sw.RenderEndTag(); // div (see #Div1, above) sw.WriteLine(); } }
/// <summary> /// Initialize information for the hidden controls and script. This sets up the information to create hidden fields in the form /// and to update the framesetMgr on page load. /// </summary> private void InitHiddenControlInfo(RenderContext context, StringBuilder onLoadScript) { // Should only do this if this is LRM content. Other content does not allow writing to the page. if (Session.CurrentActivityResourceType != ResourceType.Lrm) { return; } IDictionary <string, string> controls = context.FormHiddenControls; // Write the script to define frameMgr in script. WriteFindFrameMgr(onLoadScript); // If the session is attempt-based, then write attempt information if (Session != null) { controls.Add(HiddenFieldNames.AttemptId, FramesetUtil.GetStringInvariant(Session.AttemptId.GetKey())); onLoadScript.AppendFormat("frameMgr.SetAttemptId(document.getElementById({0}).value);\r\n", JScriptString.QuoteString(HiddenFieldNames.AttemptId, false)); } // If the session has ended (that is, is suspended, completed or abandoned), then we're // done. Just return. if (SessionIsEnded) { return; } // Write view to display. controls.Add(HiddenFieldNames.View, FramesetUtil.GetString(Session.View)); onLoadScript.AppendFormat("frameMgr.SetView(document.getElementById({0}).value);\r\n", JScriptString.QuoteString(HiddenFieldNames.View, false)); // Write frame to post. controls.Add(HiddenFieldNames.PostFrame, "frameContent"); onLoadScript.AppendFormat("frameMgr.SetPostFrame(document.getElementById({0}).value);\r\n", JScriptString.QuoteString(HiddenFieldNames.PostFrame, false)); // Set contentFrameUrl to be null. This prevents the content frame from being re-loaded. onLoadScript.Append("frameMgr.SetContentFrameUrl(null);\r\n"); // If a new activity has been identified, then instruct frameMgr to reinitialize the RTE. // BE CAREFUL to do this before setting any other data related to the rte! if (ActivityHasChanged) { string initNewActivity = "false"; if (Session.HasCurrentActivity) { initNewActivity = (CurrentActivityRequiresRte ? "true" : "false"); } onLoadScript.AppendFormat("frameMgr.InitNewActivity( {0} );\r\n", initNewActivity); } // Write the current activity Id. Write -1 if there isn't one. controls.Add(HiddenFieldNames.ActivityId, (Session.HasCurrentActivity ? FramesetUtil.GetStringInvariant(Session.CurrentActivityId) : "-1")); onLoadScript.AppendFormat("frameMgr.SetActivityId(document.getElementById({0}).value);\r\n", JScriptString.QuoteString(HiddenFieldNames.ActivityId, false)); // Write the navigation control state. Format of the control state is a series of T (to show) or F (to hide) // values, separated by semi-colons. The order of controls is: // showNext, showPrevious, showAbandon, showExit, showSave StringBuilder sb = new StringBuilder(10); sb.Append((Session.ShowNext) ? "T" : "F"); sb.Append(";"); sb.Append((Session.ShowPrevious) ? "T" : "F"); sb.Append(";"); sb.Append((Session.ShowAbandon) ? "T" : "F"); sb.Append(";"); sb.Append((Session.ShowExit) ? "T" : "F"); sb.Append(";"); sb.Append((Session.ShowSave) ? "T" : "F"); sb.Append(";"); onLoadScript.AppendFormat("frameMgr.SetNavVisibility( {0}, {1}, {2}, {3}, {4});\r\n", (Session.ShowNext ? "true" : "false"), (Session.ShowPrevious ? "true" : "false"), (Session.ShowAbandon ? "true" : "false"), (Session.ShowExit ? "true" : "false"), (Session.ShowSave ? "true" : "false")); controls.Add(HiddenFieldNames.ShowUI, sb.ToString()); context.Script = onLoadScript.ToString(); }
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] // catching all exceptions in order to return http response code private void RenderPackageContent(string resPath) { // If this is the primary resource of the current activity, then process it for rendering, including (in the case of // LRM content) injecting script to notify client script of page load. if (IsPrimaryResource(resPath)) { // If the resPath is empty or it matches the xmlBase value of the resource of the current activity, // that means it's asking for the default resource associated with the current // activity. Check if there is one. If there isn't, then show a message that indicates the content can't be shown // because there's no resource. if (Session.CurrentActivityResourceType == ResourceType.None) { RegisterError(ResHelper.GetMessage(FramesetResources.CON_ResourceNotFoundTitle), ResHelper.GetMessage(FramesetResources.CON_ResourceNotFoundMsg), false); return; } // If the entry point for the current activity is an absolute Uri, then we should not be here (the // hidden frame should have loaded the absolute Uri into the content frame). if (Session.CurrentActivityEntryPoint.IsAbsoluteUri) { RegisterError(ResHelper.GetMessage(FramesetResources.CON_ResourceNotFoundTitle), ResHelper.GetMessage(FramesetResources.CON_ResourceNotFoundMsg), false); return; } bool fileNotFound = false; // Check if we got an exception indicating the file could not be found try { string filePath = Session.CurrentActivityEntryPoint.OriginalString.Replace("%20", " "); RenderContext context = new RenderContext(filePath, Response); StringBuilder scriptBlock = new StringBuilder(1000); // Initialize the hidden control and script for the page InitHiddenControlInfo(context, scriptBlock); // Allow application to modify the context. UpdateRenderContext(context, scriptBlock, Session); FinishOnLoadScript(scriptBlock); // Save script to context, if neeed if (scriptBlock.Length > 0) { context.Script = scriptBlock.ToString(); } // Clear any previous page information and render the page Session.Render(context); // When the primary resource is rendered, the session may be changed, so save any changes. if (!SessionIsReadOnly) { Session.CommitChanges(); } } catch (FileNotFoundException) { fileNotFound = true; } catch (DirectoryNotFoundException) { fileNotFound = true; } if (fileNotFound) { // The entry point defined in the package was a relative Uri but does not map to a file in the package. RegisterError(ResHelper.GetMessage(FramesetResources.CON_ResourceNotFoundTitle), ResHelper.GetMessage(FramesetResources.CON_ResourceNotFoundMsg), false); return; } } else { long pageId; if (IsPrimaryResourceOfLrmActivity(resPath, out pageId)) { // If this is LRM content and is a request for the primary resource of another activity, then // move to that activity and render a 'please wait' // message that tells the frameset about the new activity. ProcessNavigationRequests(Session); string activityId = "ITEM" + FramesetUtil.GetStringInvariant(pageId); Session.MoveToActivity(activityId); if (!SessionIsReadOnly) { Session.CommitChanges(); } Response.Clear(); Response.Redirect(GetRedirectLocation()); } else { // There was a relative path provided. Write it to the output stream. If this method fails because the path was not // in the package or could not be accessed for some reason, return an error code. try { RenderContext context = new RenderContext(resPath.Replace("%20", " "), Response); UpdateRenderContext(context, null, Session); Session.Render(context); // Session is not changed in non-Execute views, so no need to call CommitChanges(). } catch (ThreadAbortException) { // Do nothing } catch (FileNotFoundException) { Response.StatusCode = 404; Response.StatusDescription = "Not Found"; } catch (HttpException) { // Something wrong with the http connection, so in this case do not set the response // headers. } catch { // This could fail for any number of reasons: invalid content that // refers to non-existant file, or a problem somewhere in the server // code. Return generic error code. Response.StatusCode = 500; Response.StatusDescription = "Internal Server Error"; } } } }
/// <summary>Write initialization code for frameset manager. </summary> /// <remarks> /// This method is called in three possible cases: /// 1. An error condition occurred /// 2. The submit page is being displayed. Note that in this case, since the submit page is registered as displaying an /// error condition, HasError will be true. /// 3. The current activity has changed and we display this page mainly so that the 'please wait' information can be /// displayed and the client can issue a GET request to load the new activity. /// </remarks> public void WriteFrameMgrInit() { // Write frame to post. When displaying an error (which is the case, since we are here) the hidden frame is posted next Response.Write("frameMgr.SetPostFrame('frameHidden');\r\n"); Response.Write("frameMgr.SetPostableForm(window.top.frames[MAIN_FRAME].document.getElementById(HIDDEN_FRAME).contentWindow.document.forms[0]);\r\n"); if (HasError || SubmitPageDisplayed) { // Set the content frame URL to be null. This means the content frame will not be re-loaded by the frameMgr. Response.Write("frameMgr.SetContentFrameUrl(null); \r\n"); } // If there is no session, we can't do anything else if (Session == null) { return; } if ((ActivityHasChanged) && (!SubmitPageDisplayed)) { // Reload the content frame with the new activity. Response.Write(String.Format(CultureInfo.CurrentCulture, "frameMgr.SetContentFrameUrl(\"{0}\"); \r\n", GetContentFrameUrl())); // The new activity may be scorm content, so reinitialize the rte, if needed Response.Write(ResHelper.Format("frameMgr.InitNewActivity( {0} );\r\n", (CurrentActivityRequiresRte ? "true" : "false"))); } Response.Write(ResHelper.Format("frameMgr.SetAttemptId('{0}');\r\n", FramesetUtil.GetStringInvariant(Session.AttemptId.GetKey()))); // Write view to display. Response.Write(String.Format(CultureInfo.CurrentCulture, "frameMgr.SetView('{0}');\r\n", FramesetUtil.GetString(Session.View))); // Write the current activity Id. Write -1 if there isn't one. string activityId; if (SubmitPageDisplayed) { activityId = SubmitId; } else { activityId = (Session.HasCurrentActivity ? FramesetUtil.GetStringInvariant(Session.CurrentActivityId) : "-1"); } Response.Write(String.Format(CultureInfo.InvariantCulture, "frameMgr.SetActivityId({0});\r\n", JScriptString.QuoteString(activityId, true))); // Write nav visibility, in case it's changed since the hidden frame was rendered if (SubmitPageDisplayed) { // If the submit page is being displayed, don't show UI elements Response.Write(String.Format(CultureInfo.CurrentCulture, "frameMgr.SetNavVisibility( {0}, {1}, {2}, {3}, {4});", ("false"), // showNext ("false"), // showPrevious ("false"), // showAbandon ("false"), // showExit (Session.ShowSave ? "true" : "false"))); // If the submit page is now being displayed, make sure the frameset isn't waiting for another commit Response.Write("frameMgr.WaitForContentCompleted(0);\r\n"); } else { Response.Write(String.Format(CultureInfo.CurrentCulture, "frameMgr.SetNavVisibility( {0}, {1}, {2}, {3}, {4});\r\n", (Session.ShowNext ? "true" : "false"), (Session.ShowPrevious ? "true" : "false"), (Session.ShowAbandon ? "true" : "false"), (Session.ShowExit ? "true" : "false"), (Session.ShowSave ? "true" : "false"))); } // Register that the frame loading is complete. This is required so as to notify the frameset of activity id, and // other UI status. Response.Write(String.Format(CultureInfo.InvariantCulture, "frameMgr.RegisterFrameLoad({0});\r\n ", JScriptString.QuoteString("frameContent", false))); if (m_isPostedPage) { // Set PostIsComplete. THIS MUST BE THE LAST VALUE SET! Response.Write("frameMgr.PostIsComplete();"); } }