Example #1
0
        /// <summary>
        /// Writes the file from a byte array directly to the response. The output stream
        /// extension must be set prior to calling this method.
        /// If the response is provided and the path extension is not
        /// in the list of files to use IIS compatibility mode, this is much faster than
        /// copying the file contents to the output stream and should be used whenever possible.
        /// If there is no response object, the method reverts to copying the file between streams.
        /// </summary>
        /// <param name="fileBytes">The file to render.</param>
        internal void WriteFileToResponse(byte[] fileBytes)
        {
            using (Disposer disposer = new Disposer())
            {
                // Open a stream on the file. For some odd reason fxcop does not acknowledge the ability of disposer
                // to actually dispose fileStream, so we give it its own using block.
                using (Stream fileStream = new MemoryStream(fileBytes))
                {
                    // If the response was provided (which it will be, in most non-test cases), then
                    // do the TransmitFile or WriteFile. Otherwise, copy the streams to the response output stream.
                    if (Response != null)
                    {
                        // IisCompatibilityMode is not considered here, because in no case do we have a file
                        // path that can be read by TransmitFile.
                        WriteIisCompatibilityModeToResponse(fileStream);
                    }
                    else
                    {
                        DetachableStream outputDS = new DetachableStream(OutputStream);
                        disposer.Push(outputDS);

                        Utilities.CopyStream(fileStream, ImpersonationBehavior.UseImpersonatedIdentity, outputDS, ImpersonationBehavior.UseImpersonatedIdentity);

                        outputDS.Detach();
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Writes the file from the package directly to the response and set the appropriate
        /// content type in the response. If the response is provided and the path extension is not
        /// in the list of files to use IIS compatibility mode, this is much faster than
        /// copying the file contents to the output stream and should be used whenever possible.
        /// If there is no response object, the method reverts to copying the file between streams.
        /// </summary>
        /// <param name="relativePath">The package-relative path to the file to render.</param>
        internal void WriteFileToResponse(string relativePath)
        {
            // Set the mime type on the response
            string pathExtension = Path.GetExtension(relativePath);

            SetOutputStreamExtension(pathExtension);

            using (Disposer disposer = new Disposer())
            {
                PackageReader pkgReader = m_session.GetPackageReader();
                disposer.Push(pkgReader);

                // If the response was provided (which it will be, in most non-test cases), then
                // do the TransmitFile or WriteFile. Otherwise, copy the streams to the response output stream.
                if (Response != null)
                {
                    // If we are to use Compatibility mode, then write the file
                    if (UseCompatibilityMode(pathExtension))
                    {
                        Stream packageFile = pkgReader.GetFileStream(relativePath);
                        WriteIisCompatibilityModeToResponse(packageFile);
                    }
#if DOTNET40
                    else if (FileIsHtml(pathExtension))
                    {
                        SendHtmlChangingCssHref(pkgReader.GetFileStream(relativePath));
                    }
                    else if (FileIsJavascript(pathExtension))
                    {
                        SendJavascriptChangingCssHref(pkgReader.GetFileStream(relativePath));
                    }
#endif
                    else
                    {
                        pkgReader.TransmitFile(relativePath, m_context.Response);
                    }
                }
                else
                {
                    DetachableStream outputDS = new DetachableStream(OutputStream);
                    disposer.Push(outputDS);

                    Stream packageFile = pkgReader.GetFileStream(relativePath);
                    disposer.Push(packageFile);

                    Utilities.CopyStream(packageFile, ImpersonationBehavior.UseImpersonatedIdentity, outputDS, ImpersonationBehavior.UseImpersonatedIdentity);

                    outputDS.Detach();
                }
            }
        }
Example #3
0
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]    // the writer is disposed for all code paths
        internal static void CopyStream(Stream fromStream, ImpersonationBehavior readImpersonationBehavior, Stream toStream, ImpersonationBehavior writeImpersonationBehavior)
        {
            using (Disposer disposer = new Disposer())
            {
                DetachableStream dsToStream = new DetachableStream(toStream);
                disposer.Push(dsToStream);

                BinaryWriter writer = new BinaryWriter(dsToStream);
                disposer.Push(writer);

                // An addition revert during write operations is required if the setting for reading and writing
                // is not the same
                bool requiresWriteRevert = (readImpersonationBehavior != writeImpersonationBehavior);

                using (ImpersonateIdentity readId = new ImpersonateIdentity(readImpersonationBehavior))
                {
                    byte[] bytesIn = new byte[65536];
                    int    bytesRead;
                    while ((bytesRead = fromStream.Read(bytesIn, 0, bytesIn.Length)) != 0)
                    {
                        // If we have to impersonate to write, then do it. Otherwise skip it.
                        if (requiresWriteRevert)
                        {
                            using (ImpersonateIdentity id = new ImpersonateIdentity(writeImpersonationBehavior))
                            {
                                writer.Write(bytesIn, 0, bytesRead);
                            }
                        }
                        else
                        {
                            writer.Write(bytesIn, 0, bytesRead);
                        }
                    }
                }
                dsToStream.Detach();
            }
        }
Example #4
0
 /// <summary>
 /// If there is an m_result cached from a call to CreateManifestNavigator, return that manifest.
 /// Otherwise, create a manifest using a relaxed conversion.
 /// </summary>
 /// <returns>Contents of the imsmanifest.xml converted from the index.xml.</returns>
 internal Stream ConvertFromIndexXml()
 {
     ConversionResult result;
     if (m_result == null || m_result.Manifest == null)
     {
         result = ManifestConverter.ConvertFromIndexXml(GetFileStream("index.xml"), GetFilePaths(),
             true, ValidationBehavior.None);
     }
     else
     {
         result = m_result;
     }
     using(DetachableStream output = new DetachableStream(result.Manifest.OuterXml.Length))
     {
         using (XmlWriter writer = XmlWriter.Create(output))
         {
             result.Manifest.WriteSubtree(writer);
             writer.Flush();
             output.Detach();
         }
         output.Stream.Seek(0, SeekOrigin.Begin);
         return output.Stream;
     }
 }
Example #5
0
        /// <summary>
        /// Render the requested view into the output stream.
        /// </summary>
        /// <param name="context">The context within which to render the page.</param>
        /// <remarks>
        /// When this method returns the <paramref name="context"/> OutputStream will contain
        /// the rendered file.
        /// <p>
        /// The following methods and properties must be return valid values from
        /// the <paramref name="context"/>:
        /// <ul>
        /// <li>EmbeddedUiResourcePath, must be non-null</li>
        /// <li>FormElementId</li>
        /// <li>GetInputStream</li>
        /// <li>OutputStream</li>
        /// <li>View</li>
        /// </ul>
        /// </p>
        /// <p>
        /// Additionally, if the following properties are set, they will be used:
        /// <ul>
        /// <li>FormElementAction</li>
        /// <li>HiddenControls</li>
        /// <li>ScriptToRender</li>
        /// </ul>
        /// </p>
        /// All other properties on <paramref name="context"/> are ignored.
        /// </remarks>
        /// <exception cref="FileNotFoundException">The requested file attachment can't be found.</exception>
        public override void Render(RloRenderContext context)
        {
            AIResources.Culture = LocalizationManager.GetCurrentCulture();

            // string is the key (which is AssessmentItem.Id_AssessmentItem.Type)
            // int is the ordinal (0 based) which is the number of times the key has been processed
            Dictionary <string, int> assessmentItems = new Dictionary <string, int>();

            // The most common case is that the file is in the package
            Stream inputStream = null;

            AssessmentItemManager.DataModelContext = context;
            LearningDataModel learningDataModel = context.LearningDataModel;

            try
            {
                int srcIndex; // represents the index of the "src" attribute on an <img> node.
                // If this is the first time the page is being rendered, parse the page and determine
                // the interactions on the page.
                if (context.View == SessionView.Execute)
                {
                    if (!GetPageHasBeenVisited(learningDataModel))
                    {
                        using (inputStream = context.GetInputStream())
                        {
                            // If the file being requested is the default file for the current activity,
                            if (context.IsResourceEntryPoint)
                            {
                                // find all the assessment items (<IMG> tags that contain the text "mslamrk" as part of the src attribute.)
                                using (HtmlTextReader reader = new HtmlTextReader(inputStream))
                                {
                                    while (reader.Read())
                                    {
                                        if (IsAITag(reader, out srcIndex))
                                        {
                                            try
                                            {
                                                AssessmentItem         ai       = AssessmentItem.Parse(reader.GetAttributeValue(srcIndex));
                                                AssessmentItemRenderer renderer = AssessmentItemManager.GetRenderer(ai);
                                                renderer.TryAddToDataModel();
                                            }
                                            catch (FormatException)
                                            {
                                                // skip this one.  This is mirrored below in the 2nd pass.
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        SetPageHasBeenVisited(learningDataModel);
                    }
                }

                // must get the input stream again since it may not be possible to seek back to the beginning
                using (inputStream = context.GetInputStream())
                {
                    if (context.Response != null)
                    {
                        // Clear the output response
                        context.Response.Clear();
                    }

                    // If the file being requested is the default file for the current activity,
                    if (context.IsResourceEntryPoint)
                    {
                        if (context.View == SessionView.Execute)
                        {
                            // Set ExitMode to suspend so that when a student exits the activity it is left in a suspended state.
                            // This way if the activity is reactivated, the student's previous answers are intact.
                            learningDataModel.NavigationRequest.ExitMode = ExitMode.Suspended;
                        }

                        DetachableStream detachable = new DetachableStream(context.OutputStream);
                        // Parse through the input stream again, this time rendering into the output as we go.
                        using (StreamWriter writer = new StreamWriter(detachable))
                        {
                            using (HtmlTextReader reader = new HtmlTextReader(inputStream))
                            {
                                while (reader.Read())
                                {
                                    if (IsAITag(reader, out srcIndex))
                                    {
                                        try
                                        {
                                            AssessmentItem         ai       = AssessmentItem.Parse(reader.GetAttributeValue(srcIndex));
                                            AssessmentItemRenderer renderer = AssessmentItemManager.GetRenderer(ai);
                                            if (assessmentItems.ContainsKey(ai.RenderKey))
                                            {
                                                assessmentItems[ai.RenderKey] += 1;
                                            }
                                            else
                                            {
                                                assessmentItems.Add(ai.RenderKey, 0);
                                            }
                                            writer.Write(renderer.Render(assessmentItems[ai.RenderKey]).ToString());
                                        }
                                        catch (FormatException)
                                        {
                                            // skip this one.  This is mirrored above in the 1st pass.
                                        }
                                    }
                                    else
                                    {
                                        HandleNode(reader, writer);
                                    }
                                }
                            }
                            // don't allow closing the StreamWriter to close the context.OutputStream.
                            writer.Flush();
                            detachable.Detach();
                        }

                        // set the response type
                        context.SetOutputStreamExtension(Path.GetExtension(context.RelativePath));
                    }
                    else
                    {
                        // for a non-entry-point file, copy the file directly to the output stream
                        context.WriteFileToResponse(context.RelativePath);
                    }
                }



                return;
            }
            catch (FileNotFoundException)
            {
                // This means the requested file is not in the package. That's not necessarily a problem, since it
                // may be a request for an attachment.
            }

            // We got here because the file is not in the package. In that case, render it if it is a file attachment
            int beginAttachmentInfo = context.RelativePath.IndexOf("/~RLO/", StringComparison.Ordinal);

            if (beginAttachmentInfo != -1)
            {
                // attachmentInfo should be of the form <interactionId>/<attachmentIndex>, so split it into the parts
                string attachmentInfo = context.RelativePath.Substring(beginAttachmentInfo + 6);

                RenderFileAttachment(context, attachmentInfo);
            }
            else
            {
                // This means the requested file is not in the package, nor is it a request for an attachment.
                throw new FileNotFoundException(AIResources.FileNotFound);
            }
        }
Example #6
0
        /// <summary>
        /// Writes the file from a byte array directly to the response. The output stream
        /// extension must be set prior to calling this method.
        /// If the response is provided and the path extension is not
        /// in the list of files to use IIS compatibility mode, this is much faster than 
        /// copying the file contents to the output stream and should be used whenever possible.
        /// If there is no response object, the method reverts to copying the file between streams.
        /// </summary>
        /// <param name="fileBytes">The file to render.</param>
        internal void WriteFileToResponse(byte[] fileBytes)
        {
            using (Disposer disposer = new Disposer())
            {
                // Open a stream on the file. For some odd reason fxcop does not acknowledge the ability of disposer
                // to actually dispose fileStream, so we give it its own using block.
                using (Stream fileStream = new MemoryStream(fileBytes))
                {
                    // If the response was provided (which it will be, in most non-test cases), then 
                    // do the TransmitFile or WriteFile. Otherwise, copy the streams to the response output stream.
                    if (Response != null)
                    {
                        // IisCompatibilityMode is not considered here, because in no case do we have a file 
                        // path that can be read by TransmitFile. 
                        WriteIisCompatibilityModeToResponse(fileStream); 
                    }
                    else
                    {
                        DetachableStream outputDS = new DetachableStream(OutputStream);
                        disposer.Push(outputDS);

                        Utilities.CopyStream(fileStream, ImpersonationBehavior.UseImpersonatedIdentity, outputDS, ImpersonationBehavior.UseImpersonatedIdentity);

                        outputDS.Detach();
                    }
                }
            }
        }
Example #7
0
        /// <summary>
        /// Writes the file from the package directly to the response and set the appropriate 
        /// content type in the response. If the response is provided and the path extension is not
        /// in the list of files to use IIS compatibility mode, this is much faster than 
        /// copying the file contents to the output stream and should be used whenever possible.
        /// If there is no response object, the method reverts to copying the file between streams.
        /// </summary>
        /// <param name="relativePath">The package-relative path to the file to render.</param>
        internal void WriteFileToResponse(string relativePath)
        {
            // Set the mime type on the response
            string pathExtension = Path.GetExtension(relativePath);
            SetOutputStreamExtension(pathExtension);

            using(Disposer disposer = new Disposer())
            {
                PackageReader pkgReader = m_session.GetPackageReader();
                disposer.Push(pkgReader);

                // If the response was provided (which it will be, in most non-test cases), then 
                // do the TransmitFile or WriteFile. Otherwise, copy the streams to the response output stream.
                if (Response != null) 
                {                
                    // If we are to use Compatibility mode, then write the file
                    if (UseCompatibilityMode(pathExtension))
                    {
                        Stream packageFile = pkgReader.GetFileStream(relativePath);
                        WriteIisCompatibilityModeToResponse(packageFile);
                    }
                    else
                    {
                        pkgReader.TransmitFile(relativePath, m_context.Response);
                    }
                }
                else
                {
                    DetachableStream outputDS = new DetachableStream(OutputStream);
                    disposer.Push(outputDS);

                    Stream packageFile = pkgReader.GetFileStream(relativePath);
                    disposer.Push(packageFile);

                    Utilities.CopyStream(packageFile, ImpersonationBehavior.UseImpersonatedIdentity, outputDS, ImpersonationBehavior.UseImpersonatedIdentity);

                    outputDS.Detach();
                }
            }
        }
Example #8
0
        /// <summary>
        /// Render the requested view into the output stream.
        /// </summary>
        /// <param name="context">The context within which to render the page.</param>
        /// <remarks>
        /// When this method returns the <paramref name="context"/> OutputStream will contain 
        /// the rendered file.
        /// <p>
        /// The following methods and properties must be return valid values from 
        /// the <paramref name="context"/>:
        /// <ul>
        /// <li>EmbeddedUiResourcePath, must be non-null</li>
        /// <li>FormElementId</li>
        /// <li>GetInputStream</li>
        /// <li>OutputStream</li>
        /// <li>View</li>
        /// </ul>
        /// </p>
        /// <p>
        /// Additionally, if the following properties are set, they will be used:
        /// <ul>
        /// <li>FormElementAction</li>
        /// <li>HiddenControls</li>
        /// <li>ScriptToRender</li>
        /// </ul>
        /// </p>
        /// All other properties on <paramref name="context"/> are ignored.
        /// </remarks>
        /// <exception cref="FileNotFoundException">The requested file attachment can't be found.</exception>
        public override void Render(RloRenderContext context)
        {
            AIResources.Culture = LocalizationManager.GetCurrentCulture();

            // string is the key (which is AssessmentItem.Id_AssessmentItem.Type)
            // int is the ordinal (0 based) which is the number of times the key has been processed
            Dictionary<string, int> assessmentItems = new Dictionary<string, int>();

            // The most common case is that the file is in the package
            Stream inputStream = null;
            AssessmentItemManager.DataModelContext = context;
            LearningDataModel learningDataModel = context.LearningDataModel;

            try
            {
                int srcIndex; // represents the index of the "src" attribute on an <img> node.
                // If this is the first time the page is being rendered, parse the page and determine 
                // the interactions on the page.
                if (context.View == SessionView.Execute)
                {
                    if (!GetPageHasBeenVisited(learningDataModel))
                    {
                        using (inputStream = context.GetInputStream())
                        {
                            // If the file being requested is the default file for the current activity, 
                            if (context.IsResourceEntryPoint)
                            {
                                // find all the assessment items (<IMG> tags that contain the text "mslamrk" as part of the src attribute.)
                                using (HtmlTextReader reader = new HtmlTextReader(inputStream))
                                {
                                    while (reader.Read())
                                    {
                                        if (IsAITag(reader, out srcIndex))
                                        {
                                            try
                                            {
                                                AssessmentItem ai = AssessmentItem.Parse(reader.GetAttributeValue(srcIndex));
                                                AssessmentItemRenderer renderer = AssessmentItemManager.GetRenderer(ai);
                                                renderer.TryAddToDataModel();
                                            }
                                            catch (FormatException)
                                            {
                                                // skip this one.  This is mirrored below in the 2nd pass.
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        SetPageHasBeenVisited(learningDataModel);
                    }
                }

                // must get the input stream again since it may not be possible to seek back to the beginning
                using (inputStream = context.GetInputStream())
                {
                    if (context.Response != null)
                    {
                        // Clear the output response
                        context.Response.Clear();
                    }

                    // If the file being requested is the default file for the current activity, 
                    if (context.IsResourceEntryPoint)
                    {
                        if (context.View == SessionView.Execute)
                        {
                            // Set ExitMode to suspend so that when a student exits the activity it is left in a suspended state.
                            // This way if the activity is reactivated, the student's previous answers are intact.
                            learningDataModel.NavigationRequest.ExitMode = ExitMode.Suspended;
                        }

                        DetachableStream detachable = new DetachableStream(context.OutputStream);
                        // Parse through the input stream again, this time rendering into the output as we go.
                        using (StreamWriter writer = new StreamWriter(detachable))
                        {
                            using (HtmlTextReader reader = new HtmlTextReader(inputStream))
                            {
                                while (reader.Read())
                                {
                                    if (IsAITag(reader, out srcIndex))
                                    {
                                        try
                                        {
                                            AssessmentItem ai = AssessmentItem.Parse(reader.GetAttributeValue(srcIndex));
                                            AssessmentItemRenderer renderer = AssessmentItemManager.GetRenderer(ai);
                                            if (assessmentItems.ContainsKey(ai.RenderKey))
                                            {
                                                assessmentItems[ai.RenderKey] += 1;
                                            }
                                            else
                                            {
                                                assessmentItems.Add(ai.RenderKey, 0);
                                            }
                                            writer.Write(renderer.Render(assessmentItems[ai.RenderKey]).ToString());
                                        }
                                        catch (FormatException)
                                        {
                                            // skip this one.  This is mirrored above in the 1st pass.
                                        }
                                    }
                                    else
                                    {
                                        HandleNode(reader, writer);
                                    }
                                }
                            }
                            // don't allow closing the StreamWriter to close the context.OutputStream.
                            writer.Flush();
                            detachable.Detach();
                        }

                        // set the response type
                        context.SetOutputStreamExtension(Path.GetExtension(context.RelativePath));
                    }
                    else
                    {
                        // for a non-entry-point file, copy the file directly to the output stream
                        context.WriteFileToResponse(context.RelativePath);
                    }
                }

                

                return;
            }
            catch (FileNotFoundException)
            {
                // This means the requested file is not in the package. That's not necessarily a problem, since it
                // may be a request for an attachment.
            }

            // We got here because the file is not in the package. In that case, render it if it is a file attachment
            int beginAttachmentInfo = context.RelativePath.IndexOf("/~RLO/", StringComparison.Ordinal);
            if (beginAttachmentInfo != -1)
            {
                // attachmentInfo should be of the form <interactionId>/<attachmentIndex>, so split it into the parts
                string attachmentInfo = context.RelativePath.Substring(beginAttachmentInfo + 6);

                RenderFileAttachment(context, attachmentInfo);
            }
            else
            {
                // This means the requested file is not in the package, nor is it a request for an attachment.
                throw new FileNotFoundException(AIResources.FileNotFound);
            }
        }
Example #9
0
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]    // the writer is disposed for all code paths
        internal static void CopyStream(Stream fromStream, ImpersonationBehavior readImpersonationBehavior, Stream toStream, ImpersonationBehavior writeImpersonationBehavior)
        {
            using (Disposer disposer = new Disposer())
            {
                DetachableStream dsToStream = new DetachableStream(toStream);
                disposer.Push(dsToStream);

                BinaryWriter writer = new BinaryWriter(dsToStream);
                disposer.Push(writer);

                // An addition revert during write operations is required if the setting for reading and writing
                // is not the same
                bool requiresWriteRevert = (readImpersonationBehavior != writeImpersonationBehavior);

                using (ImpersonateIdentity readId = new ImpersonateIdentity(readImpersonationBehavior))
                {
                    byte[] bytesIn = new byte[65536];
                    int bytesRead;
                    while ((bytesRead = fromStream.Read(bytesIn, 0, bytesIn.Length)) != 0)
                    {
                        // If we have to impersonate to write, then do it. Otherwise skip it.
                        if (requiresWriteRevert)
                        {
                            using (ImpersonateIdentity id = new ImpersonateIdentity(writeImpersonationBehavior))
                            {
                                writer.Write(bytesIn, 0, bytesRead);
                            }
                        }
                        else
                        {
                            writer.Write(bytesIn, 0, bytesRead);
                        }
                    }
                }
                dsToStream.Detach();
            }
        }