/// <summary>
        /// Called whenever the website loads HTML from disk.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void WebSite_HtmlLoadedFromFile(object sender, TextContentEventArgs args)
        {
            var normalisedPathAndFile = NormaliseFullPath(args.PathAndFile);

            var htmlLocalisers          = _HtmlLocalisers;
            var webAdminViewMap         = _WebAdminViewMapByFullPath;
            var templateMarkerFileNames = _TemplateMarkerFileNames;

            if (htmlLocalisers != null && webAdminViewMap != null && templateMarkerFileNames != null)
            {
                WebAdminView webAdminView;
                if (webAdminViewMap.TryGetValue(normalisedPathAndFile, out webAdminView))
                {
                    foreach (var kvp in templateMarkerFileNames)
                    {
                        args.Content = ExpandTemplateMarkerFromFile(args.Content, kvp.Key, kvp.Value);
                    }

                    IHtmlLocaliser htmlLocaliser;
                    if (webAdminView.StringResources != null && htmlLocalisers.TryGetValue(webAdminView.StringResources, out htmlLocaliser))
                    {
                        args.Content = htmlLocaliser.Html(args.Content, args.Encoding);
                    }
                    args.Content = htmlLocalisers[typeof(WebAdminStrings)].Html(args.Content, args.Encoding);
                    args.Content = htmlLocalisers[typeof(VirtualRadar.Localisation.Strings)].Html(args.Content, args.Encoding);
                    args.Content = htmlLocalisers[typeof(VirtualRadar.WebSite.WebSiteStrings)].Html(args.Content, args.Encoding);

                    _ViewMethodMapper.ViewRequested(webAdminView, args);
                }
            }
        }
Beispiel #2
0
 /// <summary>
 /// Raised when the OWIN file system server is about to serve a text file.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="args"></param>
 private void FileSystemConfiguration_TextLoadedFromFile(object sender, TextContentEventArgs args)
 {
     if (args.MimeType == MimeType.Html)
     {
         OnHtmlLoadedFromFile(args);
     }
 }
Beispiel #3
0
        public void FileSystemServer_TextLoadedFromFile_Raised_For_Supported_Mime_Types()
        {
            foreach (var kvp in new Dictionary <string, string>()
            {
                { ".css", MimeType.Css },
                { ".html", MimeType.Html },
                { ".js", MimeType.Javascript },
                { ".txt", MimeType.Text }
            })
            {
                TestCleanup();
                TestInitialise();

                var extension    = kvp.Key;
                var mimeType     = kvp.Value;
                var errorMessage = $"extension={extension}, mimeType={mimeType}";

                AddSiteRootAndFile(@"c:\web\root", $"Folder/File{extension}", "Hello");
                ConfigureRequest($"/Folder/File{extension}");

                TextContentEventArgs args = null;
                _ServerConfiguration.Setup(r => r.RaiseTextLoadedFromFile(It.IsAny <TextContentEventArgs>())).Callback((TextContentEventArgs e) => {
                    args = e;
                });

                _Pipeline.BuildAndCallMiddleware(_Server.AppFuncBuilder, _Environment.Environment);

                _ServerConfiguration.Verify(r => r.RaiseTextLoadedFromFile(It.IsAny <TextContentEventArgs>()), Times.Once(), errorMessage);
                Assert.AreEqual($"/Folder/File{extension}", args.PathAndFile, errorMessage);
                Assert.AreEqual("Hello", args.Content, errorMessage);
                Assert.AreEqual(Encoding.UTF8.EncodingName, args.Encoding.EncodingName, errorMessage);
                Assert.AreEqual(mimeType, args.MimeType, errorMessage);
            }
        }
Beispiel #4
0
 /// <summary>
 /// Called whenever the web site fetches an HTML file from disk.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 void WebSite_HtmlLoadedFromFile(object sender, TextContentEventArgs e)
 {
     var key = e.PathAndFile.ToLower();
     if(key.StartsWith("/feedfilter/")) {
         e.Content = _HtmlLocaliser.Html(e.Content, e.Encoding);
     }
 }
Beispiel #5
0
        public void WebSite_HtmlLoadedFromFile_Not_Raised_For_Non_HTML_Mime_Types()
        {
            var listener = new EventRecorder <TextContentEventArgs>();

            _WebSite.HtmlLoadedFromFile += listener.Handler;
            _WebSite.AttachSiteToServer(_WebServer.Object);

            var args = new TextContentEventArgs("/index.html", "The Content", Encoding.Unicode, MimeType.Css);

            _FileSystemServerConfiguration.Raise(r => r.TextLoadedFromFile += null, args);

            Assert.AreEqual(0, listener.CallCount);
        }
Beispiel #6
0
        public void FileSystemConfiguration_RaiseTextLoadedFromFile_Raises_TextLoadedFromFile()
        {
            var eventRecorder = new EventRecorder <TextContentEventArgs>();

            _Configuration.TextLoadedFromFile += eventRecorder.Handler;

            var args = new TextContentEventArgs(null, null, null, null);

            _Configuration.RaiseTextLoadedFromFile(args);

            Assert.AreEqual(1, eventRecorder.CallCount);
            Assert.AreSame(_Configuration, eventRecorder.Sender);
            Assert.AreSame(args, eventRecorder.Args);
        }
Beispiel #7
0
        public void FileSystemServer_TextLoadedFromFile_Not_Raised_For_Other_Mime_Types()
        {
            AddSiteRootAndFile(@"c:\web\root", "Folder/File.ts", "Hello");
            ConfigureRequest($"/Folder/File.ts");

            TextContentEventArgs args = null;

            _ServerConfiguration.Setup(r => r.RaiseTextLoadedFromFile(It.IsAny <TextContentEventArgs>())).Callback((TextContentEventArgs e) => {
                args = e;
            });

            _Pipeline.BuildAndCallMiddleware(_Server.AppFuncBuilder, _Environment.Environment);

            _ServerConfiguration.Verify(r => r.RaiseTextLoadedFromFile(It.IsAny <TextContentEventArgs>()), Times.Never());
        }
Beispiel #8
0
        public void WebSite_HtmlLoadedFromFile_Raised_When_OWIN_FileSystemConfiguration_Raises_TextLoadedFromFile()
        {
            var listener = new EventRecorder <TextContentEventArgs>();

            _WebSite.HtmlLoadedFromFile += listener.Handler;
            _WebSite.AttachSiteToServer(_WebServer.Object);

            var args = new TextContentEventArgs("/index.html", "The Content", Encoding.Unicode, MimeType.Html);

            _FileSystemServerConfiguration.Raise(r => r.TextLoadedFromFile += null, args);

            Assert.AreEqual(1, listener.CallCount);
            Assert.AreSame(_WebSite, listener.Sender);
            Assert.AreSame(args, listener.Args);
        }
Beispiel #9
0
        /// <summary>
        /// Records a request for a <see cref="WebAdminView"/>.
        /// </summary>
        /// <param name="webAdminView"></param>
        /// <param name="args"></param>
        public void ViewRequested(WebAdminView webAdminView, TextContentEventArgs args)
        {
            lock (_SyncLock) {
                var pathAndFileWithoutExtension = RemoveExtension(webAdminView.PathAndFile);
                var key             = NormaliseString(pathAndFileWithoutExtension);
                var isMultiInstance = args.Content.Contains(ViewIdMarker);

                if (!isMultiInstance)
                {
                    StartSingleViewInstance(webAdminView, key);
                }
                else
                {
                    var viewId = StartMultiViewInstance(webAdminView, key, args);
                    args.Content = args.Content.Replace(ViewIdMarker, viewId);
                }
            }
        }
Beispiel #10
0
        public void FileSystemServer_TextLoadedFromFile_Reports_Encoding_Correctly()
        {
            var content = "£1.23";
            var bytes   = Encoding.UTF32.GetPreamble().Concat(Encoding.UTF32.GetBytes(content)).ToArray();

            AddSiteRootAndFile(@"c:\web\root", "Folder/File.html", bytes);
            ConfigureRequest("/Folder/File.html");

            TextContentEventArgs args = null;

            _ServerConfiguration.Setup(r => r.RaiseTextLoadedFromFile(It.IsAny <TextContentEventArgs>())).Callback((TextContentEventArgs e) => {
                args = e;
            });

            _Pipeline.BuildAndCallMiddleware(_Server.AppFuncBuilder, _Environment.Environment);

            _ServerConfiguration.Verify(r => r.RaiseTextLoadedFromFile(It.IsAny <TextContentEventArgs>()), Times.Once());
            Assert.AreEqual("/Folder/File.html", args.PathAndFile);
            Assert.AreEqual("£1.23", args.Content);
            Assert.AreEqual(Encoding.UTF32.EncodingName, args.Encoding.EncodingName);
            Assert.AreEqual(MimeType.Html, args.MimeType);
        }
Beispiel #11
0
        /// <summary>
        /// Raises the TextLoadedFromFile event on the singleton configuration object if the mime type indicates
        /// that it's a recognised text file.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="content"></param>
        /// <param name="mimeType"></param>
        /// <returns></returns>
        private byte[] RaiseTextLoadedFromFile(PipelineRequest request, byte[] content, string mimeType)
        {
            if (mimeType == MimeType.Css ||
                mimeType == MimeType.Html ||
                mimeType == MimeType.Javascript ||
                mimeType == MimeType.Text)
            {
                var textContent = TextContent.Load(content);
                var args        = new TextContentEventArgs(
                    request.FlattenedPath,
                    textContent.Content,
                    textContent.Encoding,
                    mimeType
                    );
                _Configuration.RaiseTextLoadedFromFile(args);

                textContent.Content = args.Content;
                content             = textContent.GetBytes(includePreamble: true);
            }

            return(content);
        }
Beispiel #12
0
        private string StartMultiViewInstance(WebAdminView webAdminView, string key, TextContentEventArgs args)
        {
            Dictionary <string, MappedView> runningInstances;

            if (!_MultiViewInstances.TryGetValue(key, out runningInstances))
            {
                runningInstances = new Dictionary <string, MappedView>();
            }

            string viewId;

            do
            {
                viewId = Guid.NewGuid().ToString();
            } while(runningInstances.ContainsKey(viewId));

            MappedView mappedView = CreateView(webAdminView);

            mappedView.ViewId = viewId;

            var newInnerMap = CollectionHelper.ShallowCopy(runningInstances);

            newInnerMap.Add(viewId, mappedView);

            var newOuterMap = CollectionHelper.ShallowCopy(_MultiViewInstances);

            if (newOuterMap.ContainsKey(key))
            {
                newOuterMap[key] = newInnerMap;
            }
            else
            {
                newOuterMap.Add(key, newInnerMap);
            }
            _MultiViewInstances = newOuterMap;

            return(viewId);
        }
Beispiel #13
0
 /// <summary>
 /// Raises <see cref="HtmlLoadedFromFile"/>.
 /// </summary>
 /// <param name="args"></param>
 internal void OnHtmlLoadedFromFile(TextContentEventArgs args)
 {
     EventHelper.RaiseQuickly(HtmlLoadedFromFile, this, args);
 }
Beispiel #14
0
        /// <summary>
        /// See base class docs.
        /// </summary>
        /// <param name="server"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        protected override bool DoHandleRequest(IWebServer server, RequestReceivedEventArgs args)
        {
            var requestFile = GetRequestFile(args.PathParts, args.File);

            var result = requestFile != null && !String.IsNullOrEmpty(requestFile.FileName) && File.Exists(requestFile.FileName);
            if(result) {
                var normalisedRequestPath = NormaliseRequestPath(args.PathAndFile);
                var extension = Path.GetExtension(requestFile.FileName);
                var isProtected = requestFile.Root.IsProtectedContent;

                var checksumEntry = isProtected ? requestFile.Root.FindChecksum(normalisedRequestPath, requestPathIsNormalised: true) : null;
                result = !isProtected || checksumEntry != null;
                if(result) {
                    var isHtml = ".html".Equals(extension, StringComparison.OrdinalIgnoreCase) || ".htm".Equals(extension, StringComparison.OrdinalIgnoreCase);

                    if(isProtected && !requestFile.Root.TestChecksum(checksumEntry, requestFile.FileName)) {
                        Factory.Singleton.Resolve<ILog>().Singleton.WriteLine("Will not serve {0}, it has failed the checksum test", args.PathAndFile);
                        if(!isHtml) {
                            args.Response.StatusCode = HttpStatusCode.BadRequest;
                        } else {
                            Responder.SendText(args.Request, args.Response, "<HTML><HEAD><TITLE>No</TITLE></HEAD><BODY>VRS will not serve content that has been tampered with. Install the custom content plugin if you want to alter the site's files.</BODY></HTML>", Encoding.UTF8, MimeType.Html);
                            args.Classification = ContentClassification.Html;
                        }
                    } else {
                        if(isHtml) {
                            ModifyAndSendContent(args, requestFile.FileName, extension, r => {
                                var textContentArgs = new TextContentEventArgs(args.Request, args.PathAndFile, r.Content, r.Encoding);
                                _WebSite.OnHtmlLoadedFromFile(textContentArgs);
                                r.Content = textContentArgs.Content;

                                _WebSite.InjectHtmlContent(args.PathAndFile, r);
                                _WebSite.BundleHtml(args.PathAndFile, r);
                            });
                        } else if(".js".Equals(extension, StringComparison.OrdinalIgnoreCase)) {
                            ModifyAndSendContent(args, requestFile.FileName, extension, r => {
                                _WebSite.InjectIntoJavaScript(args.PathAndFile, r);
                                _WebSite.MinifyJavaScript(r);
                            });
                        } else if(".css".Equals(extension, StringComparison.OrdinalIgnoreCase)) {
                            ModifyAndSendContent(args, requestFile.FileName, extension, r => {
                                _WebSite.MinifyCss(r);
                            });
                        } else {
                            args.Response.MimeType = MimeType.GetForExtension(extension);

                            var enableCompression = true;
                            if(args.Response.MimeType == MimeType.IconImage) enableCompression = false;
                            else if(args.Response.MimeType.StartsWith("image/")) enableCompression = false;

                            if(enableCompression) args.Response.EnableCompression(args.Request);
                            args.Response.ContentLength = new FileInfo(requestFile.FileName).Length;
                            args.Classification = MimeType.GetContentClassification(args.Response.MimeType);
                            args.Response.StatusCode = HttpStatusCode.OK;
                            using(var fileStream = new FileStream(requestFile.FileName, FileMode.Open, FileAccess.Read)) {
                                StreamHelper.CopyStream(fileStream, args.Response.OutputStream, 4096);
                            }
                        }
                    }
                }
            }

            return result;
        }
 /// <summary>
 /// See interface docs.
 /// </summary>
 /// <param name="args"></param>
 public void RaiseTextLoadedFromFile(TextContentEventArgs args)
 {
     EventHelper.Raise(TextLoadedFromFile, this, () => args);
 }